[Feature]: Official multi-arch Docker image and automated build workflow (GHCR / Docker Hub)
Maintainers usually reply within 1 day
Nobody has claimed this yet.
Assessment
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Newbie friendliness
- 55/100
- Issue type
- Feature
- Clarity
- Clearly specified
- Activity status
- Active
- Tech stack
- bun, docker, github-actions, typescript, vite
- Domain
- build-system, devops, release
Research direction
Start with package.json, bun.lock, gui/, and src/cli/index.ts; verify the documented hub command and the /healthz and /readyz endpoints. Then review the proposed Dockerfile and .github/workflows/docker-publish.yml requirements, including non-root runtime, amd64/arm64 builds, caching, and GHCR tags. Done means the image builds, passes smoke checks, and publishes on releases.
Written by the indexing model from the issue text.
Description
Area
Installation or packaging
What are you trying to accomplish?
OpenCodex is widely used not only as a local CLI proxy, but also as a centralized remote hub (on Linux VPS, homelab servers, Docker Compose, and Kubernetes/k3s clusters), following the official Remote Hub Deployment Guide.
Currently, operators who run OpenCodex in containers have to maintain their own external packaging repositories (such as nordz0r/opencodex-docker) with custom scheduled cron workflows to detect new npm/GitHub releases, build the Vite GUI, compile multi-arch images, and push them to container registries.
We would like OpenCodex to provide an official multi-arch container image (linux/amd64 and linux/arm64) published directly to GitHub Container Registry (ghcr.io/lidge-jun/opencodex:<tag> and :latest) upon every release promotion.
What prevents this today?
- No official Dockerfile: The repository currently has no container definition. Users wishing to run OpenCodex under Docker or Kubernetes must write their own Dockerfiles, determining how to correctly build the Vite dashboard (
gui/), pin Bun versions, set environment variables (OPENCODEX_HOME), and configure file permissions. - Duplicated community effort & release lag: Community packaging repositories must poll for npm/GitHub releases with periodic watchdog workflows. This introduces latency between when an upstream release is published and when the container image becomes available, as well as redundant compute across different operators.
- Trust and security: Self-hosters prefer pulling signed or official images from the upstream repository namespace (
ghcr.io/lidge-jun/opencodex) rather than relying on third-party community builds.
What should OpenCodex do?
-
Add a production-ready, security-hardened
Dockerfileat the root of the repository:- Multi-stage build:
- Stage 1 (builder): Installs dependencies with
bun install --frozen-lockfile, builds the Vite dashboard (cd gui && bun install --frozen-lockfile && bun run build), and prunes dev dependencies. - Stage 2 (runtime): Minimal runtime using
oven/bun(pinned by digest), copies only the necessary production artifacts (package.json,bun.lock,node_modules,src/,gui/dist/,bin/), creates a dedicated non-root user (USER bun), and definesVOLUME ["/home/bun/.opencodex"].
- Stage 1 (builder): Installs dependencies with
- Container Healthcheck: Built-in
HEALTHCHECKtestinghttp://127.0.0.1:10100/healthz. - Default Entrypoint / CMD: Starts the hub on default port
10100(bun run src/cli/index.ts start --port 10100).
- Multi-stage build:
-
Add a GitHub Actions workflow (
.github/workflows/docker-publish.yml) that:- Triggers automatically when a release is published (
types: [published]) or viaworkflow_dispatch. - Sets up QEMU and Docker Buildx for multi-architecture builds (
linux/amd64,linux/arm64). - Leverages GitHub Actions cache (
type=gha) for fast builds. - Runs a quick container smoke test on the built image (
/healthzand/readyzreturn 200) prior to publishing. - Publishes tagged images to GHCR (e.g.
ghcr.io/lidge-jun/opencodex:v2.50.0,ghcr.io/lidge-jun/opencodex:2.50.0, andghcr.io/lidge-jun/opencodex:latest).
- Triggers automatically when a release is published (
Example usage or interface
Here is a complete, production-tested implementation that has been used in production across multiple minor and major OpenCodex versions (from v2.40.0 to v2.50.0):
1. Proposed Dockerfile
# syntax=docker/dockerfile:1
ARG BUN_IMAGE=oven/bun:1.4.0@sha256:5ff609364c049b54eb0ff560ec96319729a972078ef2c755d758f0c6ef89c2d6
# Stage 1: Build dashboard and prepare production dependencies
FROM ${BUN_IMAGE} AS build
RUN apt-get update && apt-get install -y --no-install-recommends git ca-certificates && rm -rf /var/lib/apt/lists/*
WORKDIR /home/bun/app
COPY package.json bun.lock ./
RUN --mount=type=cache,target=/home/bun/.bun/install/cache \
bun install --frozen-lockfile
# Build the GUI dashboard (vite)
COPY gui/package.json gui/bun.lock* ./gui/
RUN cd gui && bun install --frozen-lockfile
COPY . .
RUN cd gui && bun run build
# Remove development-only toolchains before runtime stage
RUN rm -rf node_modules/@typescript node_modules/typescript
# Stage 2: Minimal runtime
FROM ${BUN_IMAGE} AS runtime
RUN apt-get update && apt-get upgrade -y && rm -rf /var/lib/apt/lists/*
WORKDIR /home/bun/app
ENV OPENCODEX_HOME=/home/bun/.opencodex \
NODE_ENV=production
COPY --from=build --chown=bun:bun /home/bun/app/package.json ./package.json
COPY --from=build --chown=bun:bun /home/bun/app/bun.lock ./bun.lock
COPY --from=build --chown=bun:bun /home/bun/app/node_modules ./node_modules
COPY --from=build --chown=bun:bun /home/bun/app/src ./src
COPY --from=build --chown=bun:bun /home/bun/app/gui/dist ./gui/dist
COPY --from=build --chown=bun:bun /home/bun/app/bin ./bin
RUN mkdir -p /home/bun/.opencodex && chown -R bun:bun /home/bun
USER bun
VOLUME ["/home/bun/.opencodex"]
EXPOSE 10100
HEALTHCHECK --interval=30s --timeout=5s --start-period=5s --retries=3 \
CMD bun -e "const r=await fetch('http://127.0.0.1:10100/healthz');if(!r.ok)process.exit(1)"
CMD ["bun", "run", "src/cli/index.ts", "start", "--port", "10100"]
2. Proposed GitHub Actions Workflow (.github/workflows/docker-publish.yml)
name: Publish Container Image
on:
release:
types: [published]
workflow_dispatch:
inputs:
tag:
description: 'Tag to build (e.g. v2.50.0)'
required: false
type: string
permissions:
contents: read
packages: write
env:
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}
jobs:
docker:
name: Build & Publish Multi-Arch Image
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Log in to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Extract metadata (tags, labels)
id: meta
uses: docker/metadata-action@v5
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
tags: |
type=semver,pattern={{version}}
type=semver,pattern={{major}}.{{minor}}
type=raw,value=latest,enable=${{ github.event_name == 'release' }}
- name: Build and push image
uses: docker/build-push-action@v5
with:
context: .
file: ./Dockerfile
platforms: linux/amd64,linux/arm64
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=gha
cache-to: type=gha,mode=max
3. User Experience (Docker Compose)
End users and hub administrators can simply run:
services:
opencodex:
image: ghcr.io/lidge-jun/opencodex:latest
container_name: opencodex-hub
restart: unless-stopped
ports:
- "10100:10100"
volumes:
- ./data:/home/bun/.opencodex
Alternatives or workarounds
- Third-party community packaging: Users currently rely on community images like
nordz0r/opencodexfromnordz0r/opencodex-docker. While functional, it requires maintenance outside the core repository and creates an unnecessary third-party trust dependency for end users. - Manual local build / systemd service: Running directly on the host using Node/Bun. This is harder to manage in orchestrated container environments (Kubernetes, Nomad, TrueNAS, unRAID, etc.).
Additional context
- Upstream documentation already emphasizes headless remote hub setups (Remote Hub Deployment). An official container image is the natural companion to this guide.
- The built-in
/healthzand/readyzendpoints make Kubernetes Liveness and Readiness probes straightforward. - Happy to submit this as a Pull Request to
devif maintainers agree with the proposed layout.
Checks
- I searched existing issues and documentation.
- This request describes a concrete OpenCodex workflow rather than merely naming a desired technology.
- I removed secrets and personal data.
- Dominant language
- TypeScript
- Stars
- 16.9k
- Forks
- 1.3k
- Avg merge
- 7h 38m
- Merged PRs (30d)
- 659
Getting set up
This project ships no dev container, Dockerfile or contributing guide, so setting up is up to you: start from its README, and see our first-contribution guide for the general steps.
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from lidge-jun/opencodex
-
account-pool bug
Difficulty 2/5 1-3 hours Newbie friendliness 76/100
lidge-jun/opencodex#7440 · 2 comments ·
Maintainers usually reply within 1 day
-
[Docs]: translate the #7395 OpenGateway and Mistral provider-guide sectionsPossibly taken @MannXo claimed this today. Opendocumentation
Difficulty 2/5 1-3 hours Newbie friendliness 76/100
lidge-jun/opencodex#7405 · 3 comments ·
Maintainers usually reply within 1 day
-
bug cli
Difficulty 2/5 1-3 hours Newbie friendliness 74/100
lidge-jun/opencodex#7403 · 2 comments ·
Maintainers usually reply within 1 day
-
account-pool enhancement needs-design proxy
Difficulty 2/5 1-3 hours Newbie friendliness 85/100
lidge-jun/opencodex#6737 · 1 comment ·
Maintainers usually reply within 1 day
-
enhancement proxy
Difficulty 4/5 1-2 days Newbie friendliness 55/100
lidge-jun/opencodex#7443 · 3 comments ·
Maintainers usually reply within 1 day
All issues in lidge-jun/opencodex
Similar issues
-
area: app type: bug
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
ExpidetGames/code-reviewer#585 ·
Maintainers usually reply within 1 day
-
Difficulty 1/5 Under an hour Newbie friendliness 83/100
module-federation/core#5205 ·
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 73/100
LanternOps/breeze#9392 · 1 comment ·
Maintainers usually reply within 1 day
-
engine-rs P3 review-deferral wasm
Difficulty 2/5 1-3 hours Newbie friendliness 77/100
maniator/verticopolis#1154 ·
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
Maintainers usually reply within 1 day