dorfteich/deploy/compose/docker-compose.yml
Claude Fable 5 6e5a632c31 Add production Dockerfiles and the Compose stack with dev overlay
Multi-stage images: web (workspace build baked into unprivileged
nginx with SPA fallback, asset caching, /healthz) and api (pnpm deploy
bundle with the prisma CLI for migrate-on-start, non-root, node-based
healthcheck). deploy/compose/docker-compose.yml defines the stage
stack (web, api, db) with frontend/internal networks, localhost-only
published ports for the host reverse proxy, log rotation, and named
volumes; .env.example documents every variable. compose.dev.yml layers
hot-reloading dev containers (or database-only usage) over the same
definition. Verified locally: full stack healthy, SPA fallback, readyz
green after automatic migration, db not reachable from outside.

Closes #6

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-04 19:30:21 +02:00

82 lines
2.0 KiB
YAML

# Production Compose stack — one file for every stage and for self-hosters.
# Configuration comes from .env (see .env.example); the host reverse proxy
# routes to the two published localhost ports (deployment.md §Compose).
#
# Networks: `frontend` is what the reverse proxy reaches (via published
# ports); `internal` connects api/collab to db and (later) the converter
# sidecars, which are never exposed.
name: ${COMPOSE_PROJECT_NAME:-dorfteich}
x-logging: &logging
logging:
driver: json-file
options:
max-size: '10m'
max-file: '5'
services:
web:
image: ${IMAGE_PREFIX:-dorfteich}-web:${TAG:-latest}
build:
context: ../..
dockerfile: apps/web/Dockerfile
args:
APP_VERSION: ${TAG:-latest}
restart: unless-stopped
ports:
- '127.0.0.1:${WEB_PORT:-8100}:8080'
networks: [frontend]
depends_on:
api:
condition: service_started
<<: *logging
api:
image: ${IMAGE_PREFIX:-dorfteich}-api:${TAG:-latest}
build:
context: ../..
dockerfile: apps/api/Dockerfile
args:
APP_VERSION: ${TAG:-latest}
restart: unless-stopped
environment:
NODE_ENV: production
PORT: '3000'
LOG_LEVEL: ${LOG_LEVEL:-info}
DATABASE_URL: postgresql://dorfteich:${POSTGRES_PASSWORD:?set in .env}@db:5432/dorfteich
ports:
- '127.0.0.1:${API_PORT:-8101}:3000'
networks: [frontend, internal]
volumes:
- uploads:/data/uploads
depends_on:
db:
condition: service_healthy
<<: *logging
db:
image: postgres:17.5-alpine
restart: unless-stopped
environment:
POSTGRES_USER: dorfteich
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:?set in .env}
POSTGRES_DB: dorfteich
networks: [internal]
volumes:
- db-data:/var/lib/postgresql/data
healthcheck:
test: ['CMD-SHELL', 'pg_isready -U dorfteich -d dorfteich']
interval: 10s
timeout: 3s
retries: 12
<<: *logging
networks:
frontend:
internal:
volumes:
db-data:
uploads: