Run Codex CLI with Docker Compose
The codex service runs Codex CLI on the directory in WORKSPACE.
compose.sh checks that WORKSPACE is an absolute path, because
Compose would resolve a relative one against this directory, then runs
docker compose here.
- Images
- GHCR
ghcr.io/hambn/codex - Docker Hub
docker.io/hambn/codex
- GHCR
- Use case
- Repeatable local sessions
On this page
Prerequisites
- Docker Engine with the Compose v2 plugin.
- An OpenAI API key in
OPENAI_API_KEY.
Run Codex
export OPENAI_API_KEY=sk-...
WORKSPACE="$PWD" ./compose.sh run --rm codexArguments after the service name go to codex. The interactive session starts at
Codex's sign-in screen with the key detected; choose the API key option. The login is
saved inside the container and removed with it. For codex exec, add
CODEX_API_KEY: ${CODEX_API_KEY} to the service's environment, since exec reads
that variable instead of OPENAI_API_KEY.
Run without registry access
On a connected machine, run docker save ghcr.io/hambn/codex:ubuntu-browser -o codex.tar.
On the offline host, load it and use the air-gapped file, which sets
pull_policy: never:
docker load -i codex.tar
WORKSPACE="$PWD" ./compose.sh -f airgapped.docker-compose.yml run --rm codexVariables
| Variable | Required | Purpose |
|---|---|---|
OPENAI_API_KEY |
yes | Passed to the container and offered at the Codex sign-in screen. |
WORKSPACE |
yes | Absolute host path mounted at /workspace. |
CODEX_IMAGE |
no | Image for both Compose files. Defaults to ghcr.io/hambn/codex:ubuntu-browser; set a digest reference to pin one build. |
Workspace
WORKSPACE is mounted at /workspace. Codex runs as UID 1000, so new files belong to
UID 1000 on the host.
Files
compose.shvalidatesWORKSPACEand passes its arguments todocker compose.docker-compose.ymlruns the published image.airgapped.docker-compose.ymlruns a loaded image and never pulls.
File contents
airgapped.docker-compose.yml14 lines
# Offline: docker load -i codex.tar first, then
# WORKSPACE="$PWD" ./compose.sh -f airgapped.docker-compose.yml run --rm codex
name: codex
services:
codex:
image: ${CODEX_IMAGE:-ghcr.io/hambn/codex:ubuntu-browser}
pull_policy: never
environment:
OPENAI_API_KEY: ${OPENAI_API_KEY:?Set OPENAI_API_KEY}
volumes:
- ${WORKSPACE:?Set WORKSPACE to an absolute host path}:/workspace
stdin_open: true
tty: truecompose.sh18 lines
#!/usr/bin/env bash
# Compose resolves relative paths against this directory, so require an absolute WORKSPACE.
set -euo pipefail
case "${WORKSPACE:-}" in
/*) ;;
"")
echo "Set WORKSPACE to an absolute host path." >&2
exit 2
;;
*)
echo "WORKSPACE must be an absolute host path: $WORKSPACE" >&2
exit 2
;;
esac
cd -- "$(dirname -- "${BASH_SOURCE[0]}")"
exec docker compose "$@"docker-compose.yml12 lines
# WORKSPACE="$PWD" ./compose.sh run --rm codex
name: codex
services:
codex:
image: ${CODEX_IMAGE:-ghcr.io/hambn/codex:ubuntu-browser}
environment:
OPENAI_API_KEY: ${OPENAI_API_KEY:?Set OPENAI_API_KEY}
volumes:
- ${WORKSPACE:?Set WORKSPACE to an absolute host path}:/workspace
stdin_open: true
tty: true