fn call_docker(args: &[&str], mounts: &[(&str, &str)]) -> Result<()> {
    tracing::info!("Running {} in docker", args[0]);
    let mut cmd = Command::new("docker");
    cmd.args(["run", "--rm"]);
    for (src, dest) in mounts {
        cmd.arg("-v").arg(format!("{}:{}", src, dest));
    }
    cmd.arg(get_docker_image());
    cmd.args(args);
    cmd.stdout(std::process::Stdio::piped());
    cmd.stderr(std::process::Stdio::piped());
    let result = cmd.output()?;
    if !result.status.success() {
        let stderr = String::from_utf8_lossy(&result.stderr);
        let stdout = String::from_utf8_lossy(&result.stdout);
        tracing::error!("Failed to run `docker run`: {:?}", cmd);
        tracing::error!("status: {:?}", result.status);
        tracing::error!("stderr: {:?}", stderr);

        return Err(anyhow!("Docker command failed \n stdout: {:?}\n stderr: {:?}", stdout, stderr));
    }
    Ok(())
}
Calls `docker run` with the given arguments and bind mounts.

Note: files created here by `call_docker` are read-only for after the process exits.
To fix this, manually set the docker user to the current user by supplying a `-u` flag.
crates/recursion/gnark-ffi/src/ffi/docker.rs