Repository navigation
[Feature]: Add first-class Docker / Docker Compose deployment support #3449
Description
Area
Installation or packaging
What are you trying to accomplish?
Run OpenCodex as a self-contained containerized proxy/dashboard without installing OpenCodex globally on the host.
The intended deployment shape is:
Codex CLI / Codex App / Claude Code on host or remote clients
↓
localhost / LAN
↓
OpenCodex container (:10100)
↓
configured providers / account pools
OpenCodex already contains meaningful Docker-aware runtime behavior, and users are already running it under Docker, Docker Compose, k3s, and other external supervisors. However, there is no official Dockerfile, Compose example, published container image, or container-specific deployment guide.
Why this is worth making first-class
Existing issues show that Docker is already an intended/real deployment shape rather than an unsupported experiment:
- [Bug] Docker foreground start blocks native requests when systemd ownership is unprovable #1612 — Docker foreground startup was explicitly accepted and fixed; maintainers stated Docker users should run
ocx startdirectly rather than use the service manager. - [Bug][Linux] native-main 503 when systemctl exists but the user bus is unreachable (#1612 regression gap) #2114 — follow-up container/systemd regression handling for Docker/tini foreground environments.
- [Feature]: ChatGPT/Codex login via OpenAI deviceauth (device code) for headless/remote hubs #3366 — current headless/k3s deployment where OAuth onboarding is the remaining friction.
- [Roadmap] Centrally hosted multi-user OpenCodex with tenant isolation #95 — centralized/remote OpenCodex deployment roadmap, including non-loopback binding, authenticated data plane, reverse proxy/TLS, and remote clients.
Today operators have to reconstruct the container contract themselves: which process to run, which directories to persist, which ports to expose, how to handle non-loopback authentication, and which commands must not be used inside a container.
What should OpenCodex do?
Provide a small, supported container deployment surface.
At minimum:
-
Official Dockerfile or published image
- Node 22 base (or another maintainer-selected supported base).
- Run OpenCodex in foreground with
ocx start. - Do not rely on systemd, launchd, Windows Task Scheduler, or
ocx serviceinside the container. - Prefer a non-root runtime user.
- Pin/package the same released OpenCodex version as the image tag.
-
Official
compose.yamlexample- Persistent
OPENCODEX_HOMEvolume. - Port
10100exposed to the host. - Example of host-only publication such as
127.0.0.1:10100:10100. - Clear example for
hostname: "0.0.0.0"inside the container. OPENCODEX_API_AUTH_TOKENhandling for non-loopback binds.- Restart policy managed by Docker/Compose instead of
ocx service.
- Persistent
-
Health/readiness contract
- Docker
HEALTHCHECKexample using/healthzor/readyz. - Document when
/readyzshould be used instead of liveness.
- Docker
-
Persistent data contract
- Document which state belongs under
OPENCODEX_HOMEand should be persisted. - Document optional
CODEX_HOME/ auth mounts when native ChatGPT/Codex credentials are used. - Prefer read-only credential mounts where possible.
- Document which state belongs under
-
OAuth/headless guidance
- Document callback ports required by current OAuth flows.
- Explain host port forwarding where needed.
- Cross-reference [Feature]: ChatGPT/Codex login via OpenAI deviceauth (device code) for headless/remote hubs #3366 for device-code login / headless OpenAI auth when that lands.
-
Container lifecycle guidance
- Explicitly document that
ocx serviceis not used in Docker. - Explicitly document whether
ocx codex-shim installis meaningful only when Codex itself runs in the same container. - Document how upgrades should work: pull/rebuild image + restart, rather than invoking an in-container self-update that mutates the running image.
- Explicitly document that
Example interface
A minimal supported Compose deployment could look approximately like this (exact image/name/config are illustrative):
services:
opencodex:
image: ghcr.io/lidge-jun/opencodex:2.42.0
restart: unless-stopped
ports:
- "127.0.0.1:10100:10100"
environment:
OPENCODEX_HOME: /data
OPENCODEX_API_AUTH_TOKEN: ${OPENCODEX_API_AUTH_TOKEN}
volumes:
- opencodex-data:/data
volumes:
opencodex-data:With container-side config:
{
"port": 10100,
"hostname": "0.0.0.0"
}And a healthcheck along the lines of:
healthcheck:
test: ["CMD", "node", "-e", "fetch('http://127.0.0.1:10100/healthz').then(r=>process.exit(r.ok?0:1)).catch(()=>process.exit(1))"]
interval: 30s
timeout: 5s
retries: 3Alternatives or workarounds
Operators can already build a custom image by installing the npm package into a Node image and running ocx start, or clone the repository and run the Bun entrypoint directly. That works, but every operator has to rediscover the same details:
- foreground-only lifecycle;
- service manager is unsupported/unnecessary in Docker;
- persistent
OPENCODEX_HOME; 0.0.0.0bind + admission token;- OAuth callback routing;
- native Codex auth mounts;
- container-safe upgrade behavior.
The runtime already contains Docker-specific handling, so documenting and packaging that contract would reduce duplicated deployment work and make existing Docker support easier to test continuously.
Scope / non-goals
This request does not require:
- Kubernetes operators or Helm charts;
- multi-tenant isolation ([Roadmap] Centrally hosted multi-user OpenCodex with tenant isolation #95 owns that larger architecture);
- weakening authentication for non-loopback binds;
- running systemd inside the container;
- bundling Codex CLI unless maintainers explicitly want a separate all-in-one image;
- solving every OAuth flow in this issue.
A minimal official image + Compose example + container deployment documentation would already close the main packaging gap.
Acceptance criteria
- An official Dockerfile or published container image exists.
- A documented Compose example persists OpenCodex state.
- The container runs
ocx startdirectly and does not depend on a service manager. - Non-loopback bind/auth requirements are documented and tested.
-
/healthzand/or/readyzare wired into a documented container healthcheck. - Upgrade guidance does not require mutating the running image in place.
- OAuth/headless callback considerations are documented.
- The supported container path has at least one CI smoke test.
Checks
- I searched existing issues and documentation.
- This request builds on existing Docker/runtime support rather than duplicating [Bug] Docker foreground start blocks native requests when systemd ownership is unprovable #1612 or [Bug][Linux] native-main 503 when systemctl exists but the user bus is unreachable (#1612 regression gap) #2114.
- I removed secrets and personal data.
Activity
lidge-jun commentedon Sep 4, 2026
리뷰 · 우선순위 48 / 80
설명
이 이슈는 OpenCodex를 호스트에 전역 설치하지 않고, Docker/Compose로 프록시·대시보드를 띄우는 “공식 컨테이너 계약”을 요구합니다. 지금
devHEAD에는 루트Dockerfile도compose.yaml도 없습니다. 그런데 런타임 쪽에는 이미 Docker를 염두에 둔 동작이 있습니다. #1612에서 Docker 포그라운드 기동이 받아들여졌고, #2114는 컨테이너/tini 환경을 다뤘으며, #3366은 headless/k3s에서 OAuth가 남은 마찰이라고 적혀 있습니다. #95는 원격/중앙 배포의 큰 그림입니다. 즉 “Docker로 돌린다”는 실험이 아니라 이미 있는 배포 형태인데, 이미지·Compose 예시·헬스체크·볼륨·비루프백 인증·업그레이드 안내가 공식으로 정리되지 않은 상태입니다.요청 범위는 작습니다. 공식 Dockerfile 또는 퍼블리시 이미지,
OPENCODEX_HOME유지 볼륨,10100포트, 컨테이너 안hostname: 0.0.0.0,OPENCODEX_API_AUTH_TOKEN,/healthz·/readyz헬스체크,ocx service를 쓰지 말 것, 이미지 안 self-update 금지. K8s/Helm·멀티테넌트·인증 약화는 비목표로 잘 잘랐습니다. 같은 주제의 구현 PR이 이미 열려 있습니다. #3421 “Add Docker Compose deployment support”가 digest-pin Dockerfile, 읽기 전용 루트, non-root, stdin 토큰 부트스트랩, Compose, 문서까지 가져가고 있습니다. 이슈 #3449는 그 PR의 제품 스펙 문서에 가깝고, 중복 요청이라기보다 #3421이 닫아야 할 수용 기준 목록으로 읽는 편이 맞습니다.경로/심볼 - 현재
dev에Dockerfile/compose.yaml없음. 공식 표면이 아직 HEAD에 없다는 이슈 전제가 맞습니다.경로/심볼 - #1612/#2114/#3366/#95와의 연결이 정확합니다. 다만 #95 전체(비루프백 데이터플레인·원격 클라이언트)를 이 이슈 하나로 끌면 범위가 커집니다. 본문이 non-goals로 막은 선을 유지하는 게 좋습니다.
경로/심볼 - #3421이 이미 이미지 퍼블리시 워크플로는 out of scope라고 합니다. 이 이슈 수용 기준의 “published container image”와 “CI smoke”는 #3421만으로 전부 충족되지 않을 수 있습니다. 문서+로컬 빌드 Compose로 1차를 닫고, GHCR 퍼블리시·CI 스모크는 후속 이슈로 쪼개는 판단이 필요합니다.
메인테이너의 판단이 필요한 지점
managementAuthDisabled/disableOriginCheck같은 로컬·리버스프록시 옵션과 컨테이너 가이드 문구를 어떻게 맞출지.너의 추천
이슈는 열어 두되, 본문에 #3421을 구현 PR로 명시하고 중복 구현 PR은 받지 마세요. #3421 리뷰·머지가 우선입니다. GHCR 퍼블리시와 컨테이너 CI 스모크가 #3421 범위 밖이면, merge 후 이 이슈에서 남은 체크만 후속 티켓으로 자르거나 #3449를 partial-close하세요. Preview 배포 계획은 없고, types/config split과도 무관합니다.
이 댓글은 grok-bot이 작성했습니다
lidge-jun commentedon Sep 7, 2026
The remaining source-build container acceptance is now implemented and verified on dev through #3822 and #3823.
The runtime image now declares the existing service lifecycle mode, so Docker-managed stop/recreation preserves routed catalog rows rather than restoring a native desktop catalog. The real CI probe builds the image, checks non-root/read-only operation, readiness and token admission, refuses token replacement, recreates the container, and verifies exact config/token/routed-catalog persistence and scoped cleanup.
Verification: https://github.com/lidge-jun/opencodex/actions/runs/34068218011 — final candidate 6f2ad1e, all 26 jobs successful after a single cancelled macOS shard was rerun unchanged. Merged dev 7fdb0e9 has the exact tree additionally checked against the integration base (129 focused tests passed remotely).
The source-build Dockerfile/Compose route, foreground startup, authentication, health checks, recreate-based upgrades and headless OAuth guidance satisfy this issue's acceptance list. This does not claim a published registry image, every architecture, arbitrary existing mount migration, or every in-app restart path.
Thanks to Buseong Kim for the original #3421 container contribution and Ingwannu for the separate Codex-home persistence work; both are retained as Co-authored-by trailers in the landed commits.