# Server F: one stack per environment, both on the same machine. # # docker compose -f deploy/docker-compose.yml --env-file deploy/test.env up -d --build # docker compose -f deploy/docker-compose.yml --env-file deploy/production.env up -d --build # # The environment file decides everything that tells the two apart, and it # does so through **names**, not through the place the command runs in: # # * `name:` is the stack's name (`filius-test`, `filius-production`). Docker # prefixes containers, network and volume with it, so the two stacks share # nothing — above all not the database. Without it, compose would take the # folder's name, and both stacks started from this folder would be **one** # stack: the second `up` would replace the first. That is also why no # `-p` is needed (and why forgetting one does no harm, unlike on server S). # * `image:` carries the stack's name as its tag. A shared tag would let a # build for the test environment change what production runs at its next # restart. # * The port: test 8081, production 8080, as `deploy/proxy.conf` expects. # # Needs Docker Compose v2 (`docker compose`; the old `docker-compose` 1.x # does not know `name:`). # # The data lies in the volume `_db` (documents, sessions, blobs). It is # the one thing of a stack that has to be backed up: # # docker compose -f deploy/docker-compose.yml --env-file deploy/production.env \ # exec -T db pg_dump -U filius filius > filius-production.sql name: "${FILIUS_STACK:?FILIUS_STACK missing, start with --env-file deploy/.env}" services: db: image: postgres:16-alpine restart: unless-stopped environment: POSTGRES_DB: filius POSTGRES_USER: filius POSTGRES_PASSWORD: ${FILIUS_DB_PASSWORD:?FILIUS_DB_PASSWORD missing} volumes: - db:/var/lib/postgresql/data healthcheck: test: ["CMD-SHELL", "pg_isready -U filius -d filius"] interval: 5s timeout: 5s retries: 12 # No `ports:`: only F talks to its database, over the stack's network. filius: image: mdg-filius:${FILIUS_STACK} build: context: .. dockerfile: deploy/Dockerfile restart: unless-stopped depends_on: db: condition: service_healthy environment: # The password goes into a URL: hex only (`openssl rand -hex 32`), a # `@`, `/` or `:` in it would break the URL. DATABASE_URL: postgres://filius:${FILIUS_DB_PASSWORD}@db:5432/filius FILIUS_TICKET_SECRET: ${FILIUS_TICKET_SECRET:?FILIUS_TICKET_SECRET missing} FILIUS_SERVICE_KEY: ${FILIUS_SERVICE_KEY:?FILIUS_SERVICE_KEY missing} FILIUS_ORIGINS: ${FILIUS_ORIGINS:?FILIUS_ORIGINS missing} ports: # The address the openresty reaches F on, and the stack's port. - "${FILIUS_BIND:?FILIUS_BIND missing}:${FILIUS_PUBLIC_PORT:?FILIUS_PUBLIC_PORT missing}:8080" # F stops its rooms and stores every open document before it ends # (main.ts, SIGTERM); Docker's 10 s are enough today, 30 s leave room # for a large school day. stop_grace_period: 30s volumes: db: