Running the cloacina-server Docker image
The official cloacina-server image is published to the GitHub Container
Registry on every release tag and nightly on main. This page covers
pulling, configuring, and running it.
# Latest stable release
docker pull ghcr.io/colliery-io/cloacina-server:latest
# Pin to a specific version
docker pull ghcr.io/colliery-io/cloacina-server:0.7.0
# Track main (rebuilt every night at 03:00 UTC)
docker pull ghcr.io/colliery-io/cloacina-server:nightly
The image is multi-arch (linux/amd64 + linux/arm64); Docker selects
the matching manifest automatically.
| Tag | Updated | Notes |
|---|---|---|
latest |
every release | The most recent stable tag |
<X.Y.Z> |
one-shot | Immutable, pinned to that release |
<X.Y> |
every patch | Floats forward across patch releases |
nightly |
daily 03:00 UTC | Built from main |
The server needs a Postgres database — DATABASE_URL is the only
required env var.
docker run --rm \
-e DATABASE_URL=postgres://cloacina:cloacina@host.docker.internal:5432/cloacina \
-p 8080:8080 \
ghcr.io/colliery-io/cloacina-server:latest
On startup it auto-runs migrations and (on first boot) generates a
bootstrap API key. Watch the logs for the key, or pin one with
-e CLOACINA_BOOTSTRAP_KEY=....
All flags double as env vars:
| Flag | Env | Purpose |
|---|---|---|
--bind |
— | Bind address (default 127.0.0.1:8080; usually 0.0.0.0:8080 in containers) |
--database-url |
DATABASE_URL |
Postgres connection string |
--bootstrap-key |
CLOACINA_BOOTSTRAP_KEY |
Pin the initial admin API key |
--require-signatures |
CLOACINA_REQUIRE_SIGNATURES |
Reject unsigned packages |
--verification-org-id |
CLOACINA_VERIFICATION_ORG_ID |
Org UUID for signature verification |
--tenant-runner-cache-size |
CLOACINA_TENANT_RUNNER_CACHE_SIZE |
LRU cap on per-tenant runners (default 256) |
The image’s home directory is /home/cloacina/.cloacina
(CLOACINA_HOME is set so any tooling that reads it resolves correctly).
services:
postgres:
image: postgres:16
environment:
POSTGRES_USER: cloacina
POSTGRES_PASSWORD: cloacina
POSTGRES_DB: cloacina
volumes:
- cloacina-pgdata:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U cloacina"]
interval: 5s
retries: 12
cloacina-server:
image: ghcr.io/colliery-io/cloacina-server:latest
depends_on:
postgres:
condition: service_healthy
environment:
DATABASE_URL: postgres://cloacina:cloacina@postgres:5432/cloacina
command: ["--bind", "0.0.0.0:8080"]
ports:
- "8080:8080"
healthcheck:
test: ["CMD-SHELL", "wget -qO- http://127.0.0.1:8080/health || exit 1"]
interval: 10s
retries: 6
volumes:
cloacina-pgdata:
The image itself does not declare a HEALTHCHECK — orchestrators each
have their own probe story (compose example above; Kubernetes via the
Helm chart in CLOACI-T-0605).
- Base:
debian:bookworm-slim+libpq5+ca-certificates - Compressed size: ~150 MB
- Runs as non-root (uid
10001, gid10001) - Exposes port
8080 - Source labelled via
org.opencontainers.image.sourceso ghcr links the image back to the repo
docker build -t cloacina-server:dev .
docker run --rm cloacina-server:dev --version
The Dockerfile lives at the repo root; .dockerignore keeps build
artifacts and dev metadata out of the build context.
- Deploying the API Server — full configuration reference (auth, signatures, multi-tenancy)
- Production Deployment — scaling and operational hardening