Dockerfiles and a guide for running OpenCode in Docker containers, with or without NVIDIA GPU support, on Ubuntu or macOS.
These instructions have been tested but are provided as-is. Review each command before running it and back up any important data.
Coding agents are useful, but I won't give them full access to my machine. I wanted to use OpenCode without giving up privacy or control, so I looked for a way to run it inside Docker.
I first tried Docker Sandboxes, but they use microVMs that don't support GPU passthrough, and I need the GPU. They're also still experimental.
So I built this. It's a thin wrapper around Docker's official docker/sandbox-templates:opencode image. It's small, easy to read, and easy to extend. I can bake in whatever tools a project needs so OpenCode can run them itself to verify its work. For a project that builds LaTeX documents, that means a full LaTeX toolchain, letting the agent compile, read the errors, and fix them on its own. Docker keeps the base image updated, so I don't have to.
Switching to a different coding agent is easy. Docker ships the same kind of image for other agents like Claude Code, Codex, and Gemini CLI. To try one, copy a Dockerfile in dockerfiles/, change the FROM line, and rebuild. The rest stays the same.
| Your setup | Start here |
|---|---|
| Ubuntu + NVIDIA GPU | Sections 2-4, then Section 5 (Section 1 optional) |
| Ubuntu, no GPU | Sections 2-3, then Section 5 (Section 1 optional) |
| macOS | Section 5 directly |
- Purge Any Existing Docker Installation (Optional)
- Install Docker Engine
- Docker Post-Installation Setup
- Install and Configure the NVIDIA Container Toolkit
- Running OpenCode in a Docker Container
Prerequisites (Sections 1-4, and Section 5 GPU variant):
- Ubuntu 24.04 LTS (Noble Numbat), 64-bit (amd64/arm64)
- An NVIDIA GPU with Kepler architecture or newer (compute capability ≥ 3.0)
- NVIDIA GPU drivers installed and working on the host (verify with
nvidia-smi) - Root or sudo access
Click to expand. Skip this section if you don't already have Docker installed or don't need a clean slate. It removes all conflicting or leftover packages and data before installing Docker cleanly.
Source: docs.docker.com/engine/install/ubuntu - "Uninstall old versions" and "Uninstall Docker Engine"
Remove unofficial packages that may conflict, then purge any prior official Docker CE installation:
sudo apt remove $(dpkg --get-selections docker.io docker-compose docker-compose-v2 docker-doc podman-docker containerd runc 2>/dev/null | cut -f1) 2>/dev/null
sudo apt purge docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin docker-ce-rootless-extrasBoth commands are safe to run even if the packages aren't installed:
- The first removes unofficial packages that may conflict.
- The second uses
purgeto also delete configuration files from any prior official installation.
Docker stores images, containers, volumes, and network data under /var/lib/docker and /var/lib/containerd. These are not removed by apt purge:
sudo rm -rf /var/lib/docker
sudo rm -rf /var/lib/containerd
sudo rm -f /etc/apt/sources.list.d/docker.sources
sudo rm -f /etc/apt/sources.list.d/docker.list
sudo rm -f /etc/apt/keyrings/docker.asc
sudo rm -f /etc/apt/keyrings/docker.gpgWarning: this permanently destroys all Docker images, containers, volumes, and networks on this host. Only do this if you want a clean slate.
Source: docs.docker.com/engine/install/ubuntu - "Install using the apt repository"
sudo apt-get update
sudo apt-get install -y ca-certificates curlThese allow fetching packages over HTTPS and downloading GPG keys.
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.ascThis downloads Docker's GPG signing key to /etc/apt/keyrings/, the standard location for third-party signing keys on Debian-based systems. The chmod a+r makes it readable by all users.
sudo tee /etc/apt/sources.list.d/docker.sources <<EOF
Types: deb
URIs: https://download.docker.com/linux/ubuntu
Suites: $(. /etc/os-release && echo "${UBUNTU_CODENAME:-$VERSION_CODENAME}")
Components: stable
Signed-By: /etc/apt/keyrings/docker.asc
EOFThis creates a DEB822-format sources file pointing to Docker's official repository for your Ubuntu release (Noble for 24.04). The Signed-By field ties the repo to the GPG key you just downloaded.
sudo apt-get update
sudo apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-pluginOn Ubuntu 24.04, Docker starts automatically after installation. Confirm it's running and pull a test image:
sudo systemctl status dockerIf the output shows Active: active (running), the engine is working. Step 3.3 runs a full end-to-end verification.
Source: docs.docker.com/engine/install/linux-postinstall
By default, the Docker daemon socket is owned by root and the docker group. To run docker commands without sudo, add your user to that group:
sudo groupadd docker 2>/dev/null # Create the group (may already exist)
sudo usermod -aG docker $USERYou must log out and log back in for the group change to take effect. Alternatively, run newgrp docker in your current shell.
The docker group grants root-equivalent privileges on the host. Only add trusted users.
On a VM, a full reboot may replace the logout step.
On Ubuntu 24.04 the Docker service is enabled at boot by default. To make sure (or set it explicitly):
sudo systemctl enable docker.service
sudo systemctl enable containerd.serviceThis configures systemd to start both the Docker daemon and containerd automatically on every boot.
docker run hello-worldIf this succeeds without sudo, post-installation is complete. If you get a permission denied error, confirm you logged out and back in (or rebooted) after Step 3.1.
Source: docs.nvidia.com/datacenter/cloud-native/container-toolkit/latest/install-guide.html
sudo apt-get update && sudo apt-get install -y --no-install-recommends gnupg2ca-certificates and curl were already installed in Step 2.1.
curl -fsSL https://nvidia.github.io/libnvidia-container/gpgkey \
| sudo gpg --dearmor -o /usr/share/keyrings/nvidia-container-toolkit-keyring.gpg
curl -s -L https://nvidia.github.io/libnvidia-container/stable/deb/nvidia-container-toolkit.list \
| sed 's#deb https://#deb [signed-by=/usr/share/keyrings/nvidia-container-toolkit-keyring.gpg] https://#g' \
| sudo tee /etc/apt/sources.list.d/nvidia-container-toolkit.list- The first command downloads NVIDIA's GPG key and converts it to the binary format apt expects.
- The second downloads the repository list and adds the
signed-bydirective so apt trusts packages from this repo.
sudo apt-get update
sudo apt-get install -y nvidia-container-toolkitThe official docs show pinning to a specific version (e.g., nvidia-container-toolkit=1.18.2-1). Pin explicitly if you need reproducible deployments, otherwise the unpinned install above is simpler.
Run nvidia-ctk to register the NVIDIA runtime with Docker and set it as the default:
sudo nvidia-ctk runtime configure --runtime=docker --set-as-defaultThis edits /etc/docker/daemon.json to register the nvidia runtime and set "default-runtime": "nvidia". All containers then use the NVIDIA runtime automatically. You can drop --gpus and --runtime=nvidia from every docker run command.
Source: NVIDIA Container Toolkit Install Guide and NVIDIA Container Toolkit User Guide (--set-as-default flag)
Verify the result:
cat /etc/docker/daemon.jsonExpected output
{
"default-runtime": "nvidia",
"runtimes": {
"nvidia": {
"args": [],
"path": "nvidia-container-runtime"
}
}
}Restart Docker to apply the new configuration:
sudo systemctl restart dockerSource: docs.nvidia.com/datacenter/cloud-native/container-toolkit/latest/sample-workload.html
docker run --rm nvidia/cuda:13.2.0-base-ubuntu24.04 nvidia-smiYou should see output listing your GPU(s), driver version, and CUDA version, matching (or compatible with) the host driver.
Notes on the command and image tag
This pulls NVIDIA's official CUDA base image and runs nvidia-smi inside the container. If the command fails, try adding --gpus all explicitly to rule out a default-runtime configuration issue.
Replace 13.2.0-base-ubuntu24.04 with a tag matching your driver's supported CUDA version. Check your host CUDA version with nvidia-smi and browse available tags at hub.docker.com/r/nvidia/cuda.
GPU variants are in collapsible sections you can skip. The setup follows the Docker custom templates documentation and OpenCode documentation.
If you're on Ubuntu, you already installed Docker in Sections 1-3. Skip to Step 5.2.
macOS: install Docker Desktop via Homebrew:
brew install --cask docker-desktopOpen Docker Desktop from your Applications folder or Spotlight (Cmd + Space, type "Docker") and follow the prompts. Wait for the whale icon in your menu bar.
Source: docs.docker.com/desktop/setup/install/mac-install
Verify Docker is running:
docker --versionFrom the repo root:
docker build -t opencode-nogpu -f dockerfiles/Dockerfile.opencode dockerfiles/Rebuild only if you change the Dockerfile or want updated base images. Add --pull to fetch the latest base image and pick up security patches.
GPU variant and project-specific extras
GPU build
docker build -t opencode-gpu \
--build-arg NVIDIA_VISIBLE_DEVICES=all \
--build-arg NVIDIA_DRIVER_CAPABILITIES=compute,utility \
-f dockerfiles/Dockerfile.opencode dockerfiles/In Step 5.3, use opencode-gpu instead of opencode-nogpu.
Project-specific extras
Add a derived Dockerfile that layers tools on top of the base image. The repository includes two examples:
-
dockerfiles/Dockerfile.opencode-latex, which installstexlive-fullandlatexmk:docker build -t opencode-latex \ -f dockerfiles/Dockerfile.opencode-latex dockerfiles/
To layer on the GPU base instead, pass --build-arg BASE_IMAGE=opencode-gpu. texlive-full is several gigabytes, so the first build of the LaTeX image will take a while.
In Step 5.3, replace opencode-nogpu with your derived image name (e.g. opencode-latex). Additional derived images (Dockerfile.opencode-rust, etc.) follow the same pattern.
Each project gets its own container, named after its directory (e.g. my-project-opencode).
First, make sure OpenCode's config folder exists on the host (one-time, safe to re-run):
mkdir -p ~/.config/opencodeThen create the container from your project directory:
# Navigate to your project directory first, e.g.:
# cd ~/my-project
workspace="$(pwd -P)"
cname="my-project-opencode" # Edit to your preferred container name
docker run -it \
--name "${cname}" \
--mount type=bind,src="${workspace}",dst=/workspace \
--mount type=bind,src="$HOME/.config/opencode",dst=/home/agent/.config/opencode \
opencode-nogpuNotes
Note: If two projects share a directory name, set
cnamemanually to avoid a conflict (e.g.cname="my-project-2-opencode").
Note: If you use PyTorch's
DataLoaderwithnum_workers > 0, add--shm-size=8gto thedocker runcommand. Docker's default 64 MB shared-memory limit causes "No space left on device" errors at runtime.
GPU variant. Click to expand.
# Navigate to your project directory first, e.g.:
# cd ~/my-project
workspace="$(pwd -P)"
cname="my-project-opencode" # Edit to your preferred container name
docker run -it --gpus all \
--name "${cname}" \
--mount type=bind,src="${workspace}",dst=/workspace \
--mount type=bind,src="$HOME/.config/opencode",dst=/home/agent/.config/opencode \
opencode-gpuTo verify GPU access, run nvidia-smi inside the container.
The --mount flags share your project directory and OpenCode config folder with the container.
Inside the container, launch OpenCode:
opencodeOpenCode starts in /workspace, reading API keys, provider credentials, and terminal UI settings from the mounted ~/.config/opencode folder. See the OpenCode documentation for full config details.
After the first run, always use start to resume — this preserves installed packages and configuration:
docker start -ai my-project-opencodeSubstitute your container name. You can run this from any directory.
When you're done, exit with exit or Ctrl+D. The container stops automatically.
Stopping and removing:
docker stop my-project-opencode # stop a running container
docker rm my-project-opencode # remove it entirelyYour OpenCode config files (~/.config/opencode/opencode.json and ~/.config/opencode/tui.json) live on the host and survive container removal. Packages installed inside the container are lost.
Other useful commands:
docker ps # list running containers
docker ps -a # include stopped containers
docker exec -it my-project-opencode /bin/bash # open a second terminal in a running containerNote:
docker start -aionly works on a stopped container. If it's already running, usedocker execinstead.
Created by Yanzhe Bekkemoen, with assistance from Claude by Anthropic.
Contributions are welcome. Feel free to open an issue or pull request.
This project is licensed under the MIT License.