tool-containers
Menu
GitHub (opens in new tab)

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
  • GHCRghcr.io/hambn/codex
  • Docker Hubdocker.io/hambn/codex
Use case
Repeatable local sessions
Upstream
github.com/openai/codex (opens in new tab)
Source
tools/ai/codex/docs/docker-compose (opens in new tab)
On this page

Prerequisites

  • Docker Engine with the Compose v2 plugin.
  • An OpenAI API key in OPENAI_API_KEY.

Run Codex

Shell
export OPENAI_API_KEY=sk-...
WORKSPACE="$PWD" ./compose.sh run --rm codex

Arguments 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:

Shell
docker load -i codex.tar
WORKSPACE="$PWD" ./compose.sh -f airgapped.docker-compose.yml run --rm codex

Variables

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

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: true
compose.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

Topics