Skip to main content

Docker deployment

The registry server ships as a pre-built Docker image published to GitHub Container Registry on every release.

Image: ghcr.io/dejanradmanovic/event-spec-server

TagDescription
latestMost recent release
v0.3.1Specific semver release

Multi-arch: linux/amd64 + linux/arm64. The image is based on alpine:3 and includes ca-certificates and git.


Quick start — SQLite

For development and single-node deployments:

docker run -p 8080:8080 \
-v "$PWD/data:/data" \
ghcr.io/dejanradmanovic/event-spec-server:latest \
--db file:/data/registry.db

The database schema is applied automatically on first startup. Open http://localhost:8080/ui/ to verify the server is running.


Bootstrap — first API key

On a fresh database with no keys, the first key can be created without authentication.

Via API:

curl -X POST http://localhost:8080/v1/admin/keys \
-H "Content-Type: application/json" \
-d '{"role": "admin", "name": "bootstrap"}'

Response:

{
"id": 1,
"key": "a3f8c2...",
"role": "admin"
}

Via admin UI:

Open http://localhost:8080/ui/ in a browser. On the first launch the interface presents a bootstrap screen to create the initial admin key.

The raw key value is returned once — save it immediately. Only its SHA-256 hash is persisted. If it is lost, it cannot be recovered; revoke it and create a new one.


Docker Compose — SQLite (development)

docker-compose.yml
services:
registry:
image: ghcr.io/dejanradmanovic/event-spec-server:latest
ports:
- "8080:8080"
volumes:
- ./data:/data
command: ["--db", "file:/data/registry.db"]
restart: unless-stopped
docker compose up -d

Docker Compose — PostgreSQL (production)

docker-compose.yml
services:
db:
image: postgres:16-alpine
environment:
POSTGRES_USER: event_spec
POSTGRES_PASSWORD: secret
POSTGRES_DB: event_spec
volumes:
- pgdata:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U event_spec"]
interval: 5s
timeout: 3s
retries: 5

registry:
image: ghcr.io/dejanradmanovic/event-spec-server:latest
ports:
- "8080:8080"
depends_on:
db:
condition: service_healthy
environment:
POSTGRES_USER: event_spec
POSTGRES_PASSWORD: secret
POSTGRES_DB: event_spec
command:
- "--db"
- "postgres://${POSTGRES_USER}:${POSTGRES_PASSWORD}@db:5432/${POSTGRES_DB}"
restart: unless-stopped

volumes:
pgdata:
Credentials in the --db flag

Shell variable expansion (${VAR}) works in the command array when the variables are defined in the environment block of the same service.


--db flag reference

DSN formatDescription
file:/data/registry.dbSQLite file at an absolute path
file:./registry.dbSQLite file relative to the working directory
postgres://user:pass@host:5432/dbnamePostgreSQL connection string
postgres://user:pass@host:5432/dbname?sslmode=requirePostgreSQL with TLS

The schema is applied automatically on startup. No manual migration steps are needed.


Digest pinning

For reproducible production deployments, pin to an image digest rather than a mutable tag:

# docker-compose.yml
services:
registry:
image: ghcr.io/dejanradmanovic/event-spec-server@sha256:<digest>

Find the digest for a tagged release:

docker pull ghcr.io/dejanradmanovic/event-spec-server:v0.3.1
docker inspect --format='{{index .RepoDigests 0}}' \
ghcr.io/dejanradmanovic/event-spec-server:v0.3.1

Next steps