Files
opencode-devbox/DOCKER_HUB.md
T
joakimp c182ada0dd
Publish Docker Image / build-base (push) Successful in 40m32s
Publish Docker Image / build-omos (push) Successful in 50m17s
Publish Docker Image / update-description (push) Successful in 13s
Persist zoxide directory history across container recreations
Zoxide stores its database at ~/.local/share/zoxide/db.zo. Without a
named volume, the 'z <fragment>' jump targets are lost on every
'docker compose up --force-recreate'.

Add devbox-zoxide named volume in docker-compose.yml and
docker-compose.shared.yml, add ~/.local/share/zoxide to the
entrypoint ownership-fix loop per AGENTS.md convention, and update
the data-persistence tables in README.md and DOCKER_HUB.md.
2026-04-23 09:17:39 +02:00

20 KiB

opencode-devbox — Docker Hub

Portable AI developer environment for opencode. Debian-based, with git, SSH, Node.js, AWS CLI v2, and common dev tools pre-installed.

Image Variants

Two image variants are published for each release:

Tag Description
latest / vX.Y.Z Base image — opencode, Node.js, AWS CLI, dev tools
latest-omos / vX.Y.Z-omos Base + oh-my-opencode-slim multi-agent orchestration and Bun

Both variants support linux/amd64 and linux/arm64.

Quick Start

docker run -it --rm \
  -e ANTHROPIC_API_KEY=your-key \
  -e OPENCODE_PROVIDER=anthropic \
  -e GIT_USER_NAME="Your Name" \
  -e GIT_USER_EMAIL="you@example.com" \
  -v ~/projects:/workspace \
  -v ~/.ssh:/home/developer/.ssh:ro \
  joakimp/opencode-devbox:latest

This drops you straight into opencode with your project mounted at /workspace.

Interactive Shell

To get a shell first (useful for AWS SSO login or running other commands):

docker run -it --rm \
  -e ANTHROPIC_API_KEY=your-key \
  -e OPENCODE_PROVIDER=anthropic \
  -v ~/projects:/workspace \
  -v ~/.ssh:/home/developer/.ssh:ro \
  joakimp/opencode-devbox:latest bash

Then run opencode when ready.

Running Multiple Shells

Once opencode is running it takes over the terminal. To have a separate shell for aws, git, or other commands, run the container in the background and attach multiple times:

# Start in background
docker run -d --name devbox \
  -e ANTHROPIC_API_KEY=your-key \
  -e OPENCODE_PROVIDER=anthropic \
  -v ~/projects:/workspace \
  -v ~/.ssh:/home/developer/.ssh:ro \
  joakimp/opencode-devbox:latest sleep infinity

# Shell 1: run opencode
docker exec -it -u developer devbox opencode

# Shell 2 (separate terminal): aws, git, etc.
docker exec -it -u developer devbox bash

# When done
docker rm -f devbox

Note: Always use -u developer with docker exec — the container starts as root for UID adjustment, then drops to developer. Without -u developer, exec runs as root.

Environment Variables

All configuration is done via environment variables, typically stored in a .env file.

Provider Configuration

Variable Description Default
OPENCODE_PROVIDER LLM provider (anthropic, openai, amazon-bedrock) anthropic
OPENCODE_MODEL Model override Provider default

API Keys

Set the key matching your provider:

Variable Provider
ANTHROPIC_API_KEY Anthropic
OPENAI_API_KEY OpenAI
AWS_ACCESS_KEY_ID + AWS_SECRET_ACCESS_KEY AWS Bedrock (static creds)

AWS Bedrock

Variable Description Default
AWS_REGION AWS region us-east-1
AWS_PROFILE AWS SSO profile name default

Git

Variable Description
GIT_USER_NAME Git commit author name
GIT_USER_EMAIL Git commit author email

User ID Mapping

The container runs as user developer (UID 1000 by default). If your host user has a different UID, file permission mismatches can occur on mounted volumes.

