Skip to content
mcinquin edited this page Oct 12, 2026 · 1 revision

Docker

Two Compose files in the repository:

File Usage
docker-compose.yml Production — pinned image from GHCR, hardened runtime
docker-compose.dev.yml Local Docker — build from the Dockerfile

The image starts with an empty collection: only a writable data/ directory is required. The container runs as the hobbyhoops system user (UID/GID 1111). Mount data/ at /app/data and make it writable by that user.

Simple run (no reverse proxy)

For local / LAN over HTTP, prefer the README quick start: docker-compose.dev.yml with COOKIE_SECURE=false and TRUST_PROXY=false.

Production (GHCR)

After each semantic-release run on main, images are published to GitHub Container Registry:

  • ghcr.io/mcinquin/hobbyhoops:latest
  • ghcr.io/mcinquin/hobbyhoops:X.Y.Z

Prefer a version tag in production, not latest. The default tag is kept in sync with releases in docker-compose.yml (HOBBYHOOPS_VERSION).

cp .env.example .env
# Required: AUTH_SECRET (openssl rand -hex 32)
mkdir -p data && sudo chown -R 1111:1111 data

export HOBBYHOOPS_VERSION=X.Y.Z   # tag matching your GHCR release
docker compose pull
docker compose up -d

docker-compose.yml expects a .env file (required: true). AUTH_SECRET must be set or Compose will fail at startup.

Defaults suited to an HTTPS reverse proxy that rewrites forwarding headers:

  • TRUST_PROXY=true (set false in .env if the proxy does not set X-Forwarded-For / X-Forwarded-Proto correctly)
  • COOKIE_SECURE=true

Override via .env if needed. See Security and SECURITY.md.

Runtime hardening

Production Compose options include: non-root user, read_only root filesystem, dropped capabilities, health check on /api/health, and log rotation. No CPU/RAM cap by default (a low mem_limit / cpus makes Next.js feel very slow).

The application listens on 127.0.0.1:3000 (not exposed on all interfaces). Place a reverse proxy (e.g. Apache) on the host and proxy to that address. The reverse proxy stays outside Compose.

Reverse proxy notes

  • Terminate TLS on the proxy; forward to http://127.0.0.1:3000.
  • Rewrite X-Forwarded-For / X-Forwarded-Proto when TRUST_PROXY=true.
  • HTTP hardening headers (HSTS, X-Content-Type-Options, etc.) are handled by the proxy.
  • Keep COOKIE_SECURE=true behind HTTPS.

Local Docker (build)

cp .env.example .env
mkdir -p data && sudo chown -R 1111:1111 data
docker compose -f docker-compose.dev.yml up --build -d

AUTH_SECRET is optional here (a dev-only default is provided); still set a real value to match production behaviour. For plain HTTP, set COOKIE_SECURE=false.

Related

Clone this wiki locally