- Container Architecture
- Building the Container Image
- Authentication Setup
- Azure Foundry Provider
- Runtime Behavior
- Working with OpenCode from the Container
- Usage Examples
- Included Tooling and Skills
- Release Model
- Repository Structure
- Development and Validation
- Troubleshooting
A containerized OpenCode CLI environment with bundled runtime tooling, provider integrations, and reusable OpenCode skills. The image ships with sensible defaults so you can start working in local projects quickly while still mounting your own workspace, credentials, and persisted user state from the host.
- Prepared startup flow: The entrypoint loads the container shell environment before launching
opencode - Bun-based image: Uses
oven/bun:latestas the base image and installsopencode-ai - Consistent shell tooling: Uses shell bootstrap and
BASH_ENVso command execution sees the same prepared environment - Curated additions: Bundles Azure Foundry support, memory/context tooling, and reusable skills
Build from the provided Dockerfile:
docker build -t opencode-cli:dev .You can also use the included Makefile:
make buildCustomize the main image component versions and local tag as needed:
docker build \
--build-arg OPENCODE_VERSION=latest \
--build-arg AZURE_FOUNDRY_PROVIDER_VERSION=0.2.0 \
--build-arg ENGRAM_VERSION=v1.9.1 \
-t opencode-cli:dev .With make:
make build IMAGE=opencode-cli TAG=dev OPENCODE_VERSION=latestThe Dockerfile also accepts AZURE_FOUNDRY_PROVIDER_VERSION and ENGRAM_VERSION if you want to
override the bundled provider or memory-tooling version during a direct docker build.
The image includes default OpenCode configuration and helper integrations so it works out of the box, but you should still mount host directories for practical day-to-day use. In most setups, mounting your host home directory lets OpenCode state, credentials, and memory-related data persist across runs.
Typical run pattern:
docker run -it --rm \
-v $HOME:/home/bun \
-v ${PWD}:/work \
opencode-cli:devThis gives the container access to:
/home/bunfor OpenCode config and any persisted credentials/home/bun/.local/share/opencodethrough the home mount for persisted local OpenCode and memory-related state/workfor the project you want OpenCode to read and modify
If your OpenCode setup depends on provider-specific environment variables, keep them in a local env file instead of placing secrets directly on the command line.
install -m 600 /dev/null .env
${EDITOR:-vi} .env
docker run -it --rm \
-v $HOME:/home/bun \
-v ${PWD}:/work \
--env-file .env \
opencode-cli:devSecurity tips:
- Keep
.envfiles out of version control - Restrict permissions to the current user only
- Prefer short-lived credentials where possible
The exact variables depend on the provider configuration you use with OpenCode. This image does
not hardcode credentials, so pass provider settings at runtime with -e or --env-file.
The image also includes default configuration under /etc/opencode, so most users only need to
provide environment variables and volume mounts rather than build up the entire runtime setup from
scratch.
Common patterns include:
- OpenAI-compatible endpoints and API keys
- Azure-related endpoint, deployment, and credential variables
- Any custom variables required by OpenCode providers you enable in your config
Once your configuration is mounted and any required variables are provided, verify that the container starts correctly:
docker run -it --rm \
-v $HOME:/home/bun \
-v ${PWD}:/work \
--env-file .env \
opencode-cli:dev --helpIf your setup is correct, the CLI should start without basic configuration errors. Use a real provider-backed command when you need to verify credentials end to end.
The image builds and installs the azure-foundry-provider package during the Docker build and
places the compiled provider under /usr/local/provider/azure-foundry-provider.
This means the container is prepared for Azure Foundry-oriented OpenCode setups without requiring you to compile the provider on first run. Provider credentials and runtime configuration are still supplied by your OpenCode config and environment variables.
The image also bundles additional helper integrations for memory and large-context workflows, so common local coding setups can start with a useful default baseline.
The container does a small amount of runtime preparation before launching OpenCode:
- It loads the shell environment through the entrypoint before starting the CLI
- It uses
BASH_ENVso non-interactive shell commands inherit the prepared toolchain environment - It enables OpenCode experimental features by default with
OPENCODE_EXPERIMENTAL=1
This helps keep CLI sessions and tool-invoked shell commands consistent inside the container.
For normal usage, mount both your home directory and the current project directory.
docker run -it --rm \
-v $HOME:/home/bun \
-v ${PWD}:/work \
--env-file .env \
opencode-cli:dev [OPENCODE_ARGS]Replace [OPENCODE_ARGS] with the arguments supported by your installed opencode-ai version.
-v $HOME:/home/bun: Persists OpenCode config, credentials, and memory/history data stored under the OpenCode data directory-v ${PWD}:/work: Mounts your current project into the container working directory--env-file .env: Supplies provider credentials and runtime settings without exposing them in shell history--rm: Removes the container after the process exits-it: Provides an interactive terminal for CLI workflows
The container runs in /work, which maps to your current host directory. This means:
- Project files are immediately available to OpenCode
- Files created or edited by OpenCode are written back to your local directory
- Relative paths behave as expected inside the container
Start an interactive OpenCode session in the current project:
docker run -it --rm \
-v $HOME:/home/bun \
-v ${PWD}:/work \
--env-file .env \
opencode-cli:devRun a one-off command such as help or version output:
docker run -it --rm \
-v $HOME:/home/bun \
-v ${PWD}:/work \
--env-file .env \
opencode-cli:dev --versionIf you want to keep project-local settings, create a dedicated env file and reuse it:
install -m 600 /dev/null .env
${EDITOR:-vi} .env
docker run -it --rm \
-v $HOME:/home/bun \
-v ${PWD}:/work \
--env-file .env \
opencode-cli:dev --helpCreate a short alias for daily use:
# Add to your ~/.bashrc or ~/.zshrc
alias opencodec='docker run -it --rm -v $HOME:/home/bun -v ${PWD}:/work --env-file .env opencode-cli:dev'
# Then use simply:
opencodec --help
opencodecThe image currently installs or bundles the following pieces during build:
opencode-aimise- shell bootstrap for interactive and non-interactive command execution
- default OpenCode configuration under
/etc/opencode engramfor persisted memory-oriented workflowsalephtooling for large-context local analysis workflows- local MCP-backed integrations available by default
pythongoripgrepuvgitsudo,curl,gpg,make- Azure Foundry provider build output
- OpenCode skills for
humanizer,aleph, and changelog automation
The repository also includes git-export.py, a helper script that exports a single directory from
a GitHub repository using a treeless, sparse clone workflow.
This repo publishes container images to GitHub Container Registry from version tags.
create-linked-release.ymlchecks the latest matching upstream release on a schedule and creates a local tag when a new one appearsbuild-and-deploy.ymlruns onv*tags, validates semver, and publishes the image toghcr.io/ophiosdev/opencode-cli- Published tags include semver variants, a commit SHA tag, and
latestwhen enabled for the default branch
Dockerfile: Builds the OpenCode container image and installs providers, tools, and skillsentrypoint.sh: Loads shell environment and startsopencodegit-export.py: Sparse GitHub directory export helperMakefile: Convenience targets for local image build and cleanup.github/workflows/: PR validation, release sync, and registry publishing workflows.mise.toml: Local tool definitions for linting and validation utilities
The repo uses pre-commit for lightweight validation of committed files.
Configured checks include:
- General file hygiene checks from
pre-commit-hooks - YAML linting with
yamllint - Dockerfile linting with
hadolint - Markdown linting with
markdownlint-cli2 - GitHub Actions validation with
actionlint - Spelling checks with
typos
The pull request workflow always runs pre-commit checks and also performs a Docker build smoke
test when Dockerfile changes.
- Repeated setup prompts: ensure
-v $HOME:/home/bunis present so config persists - Missing credentials: confirm required provider variables are passed with
-eor--env-file - Startup config failures: run
opencode-cli:dev --helpfirst to confirm the base container starts cleanly - Memory/history not persisting: confirm your
/home/bunmount is present so OpenCode state survives container recreation
- Project files not visible: confirm
-v ${PWD}:/workis included - Output files not appearing locally: check that your command is operating inside
/work - Permission mismatches: inspect ownership on your mounted directories and rebuild or adjust runtime strategy if needed
- Build failures fetching dependencies: verify network access to npm, GitHub, and other upstream sources used in the Docker build
- Provider or skill changes upstream: rebuild the image to refresh fetched components
- Command invocation errors: place OpenCode arguments after the image name and use
--helpto confirm supported flags