ungleich-user/compose.yaml
Sajeyks f19d0576ed Add compose.yaml for a plain production-style deployment
PostgreSQL with a persistent volume, a one-off migrate service running
migrate_locked, and the web app, which starts only after migrations
succeeded. The app runs with a read-only filesystem, no capabilities and
a health check. Configuration comes from .env (or ENV_FILE). Checked end
to end: database healthy, migrations applied, both probes OK, login
works.
2026-11-11 21:40:30 +03:00

61 lines
1.6 KiB
YAML

# Production-style deployment with Docker Compose: PostgreSQL, a one-off
# migration step, and the web app. Configuration comes from .env
# (copy .env.example). See docker.md.
#
# cp .env.example .env # then fill in the required values
# docker compose up -d --build
#
# For local development use docker-compose.dev.yml instead.
x-app: &app
build: .
image: ungleich-user:latest
env_file: ${ENV_FILE:-.env}
environment:
DATABASE_HOST: db
read_only: true
tmpfs:
- /tmp
cap_drop: [ALL]
security_opt: ["no-new-privileges:true"]
services:
db:
image: postgres:18-alpine
restart: unless-stopped
environment:
POSTGRES_DB: ${DATABASE_NAME:-ungleich_user}
POSTGRES_USER: ${DATABASE_USER:-ungleich_user}
POSTGRES_PASSWORD: ${DATABASE_PASSWORD:?set DATABASE_PASSWORD in .env}
volumes:
- pgdata:/var/lib/postgresql
healthcheck:
test: ["CMD-SHELL", "pg_isready -U $${POSTGRES_USER}"]
interval: 3s
retries: 20
# Runs once per `up` and exits; web starts only if it succeeded.
migrate:
<<: *app
command: ["python", "manage.py", "migrate_locked"]
restart: "no"
depends_on:
db:
condition: service_healthy
web:
<<: *app
restart: unless-stopped
ports:
- "${PORT:-8000}:8000"
depends_on:
migrate:
condition: service_completed_successfully
healthcheck:
test: ["CMD", "python", "-c", "import urllib.request; urllib.request.urlopen('http://localhost:8000/healthz', timeout=3)"]
interval: 15s
timeout: 5s
retries: 3
volumes:
pgdata: