Files
Jon Chery de8fdc0fe4 feat(P03): docker release — multi-stage Dockerfile + Gitea container registry publish
REQ-046: Docker image published to Gitea container registry per release.

Dockerfile: multi-stage (golang:1.25 -> distroless/static-debian12:nonroot).
  CGO_ENABLED=0, ORCA_HOME=/var/lib/orca, ENTRYPOINT [/orca].
  Image size: ~28MB. Runs as nonroot.

.coreci.yml: new container-publish step in release pipeline (docker:24-cli,
  builds + tags + login + push + logout).

scripts/release.sh: docker build + push after Gitea release. Graceful
  skip if docker absent or GITEA_TOKEN unset. Env-overridable registry.

.dockerignore: excludes .git, bin/, .env, .ciagent/, testdata/, *.tar.gz.

docs/docker.md: pull, run, state persistence (volume mount), local build,
  manual publish guide.

Verified: docker build + run version/init with volume persistence.

---ci---
project: orca
phase: 3
milestone: v0.5
status: verify
---/ci---
2026-08-03 18:52:36 +00:00

2.9 KiB

Docker Guide

Orca is available as a container image on the Gitea container registry. The image is a minimal distroless static build (~2MB runtime layer) that runs the orca binary directly.

Image

git.cloudinit.dev/coreci/orca:<version>
git.cloudinit.dev/coreci/orca:latest

The image is built from the Dockerfile in the repo root:

  • Build stage: golang:1.25 — compiles a static binary with CGO_ENABLED=0 (modernc/sqlite is pure Go, no CGO).
  • Runtime stage: gcr.io/distroless/static-debian12:nonroot — ~2MB, no shell, runs as nonroot user.

Pull

docker pull git.cloudinit.dev/coreci/orca:latest
# or pin a version
docker pull git.cloudinit.dev/coreci/orca:v0.4.4

The repo is public (REQ-045), so anonymous pull works without login.

Run

# Print version
docker run --rm git.cloudinit.dev/coreci/orca:v0.4.4 version

# Initialize state (creates /var/lib/orca/ inside the container)
docker run --rm -v orca-data:/var/lib/orca git.cloudinit.dev/coreci/orca:v0.4.4 init

# Run the daemon (persist state via volume)
docker run -d --name orca \
  -p 8080:8080 \
  -v orca-data:/var/lib/orca \
  git.cloudinit.dev/coreci/orca:v0.4.4 daemon --addr=:8080

State Persistence

The image sets ENV ORCA_HOME=/var/lib/orca. All orca state (SQLite database, CA certs, server certs) is written under this path. To persist state across container restarts, mount a volume:

docker volume create orca-data
docker run --rm -v orca-data:/var/lib/orca git.cloudinit.dev/coreci/orca:v0.4.4 init
docker run -d --name orca -p 8080:8080 -v orca-data:/var/lib/orca git.cloudinit.dev/coreci/orca:v0.4.4 daemon

Without a volume, state is lost when the container exits.

System-Level Namespace Inside Containers

The --system flag is not needed inside containers — the image already sets ORCA_HOME=/var/lib/orca. Use --system only if you want a different namespace root (e.g., /root/.orca), which requires running as root (the distroless image runs as nonroot by default).

Build Locally

docker build --build-arg VERSION=v0.4.4 -t orca-local:v0.4.4 .
docker run --rm orca-local:v0.4.4 version

Build args:

  • VERSION — semver tag (injected via -ldflags)
  • GIT_COMMIT — short commit hash
  • BUILD_TIME — ISO 8601 build timestamp

Publish (for maintainers)

The .coreci.yml release pipeline includes a container-publish step that builds and pushes the image on every tag release. To publish manually:

export GITEA_TOKEN=<token>
docker build --build-arg VERSION=v0.4.4 -t git.cloudinit.dev/coreci/orca:v0.4.4 -t git.cloudinit.dev/coreci/orca:latest .
echo "$GITEA_TOKEN" | docker login git.cloudinit.dev -u cloudinit-bot --password-stdin
docker push git.cloudinit.dev/coreci/orca:v0.4.4
docker push git.cloudinit.dev/coreci/orca:latest

See Also