name: colofon services: frontend: image: ghcr.io/nonetss/colofon-frontend:main container_name: colofon-frontend init: true # Reached only through the gateway, which publishes the site expose: - "4321" environment: BACKEND_URL: http://backend:3000 depends_on: backend: condition: service_healthy env_file: .env healthcheck: test: [ "CMD", "bun", "-e", "fetch('http://localhost:4321/login').then((r) => process.exit(r.ok ? 0 : 1)).catch(() => process.exit(1))" ] interval: 10s timeout: 5s retries: 5 start_period: 15s restart: unless-stopped networks: - colofon backend: image: ghcr.io/nonetss/colofon-backend:main container_name: colofon-backend init: true expose: - "3000" environment: NODE_ENV: production DATABASE_URL: ${DATABASE_URL} # Better Auth's base URL is the public URL: OAuth callbacks are built # from it. It reuses CORS_ORIGIN from .env so both always match. BETTER_AUTH_URL: ${CORS_ORIGIN} BETTER_AUTH_SECRET: ${BETTER_AUTH_SECRET} # CORS_ORIGIN (the public URL) comes from .env. `environment` # overrides `env_file`. env_file: .env volumes: # One clone per content repository (stored in the database), kept # across container recreations. - content_data:/app/.content # The bare repository of each hosted content repository: possibly the # only copy of its content, so apart from the disposable clones. - hosted_data:/app/.hosted depends_on: db: condition: service_healthy healthcheck: test: [ "CMD", "bun", "-e", "fetch('http://localhost:3000/').then((r) => process.exit(r.ok ? 0 : 1)).catch(() => process.exit(1))" ] interval: 10s timeout: 5s retries: 5 start_period: 15s restart: unless-stopped networks: - colofon # Gateway (apps/gateway/Caddyfile): the only published service. Its :80 # site routes /rpc, /api, /scalar and /openapi.json to the backend and the # rest to the frontend. gateway: image: ghcr.io/nonetss/colofon-gateway:main container_name: colofon-gateway ports: # Host port comes from .env (scripts/bootstrap.sh prompts for it); the # default keeps `docker compose up` working with no FRONTEND_PORT set. - "${FRONTEND_PORT:-4444}:80" depends_on: frontend: condition: service_healthy healthcheck: test: [ "CMD", "wget", "-q", "--spider", "http://localhost/health" ] interval: 10s timeout: 5s retries: 5 start_period: 5s restart: unless-stopped networks: - colofon db: image: postgres:17 container_name: colofon-db environment: POSTGRES_USER: postgres POSTGRES_PASSWORD: ${POSTGRES_PASSWORD} POSTGRES_DB: colofon volumes: - db_data:/var/lib/postgresql/data healthcheck: test: [ "CMD-SHELL", "pg_isready -U postgres -d colofon" ] interval: 10s timeout: 5s retries: 5 start_period: 10s restart: unless-stopped networks: - colofon volumes: content_data: hosted_data: db_data: networks: colofon: driver: bridge