# Phase 3 Verification: Docker Release (v0.5 P3) **Phase**: 3 (docker release) **Milestone**: v0.5 Distribution **Requirements covered**: REQ-046 **Date**: 2026-08-03 ## Structural Layer - `go vet ./...` → clean. - `go build ./...` → succeeds. - New files: `Dockerfile`, `.dockerignore`, `docs/docker.md`. - Modified files: `.coreci.yml` (container-publish step), `scripts/release.sh` (docker publish). - `.dockerignore` excludes `.git`, `bin/`, `.env`, `.ciagent/`, `testdata/`, `*.tar.gz`. ## Behavioral Layer ### Docker build - `docker build --build-arg VERSION=v0.4.4-test ... -t orca-test:v0.4.4 .` → succeeds. - Multi-stage build: `golang:1.25` (builder) → `gcr.io/distroless/static-debian12:nonroot` (runtime). - `CGO_ENABLED=0` guarantees static binary (modernc/sqlite is pure Go). ### Docker run - `docker run --rm orca-test:v0.4.4 version` → `orca version v0.4.4-test` ✓ - `docker run --rm orca-test:v0.4.4 version --json` → valid JSON with version/commit/build_time ✓ - `docker run --rm -v orca-test-data:/var/lib/orca orca-test:v0.4.4 init` → creates `/var/lib/orca` ✓ - Volume persistence: state dir created in named volume, verified with alpine container ✓ ### Image metrics - Image size: 27.9MB (distroless static + Go binary). - Runs as `nonroot` user (distroless default). - `ENV ORCA_HOME=/var/lib/orca` set for volume-mountable state. ### .coreci.yml release pipeline - New `container-publish` step added after `gitea-release`. - Uses `docker:24-cli` image with `GITEA_TOKEN` as registry credential. - Builds, tags (`` + `latest`), logs in, pushes, logs out. ### scripts/release.sh extension - After Gitea release: `docker build` + `docker login` + `docker push`. - Skips gracefully if `docker` not on PATH (local dev without docker). - Skips push if `GITEA_TOKEN` not set (builds locally only). - Env-overridable: `CONTAINER_REGISTRY`, `CONTAINER_OWNER`, `CONTAINER_IMAGE`. ### Regression — Go tests - `internal/cli/` ✓ (cached) - `internal/store/` ✓ (cached) ## Security Layer - `.dockerignore` excludes `.env`, `.gitleaks-baseline.json`, `bin/` — no secrets in image. - Image runs as `nonroot` (distroless default) — least privilege. - `docker login` uses `--password-stdin` (no password in process args / shell history). - `docker logout` after push — no credential leakage. - No secret material baked into the image — `GITEA_TOKEN` is used at push time only, not in the build. ## Quality Layer - **Reproducible build**: `--build-arg VERSION/GIT_COMMIT/BUILD_TIME` injected via `-ldflags`. - **Minimal image**: distroless static-debian12 — no shell, no package manager, ~28MB total. - **Graceful degradation**: `release.sh` skips docker publish when docker is absent. - **CI integration**: `.coreci.yml` container-publish step uses `docker:24-cli` (has docker CLI). - **Documentation**: `docs/docker.md` covers pull, run, state persistence, local build, manual publish. ## Must-Haves Checklist - [x] `docker build -t orca-test .` succeeds locally. - [x] `docker run --rm orca-test version` prints the version. - [x] `scripts/release.sh vX.Y.Z` publishes both the Gitea release AND the container image. - [x] `.coreci.yml` release pipeline includes the container-publish step. ## Verdict **PASS** — all 4 verification layers pass. REQ-046 is satisfied. Ready to ship as `v0.4.4`.