The entrypoint automatically detects the owner of /workspace and adjusts the container user's UID/GID to match. You can also set it explicitly:

Variable Description Default
USER_UID Container user UID Auto-detect from /workspace owner
USER_GID Container user GID Auto-detect from /workspace owner

Locale and Editor

The container defaults to English (en_US.UTF-8) and neovim as the editor. Override via environment variables:

Variable Description Default
LANG System locale en_US.UTF-8
LANGUAGE Language priority list en_US:en
LC_ALL Override all locale settings en_US.UTF-8
EDITOR Default text editor nvim

Pre-generated locales: en_US, en_GB, sv_SE, da_DK, nb_NO, fi_FI, de_DE, fr_FR, es_ES, it_IT, pt_BR, nl_NL, pl_PL, ja_JP, ko_KR, zh_CN (all UTF-8).

Example for Swedish:

LANG=sv_SE.UTF-8
LANGUAGE=sv_SE:sv
LC_ALL=sv_SE.UTF-8

To add a locale not in the list, run inside the container:

sudo sed -i '/xx_XX.UTF-8/s/^# //g' /etc/locale.gen
sudo locale-gen

Replace xx_XX with the desired locale (e.g. ru_RU, tr_TR). This change does not persist across container restarts — for permanent additions, build from source and modify the Dockerfile.

Initial Setup

1. Create host directories

Bind-mounted directories must exist on the host before starting the container. Docker creates missing directories as root-owned, which causes permission issues.

# Required
mkdir -p ~/projects

# If mounting opencode config (recommended for persistent settings)
mkdir -p ~/.config/opencode

# If using AWS Bedrock
# mkdir -p ~/.aws

# If mounting neovim config
# mkdir -p ~/.config/nvim

2. Create a .env file

Create a .env file with your configuration. Examples for each provider:

Anthropic:

OPENCODE_PROVIDER=anthropic
ANTHROPIC_API_KEY=sk-ant-...
GIT_USER_NAME=Your Name
GIT_USER_EMAIL=you@example.com

OpenAI:

OPENCODE_PROVIDER=openai
OPENAI_API_KEY=sk-...
GIT_USER_NAME=Your Name
GIT_USER_EMAIL=you@example.com

AWS Bedrock (SSO):

OPENCODE_PROVIDER=amazon-bedrock
OPENCODE_MODEL=amazon-bedrock/eu.anthropic.claude-opus-4-6-v1
AWS_REGION=eu-west-1
AWS_PROFILE=your-profile-name
GIT_USER_NAME=Your Name
GIT_USER_EMAIL=you@example.com

3. AWS SSO setup (Bedrock users only)

AWS SSO requires a ~/.aws/config file on the host with your SSO session configuration. If you already have this on another machine, copy it:

scp -r user@other-machine:~/.aws ~/.aws

Or configure from scratch:

aws configure sso

You'll be prompted for:

  • SSO session name
  • SSO start URL
  • SSO region
  • Registration scopes (typically sso:account:access)

The ~/.aws directory must be mounted into the container (see docker-compose example below).

Data Storage and Persistence

Understanding what survives container restarts and what doesn't:

Path in container Source Survives restart? Contains
/workspace Host bind mount Yes — lives on host Your project files
/home/developer/.ssh Host bind mount (ro) Yes — lives on host SSH keys
/home/developer/.aws Host bind mount Yes — lives on host AWS credentials/SSO cache
/home/developer/.local/share/opencode Named volume (if configured) Yes — Docker volume Session history, memory, auth tokens
/home/developer/.local/state/opencode Named volume (if configured) Yes — Docker volume TUI settings (theme, toggles)
/home/developer/.cache/bash Named volume devbox-shell-history Yes — Docker volume Bash history ($HISTFILE) — survives container recreate
/home/developer/.local/share/zoxide Named volume devbox-zoxide Yes — Docker volume Zoxide directory history (z <fragment> jump targets)
/home/developer/.local/share/uv Named volume (if configured) Yes — Docker volume Python installs, uv tool installs
/home/developer/.rustup Named volume (if configured) Yes — Docker volume Rust toolchains
/home/developer/.cargo Named volume (if configured) Yes — Docker volume Cargo binaries, registry cache
/home/developer/.vscode-server Named volume (if configured) Yes — Docker volume VS Code server and extensions
/home/developer/.config/opencode Host bind mount (if configured) Yes — lives on host opencode.json, skills, plus oh-my-opencode-slim.json on the OMOS variant

