I didn't want another tool installed globally on my machine, so I containerized OpenCode.
The result: opencode-dockerized - a Docker Compose setup that runs OpenCode web in a container with the Docker CLI and mounted socket, so it can still manage containers on your host.
Why bother Dockerizing it?
- No global installs or version conflicts on your local machine
- Same environment everywhere, easy to share with a team
- OpenCode config and auth live inside the project, not scattered across
~/.local/share
How it works
The setup is straightforward:
# Build once
make opencode-build
# Run
make opencode-run
# → http://localhost:4096
# Tear down
make opencode-down
The trickier parts are handled automatically:
Docker socket access - The container mounts /var/run/docker.sock so opencode can run Docker commands on the host. The entrypoint detects the socket's GID at runtime and adds the opencode user to that group before dropping privileges. No manual config needed, works on both macOS (Docker Desktop) and Linux.
UID/GID matching - The container runs as a non-root user with your host's UID/GID, detected automatically by the Makefile. Files created inside the container have the right ownership on the host.
Auth persistence - Credentials are written to .opencode/share/auth.json (gitignored). If you're already authenticated locally, you can just copy your existing auth.json in and skip the login flow entirely.
What it does not
This setup does not provide meaningful isolation from the host. Mounting the Docker socket gives the container full access to the host Docker daemon.
Some features for my own convenience (and maybe yours?)
The RPI workflow
The repo ships slash commands that implement a Research → Plan → Implement workflow:
-
/research <task>- explores the codebase, writes a research doc todocs/thoughts/ -
/deep-research <task>- same, but uses Claude Opus for harder problems -
/plan <artifact-folder>- turns the research doc into a numbered implementation plan -
/implement <artifact-folder>- executes the plan step by step and runs a quality gate
Each phase is intentionally scoped: research never touches code, plan never touches code, implement follows the plan exactly.
Create Skills - persistent domain knowledge - via command
Skills are folders under .opencode/skills/<skill-name>/ that the model loads on demand. Each one contains:
-
SKILL.md- reference facts: file paths, data shapes, API shapes, naming rules -
GOTCHAS.md- accumulated failure points and fixes, never deleted -
HISTORY.md- append-only change log, one entry per session -
assets/andscripts/- templates and helper scripts the agent can run
Scaffold a new skill with:
/skill billing-lib "Internal billing library - edge cases, footguns, charge flow"
Domain knowledge accumulates over time in version-controlled files rather than disappearing at the end of a chat session.
Try it!
git clone https://github.com/mazumba/opencode-dockerized
cp compose.override.yml.dist compose.override.yml
# Set your projects path in compose.override.yml
make opencode-build && make opencode-run
Would love feedback, especially if you run it on a setup I haven't tested. PRs and issues welcome!
Top comments (0)