Third-party community image. This is an unofficial, community-maintained Docker image of opencode. It is not affiliated with or endorsed by the opencode project.
A minimal Docker image that runs opencode with its built-in web UI (opencode web), usable directly with Docker or inside a MicroSandbox microVM.
The image is published to GHCR by CI: ghcr.io/ctxinf/opencode-image
Quick throwaway run:
docker run --rm -p 7777:7777 ghcr.io/ctxinf/opencode-image:latestOpen http://localhost:7777.
For a persistent deployment use compose (docker/docker-compose.yml):
services:
opencode:
image: ghcr.io/ctxinf/opencode-image:latest
container_name: opencode
ports:
- "7777:7777"
environment:
# Without a password opencode logs "server is unsecured" and the web UI
# is open to anyone who can reach the port. Set it for any real deployment.
- OPENCODE_SERVER_PASSWORD=${OPENCODE_SERVER_PASSWORD:-}
# Initial workspace dir; created and git-inited on start if missing
- OPENCODE_WORKDIR=${OPENCODE_WORKDIR:-/workspace}
volumes:
- opencode-config:/root/.config/opencode
- opencode-data:/root/.local/share/opencode
- workspace:/workspace
restart: unless-stopped
volumes:
opencode-config:
opencode-data:
workspace:cd docker
OPENCODE_SERVER_PASSWORD=change-me docker compose up -dThe three named volumes persist across restarts:
| Volume | Mount | Purpose |
|---|---|---|
opencode-config |
/root/.config/opencode |
opencode config (seeded from the image) |
opencode-data |
/root/.local/share/opencode |
sessions / auth / state |
workspace |
/workspace |
your project files |
The baked-in config (docker/config/opencode.jsonc) disables sharing, auto-update, LSP and telemetry. API keys are entered in the web UI, not baked into the image.
Runtime env vars:
| Var | Default | Purpose |
|---|---|---|
OPENCODE_SERVER_PASSWORD |
(unset — unsecured!) | web UI password |
OPENCODE_WORKDIR |
/workspace |
initial project dir, e.g. -e OPENCODE_WORKDIR=/workspace/app1 |
The image runs under tini, so Ctrl+C on a foreground docker run stops the container cleanly.
Note: named volumes are seeded from the image only on first creation and keep session history across image upgrades. If the web UI opens an unexpected project dir, it is replaying old sessions from the
opencode-datavolume — remove it (docker compose down && docker volume rm docker_opencode-data) for a fresh start.
example/microsandbox-run.ts starts the GHCR image in a microVM like docker run --rm — the sandbox lives as long as the script:
npm install
npm run sandbox # -> http://localhost:17777
npm run sandbox -- 18000 # custom host portOverride the image with OPENCODE_IMAGE=... if needed.
Only needed if you want to change the image itself:
cd docker
docker build -t opencode-image:latest .
# pin a different opencode version:
docker build --build-arg OPENCODE_VERSION=1.15.12 -t opencode-image:latest .The Dockerfile downloads the opencode release tarball at build time — no binaries are checked into the repo.
- docker-image.yml — on tag push
v*or manual dispatch: builds and pushesghcr.io/ctxinf/opencode-imagewithlatest, semver, and commit-SHA tags. A tagvX.Y.Zbuilds opencodeX.Y.Zand records it in the image description. - track-upstream.yml — twice a month (1st/15th): builds the latest anomalyco/opencode release and pushes it as
latest+<version>, skipping versions already published. - check.yml — type-checks the TypeScript examples with the TypeScript 7 preview (
tsgo --noEmit).
docker/
Dockerfile # debian:bookworm + opencode binary, CMD = opencode web
docker-compose.yml # persistent deployment with named volumes
config/opencode.jsonc # default opencode config baked into the image
example/
microsandbox-run.ts # minimal MicroSandbox launcher
.github/workflows/ # GHCR image publish + type check