opencode-docker is a Docker Compose stack for OpenCode with Oh My OpenAgent pre-configured for Z.AI Coding Plan (GLM-5). Built for practical day-to-day use with strong host separation, reproducible tooling, and persistent configuration.
- Docker Engine with Docker Compose plugin
- Task for the documented local workflows
- Network access for image pulls and Z.AI API calls
- A valid Z.AI Coding Plan API key
-
AI coding assistant:
- OpenCode
- OpenChamber as an optional alternative web UI for OpenCode
- Oh My OpenAgent with GLM-5 model mappings for all agent roles
-
Platform tools:
-
Programming languages/runtimes:
-
Developer tooling:
dockerCLI with Compose plugin,golangci-lint,yq,jq,git,curl
- The container runs non-root via
gosu. - Runtime state is isolated in
./data/. - By default, no Docker socket or host config mounts (
~/.ssh,~/.gitconfig) are exposed. - Default port binding is
127.0.0.1(localhost only).
Warning
Setting OPENCODE_BIND_ADDRESS=0.0.0.0 exposes the port on all interfaces. Always set OPENCODE_SERVER_PASSWORD when doing this.
Docker daemon access is available only through the explicit Docker override documented below. Mounting the Docker socket lets OpenCode control the host Docker daemon and should only be used for trusted local development.
Required API keys:
OCD_ZHIPU_API_KEYfor the default GLM-5 model mappingOCD_GEMINI_API_KEYfor the configuredmultimodal-lookeragent using Gemini vision
Get the required keys:
- Open the Z.AI Open Platform API key page
- Sign in or create an account
- Create a new API key
- Copy the generated key into
.envasOCD_ZHIPU_API_KEY
- Open Google AI Studio
- Sign in with your Google account
- Click Create API Key
- Copy the generated key into
.envasOCD_GEMINI_API_KEY
# 1. Clone the repository
git clone https://github.com/data219/opencode-docker.git
cd opencode-docker
# 2. Copy environment file and set your API key
cp .env.example .env
# Edit .env — set OCD_ZHIPU_API_KEY and OCD_GEMINI_API_KEY
# 3. Build and start
task build
task up
# 4. Open in browser
open http://localhost:4000For CLI/TUI access, exec into the running container:
task opencode -- --helpAll OpenCode state, skills, workspace content, and tool auth/config created in the container persist in ${OPENCODE_HOME_DIR:-./data/home} because the full /home/opencode tree is bind-mounted.
Use the small Taskfile.yml for the normal local entrypoints:
| Task | Purpose |
|---|---|
task config |
Render effective Compose config |
task build |
Build the image with BuildKit |
task up |
Start the stack in the background |
task logs |
Follow the opencode service logs |
task shell |
Open a bash shell in the running container |
task opencode -- ... |
Run opencode inside the running container |
task migrate-env |
Rename legacy .env keys and add missing entries from .env.example |
task test |
Run all Bats suites |
Use the Docker override only when you want OpenCode to start and test other Docker Compose stacks through the host Docker daemon:
docker compose -f docker-compose.yml -f docker-compose.docker.yml up -d
docker compose exec opencode docker version
docker compose exec opencode docker compose versionThis keeps the default stack isolated while making Docker access a deliberate opt-in. Treat this mode as trusted-local only: Docker socket access can create privileged containers and mount host paths.
Use these only when you want to activate additional tooling beyond the default OpenCode web setup.
OpenChamber is installed in the image and can run alongside the default OpenCode web UI. Enable it in .env:
OPENCHAMBER_ENABLED=true
OPENCHAMBER_PORT=4020
OPENCHAMBER_UI_PASSWORD=change-meThen start the stack and open http://localhost:4020.
OPENCHAMBER_PORT is published through the same host bind address as OpenCode. If OPENCODE_BIND_ADDRESS=0.0.0.0, set OPENCHAMBER_UI_PASSWORD before enabling OpenChamber.
Authenticate the bundled CLIs if you want to use them inside the container.
- Env-based auth:
GH_TOKENorGITHUB_TOKEN - Interactive auth:
docker compose exec opencode gh auth login- Env-based auth:
GLAB_TOKENorGITLAB_TOKEN - Interactive auth:
docker compose exec opencode glab auth login- Env-based auth: set all of
CNTB_OAUTH2_CLIENT_ID,CNTB_OAUTH2_CLIENT_SECRET,CNTB_OAUTH2_USER, andCNTB_OAUTH2_PASSWORD - Interactive/manual auth:
docker compose exec opencode cntb config set-credentials- Env-based auth:
ATLCLI_API_TOKEN - Optional profile defaults:
ATLCLI_EMAIL,ATLCLI_SITE,ATLCLI_BASE_URL - Interactive auth:
docker compose exec opencode atlcli auth login --site https://your-company.atlassian.netbootstrap/skills/ is vendored in-repo and synced into the runtime home on container start.
Included categories:
- Platform skills:
github,glab,atlcli,linear - Code review:
code-review-master - Security:
security-threat-model,secrets-management,skeptic - CI/CD:
deployment-pipeline-design,github-actions-templates,gitlab-ci-patterns,enterprise-readiness - Architecture:
error-handling-patterns,context7 - PHP:
php - Incident response:
incident-response
Set FORCE_SKILL_SYNC=true to reset all skills to bootstrap defaults.
Use these variables only when the defaults do not fit your setup.
All env vars are optional except OCD_ZHIPU_API_KEY and OCD_GEMINI_API_KEY.
| Variable | Default | What it configures |
|---|---|---|
OCD_ZHIPU_API_KEY |
(required) | Z.AI Coding Plan API key for GLM-5 models |
OCD_GEMINI_API_KEY |
(required) | Google AI Studio API key for Gemini vision model used by the configured multimodal agent |
OPENCODE_MODE |
web |
Server mode: web (browser UI) or serve (API endpoint) |
OPENCODE_PORT |
4000 |
Server port inside the container (1024–65535) |
OPENCODE_PRINT_LOGS |
false |
Maps to opencode --print-logs and streams OpenCode logs to container stderr |
OPENCODE_LOG_LEVEL |
(empty) | Maps to opencode --log-level with DEBUG, INFO, WARN, or ERROR |
OPENCODE_CORS |
(empty) | Maps to opencode --cors for one additional allowed origin; omitted entirely when empty |
OPENCHAMBER_ENABLED |
false |
Starts the optional OpenChamber web UI alongside OpenCode when set to true |
OPENCHAMBER_PORT |
4020 |
OpenChamber port inside the container and host-published port in Docker Compose |
OPENCHAMBER_UI_PASSWORD |
(empty) | Optional OpenChamber UI password. Set this when exposing the port beyond localhost |
OPENCODE_SERVER_USERNAME |
OpenCode default (opencode) |
Optional basic auth username; empty values are not forwarded |
OPENCODE_SERVER_PASSWORD |
(empty) | Basic auth password. If empty, no auth is enforced — restrict via OPENCODE_BIND_ADDRESS |
OPENCODE_BIND_ADDRESS |
127.0.0.1 |
Host-level only. Which interface Docker listens on. Never passed into the container. |
FORCE_SKILL_SYNC |
false |
true resets all skills to bootstrap defaults on startup; false preserves user modifications |
GH_TOKEN/GITHUB_TOKEN |
(empty) | Token auth for gh. Alternative to interactive gh auth login. |
GLAB_TOKEN/GITLAB_TOKEN |
(empty) | Token auth for glab. Alternative to interactive glab auth login. |
CNTB_OAUTH2_CLIENT_ID |
(empty) | Contabo API OAuth2 client ID for cntb; all CNTB_OAUTH2_* vars must be set together. |
CNTB_OAUTH2_CLIENT_SECRET |
(empty) | Contabo API OAuth2 client secret for cntb. |
CNTB_OAUTH2_USER |
(empty) | Contabo API user for cntb. |
CNTB_OAUTH2_PASSWORD |
(empty) | Contabo API password for cntb. |
GIT_AUTHOR_NAME |
Oh-MyOpenAgent |
Startup default for git author.name (written to git config; not exported as runtime GIT_*). |
GIT_AUTHOR_EMAIL |
noreply@ohmyopencode.ai |
Startup default for git author.email (written to git config; not exported as runtime GIT_*). |
GIT_COMMITTER_NAME |
Oh-MyOpenAgent |
Startup default for git committer.name (written to git config; not exported as runtime GIT_*). |
GIT_COMMITTER_EMAIL |
noreply@ohmyopencode.ai |
Startup default for git committer.email (written to git config; not exported as runtime GIT_*). |
ATLCLI_API_TOKEN |
(empty) | Token auth for atlcli. |
ATLCLI_EMAIL |
(empty) | Default Atlassian account email for atlcli auth flows. |
ATLCLI_SITE |
(empty) | Default Atlassian cloud site for atlcli auth flows. |
ATLCLI_BASE_URL |
(empty) | Base URL override for self-hosted/data-center Atlassian endpoints in atlcli. |
This variable controls the single Docker Compose host mount. If unset, it defaults to ./data/home.
| Variable | Default | What it configures |
|---|---|---|
OPENCODE_HOME_DIR |
./data/home |
Host path mounted to /home/opencode |
The mounted path persists the full /home/opencode tree, including OpenCode config/state, skills, workspace content, and CLI auth/config. All directories are created automatically on first start.
OPENCODE_BIND_ADDRESS controls which host interface Docker exposes. The container always binds 0.0.0.0 internally (required for port forwarding).
127.0.0.1(default) — localhost only, safe for development0.0.0.0— all interfaces, must setOPENCODE_SERVER_PASSWORD
Note: Args after the mode are silently ignored. Use environment variables for all OpenCode configuration.
Logging example:
OPENCODE_PRINT_LOGS=true
OPENCODE_LOG_LEVEL=DEBUG
task up
task logsCORS example:
OPENCODE_CORS=https://opencode.example.com
task upManaged config files (.managed suffix in the image defaults) are overwritten when the config version increases. Non-managed files are only seeded if they don't exist — user edits are always preserved.
When you pull a new image with updated defaults, the entrypoint detects version mismatches and warns you. No user files are silently overwritten.
git pull
task build
task upManaged configs are automatically re-seeded when the image ships a new config version. Your non-managed customizations are preserved.
docker compose down
DOCKER_BUILDKIT=1 docker compose build
docker compose up -dBuild instructions, testing, config seeding internals, and architectural decisions are documented in CONTRIBUTING.md.
GitHub Actions QA is split into two workflows:
Buildruns a directdocker build -t opencode-docker:test .validation of the Dockerfile withoutdocker compose.Testingruns after a successfulBuildworkflow and executestask test-unit,task test-lint, andtask test-integration.
task test-integration boots the Docker Compose stack for real, waits for container health, and verifies the runtime OpenCode/OmO setup inside the container.
MIT