Key points

  • Project files (/workspace) are always safe — they're your host filesystem.
  • opencode config is auto-generated from OPENCODE_PROVIDER env var on each start if no existing config is found. To persist config changes, mount the config directory from the host (see Custom opencode Config below).
  • opencode data (session history, memory) is lost on container recreation unless you add a named volume.
  • TUI settings (theme, toggles) are lost on container recreation unless you add the devbox-state named volume.
  • Bash history persists via the devbox-shell-history volume mounted at ~/.cache/bash. HISTFILE is pre-configured; no setup required.
  • Python installs via uv python install are lost on container recreation unless you add the devbox-uv named volume.
  • Rust toolchains via rustup-init are lost on container recreation unless you add the devbox-rustup and devbox-cargo named volumes.
  • AWS SSO tokens persist across restarts when ~/.aws is mounted (recommended for Bedrock users).

Custom opencode Config

For full control over opencode settings (MCP servers, custom models, and — on the OMOS variant — oh-my-opencode-slim agents), mount the entire config directory from the host:

docker run -it --rm \
  -v ~/.config/opencode:/home/developer/.config/opencode \
  ... \
  joakimp/opencode-devbox:latest

This persists all configuration changes across container restarts. When an existing opencode.json is found, the OPENCODE_PROVIDER auto-config is skipped.

Portability note: The mounted config runs inside a Linux container. Any absolute paths inside opencode.json (for example, host-specific plugin entries like file:///usr/local/lib/node_modules/... or file:///opt/homebrew/...) will not resolve inside the container. Prefer bare package specifiers (e.g. "oh-my-opencode-slim") that resolve via node_modules lookup, which works on both macOS and Linux hosts.

Neovim Configuration

The image includes neovim 0.12 with EDITOR=nvim set by default. To use your own neovim config (and have plugins auto-install via lazy.nvim on first start), mount it from the host:

docker run -it --rm \
  -v ~/.config/nvim:/home/developer/.config/nvim:ro \
  ... \
  joakimp/opencode-devbox:latest

Python Development with uv

The image includes Python 3.13 (from Debian Trixie) and uv, a fast Python package manager that replaces pip, venv, and pyenv:

# Python 3.13 is available out of the box
python3 --version

# Use uv for package management
uv venv
uv pip install -r requirements.txt

# Or use uv's project workflow (reads pyproject.toml)
uv sync

# Run a Python script
uv run python script.py

# Install standalone Python tools
uvx ruff check .

# Install a newer Python version (persists with devbox-uv volume)
uv python install 3.14

To persist Python installs across container restarts, add a named volume:

docker run -it --rm \
  -v devbox-uv:/home/developer/.local/share/uv \
  ... \
  joakimp/opencode-devbox:latest

Project virtual environments (.venv) are stored in your workspace directory and persist automatically via the /workspace bind mount.

Rust Development with rustup

The image includes rustup-init, the Rust toolchain installer. Rust is not pre-installed but can be bootstrapped on demand:

# One-time setup: install Rust toolchain (~300MB, persists with volumes)
rustup-init -y
source ~/.cargo/env

# Now use Rust normally
cargo new my-project
cargo build
cargo run

To persist Rust toolchains and cargo data across container restarts, add named volumes:

docker run -it --rm \
  -v devbox-rustup:/home/developer/.rustup \
  -v devbox-cargo:/home/developer/.cargo \
  ... \
  joakimp/opencode-devbox:latest

JavaScript and TypeScript

The base image includes Node.js 22 and npm — sufficient for most JavaScript and TypeScript development:

# Initialize a new project
npm init -y

# Install dependencies
npm install

# Run TypeScript (via tsx, ts-node, etc.)
npx tsx src/index.ts

The OMOS image variant also includes Bun, a faster JavaScript runtime and package manager:

bun init
bun install
bun run src/index.ts

Node modules are stored in your project directory under /workspace and persist automatically.

VS Code Integration

VS Code can connect directly to a running opencode-devbox container for a full IDE experience with IntelliSense, debugging, and extensions running inside the container.

Requirements: Install the Dev Containers extension. For remote Docker hosts, also install Remote - SSH.

Steps:

  1. Start the container: docker compose up -d
  2. In VS Code: Ctrl+Shift+P → "Dev Containers: Attach to Running Container" → select opencode-devbox

For remote Docker hosts (e.g. connecting to a server via SSH), first connect to the remote host with Remote-SSH, then attach to the container from there.

VS Code extensions installed inside the container persist as long as the container exists. For persistent extension storage across container recreations, add a named volume:

docker run -it --rm \
  -v devbox-vscode:/home/developer/.vscode-server \
  ... \
  joakimp/opencode-devbox:latest

Using docker-compose

Create a directory with a docker-compose.yml and a .env file:

mkdir opencode-devbox && cd opencode-devbox

.env — your settings (never commit this):

OPENCODE_PROVIDER=amazon-bedrock
OPENCODE_MODEL=amazon-bedrock/eu.anthropic.claude-opus-4-6-v1
AWS_REGION=eu-west-1
AWS_PROFILE=your-profile-name
GIT_USER_NAME=Your Name
GIT_USER_EMAIL=you@example.com

docker-compose.yml:

services:
  devbox:
    image: joakimp/opencode-devbox:latest
    # For multi-agent orchestration, use the omos variant instead:
    # image: joakimp/opencode-devbox:latest-omos
    container_name: opencode-devbox
    stdin_open: true
    tty: true
    env_file:
      - .env
    environment:
      - TERM=xterm-256color
    volumes:
      - ~/projects:/workspace
      - ~/.ssh:/home/developer/.ssh:ro
      - devbox-data:/home/developer/.local/share/opencode
      - devbox-state:/home/developer/.local/state/opencode
      - devbox-uv:/home/developer/.local/share/uv
      # Optional: persist Rust toolchains and cargo data
      # - devbox-rustup:/home/developer/.rustup
      # - devbox-cargo:/home/developer/.cargo
      # Optional: persist VS Code server and extensions
      # - devbox-vscode:/home/developer/.vscode-server
      # Mount AWS config for Bedrock SSO (required for amazon-bedrock provider)
      # - ~/.aws:/home/developer/.aws
      # Optional: mount opencode config directory (persists config changes across restarts)
      # - ~/.config/opencode:/home/developer/.config/opencode
      # Optional: mount opencode agent skills from host
      # - ~/.agents/skills:/home/developer/.agents/skills:ro
      # Optional: mount neovim config from host (plugins auto-install on first start)
      # - ~/.config/nvim:/home/developer/.config/nvim:ro

volumes:
  devbox-data:
  devbox-state:
  devbox-uv:
  # devbox-rustup:
  # devbox-cargo:
  # devbox-vscode:

Docker Compose loads .env automatically from the same directory. All variables from .env are passed to the container via env_file. Do not hardcode provider settings in the environment: section — use .env instead.

Then:

# Start in background
docker compose up -d

# Open a shell (always use -u developer with exec)
docker compose exec -u developer devbox bash

# For Bedrock: authenticate, then start opencode
aws sso login --sso-session <your-session> --use-device-code
opencode

# Or run opencode directly (if no SSO needed)
docker compose exec -u developer devbox opencode

# One-shot mode (creates and removes container)
docker compose run --rm devbox        # direct to opencode
docker compose run --rm devbox bash   # interactive shell

Shell defaults

The image ships baked .bash_aliases and .inputrc in /etc/skel-devbox/. On first container start the entrypoint copies them to /home/developer/ only if the target file does not already exist, so your host bind-mounts or any in-container customization are preserved across upgrades.

  • Prefix history search on Up/Down arrows (type git , press Up, walk back through prior git ... commands only). Ctrl-Up / Ctrl-Down still step through full history.
  • Persistent history via $HISTFILE=~/.cache/bash/history, backed by the devbox-shell-history named volume. Survives container recreate. 100 000 entries, time-stamped, dedup.
  • Case-insensitive tab completion and coloured completion lists.
  • Aliasesls/ll/laeza, catbat, gs/gd/gl for git, interactive rm/mv/cp.
  • Integrationszoxide (z <fragment>), fzf key bindings (Ctrl-R, Ctrl-T).
  • [devbox] prompt prefix so you always know you're in the container.

To override with your host's own files, uncomment the matching bind-mount lines in docker-compose.yml. To restore the baked defaults any time: cp /etc/skel-devbox/.bash_aliases ~/ (or delete the file and recreate the container).

What's Included

Base image (latest)

  • Debian trixie-slim — glibc, full terminal/PTY support
  • opencode — AI coding assistant
  • Node.js 22 — for npx-based MCP servers
  • AWS CLI v2 — SSO and Bedrock authentication
  • Dev tools — git, git-lfs, git-crypt, age, ssh, ripgrep, fd, fzf, bat, eza, zoxide, uv, rustup, jq, make, gcc, g++, curl, wget, neovim 0.12, tmux, htop, tree, rsync
  • Non-root user — runs as developer with UID auto-matched to workspace owner (sudo available)

OMOS image (latest-omos)

Everything in the base image, plus:

  • oh-my-opencode-slim — multi-agent orchestration plugin
  • Bun — JavaScript runtime required by oh-my-opencode-slim
  • 6 specialized agents — Orchestrator, Explorer, Oracle, Librarian, Designer, Fixer

Additional runtimes (build from source)

When building from source, additional runtimes are available via build args:

  • Python 3 (INSTALL_PYTHON=true) — Python 3 + pip + venv
  • Go (INSTALL_GO=true) — Go toolchain

oh-my-opencode-slim (OMOS variant)

The -omos image variant includes oh-my-opencode-slim, which adds a multi-agent layer on top of opencode. An Orchestrator delegates tasks to specialized agents, each configurable with different models and providers.

Quick start with OMOS

docker run -it --rm \
  -e OPENAI_API_KEY=your-key \
  -e OPENCODE_PROVIDER=openai \
  -e ENABLE_OMOS=true \
  -v ~/projects:/workspace \
  -v ~/.ssh:/home/developer/.ssh:ro \
  joakimp/opencode-devbox:latest-omos

On first start, the entrypoint configures oh-my-opencode-slim automatically. The default preset uses OpenAI models.

OMOS environment variables

Variable Default Description
ENABLE_OMOS false Activate oh-my-opencode-slim on container start
OMOS_TMUX false Enable tmux pane integration (watch agents in split panes)
OMOS_SKILLS true Install recommended skills (simplify, agent-browser, cartography)
OMOS_RESET false Force regenerate config on next start (backs up existing config)

Custom OMOS configuration

If you mount the opencode config directory (see Custom opencode Config above), the oh-my-opencode-slim.json file is included and persists across restarts. Edit it directly to control which models power each agent, fallback chains, council setup, and more.

See the oh-my-opencode-slim configuration docs for the full reference.

Verifying agents

After starting opencode with OMOS enabled, run inside the opencode session:

ping all agents

All six agents should respond if your provider authentication is working.

Multi-User Setup

This guide covers single-user setup. For running multiple opencode-devbox instances in parallel — whether each user has their own OS account or everyone shares one login — see the Multi-user setup section in the source repository. It covers volume isolation, the docker-compose.shared.yml layout, and the SIGNUM / $USER auto-detection mechanism.

Source

Build from source or contribute: opencode-devbox on Gitea