The files copied to /srv/stacks/<stack>/ verbatim: compose files, vhosts, Prometheus configuration, the webapp image source. Payloads are data, never templated and never linted as Ansible content. Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
60 lines
2.1 KiB
YAML
60 lines
2.1 KiB
YAML
# A database-backed application: the stack that needs more than "sync and up".
|
|
#
|
|
# Every credential comes from .env, with no defaults. `${VAR:?message}` makes
|
|
# Compose refuse to start and say which variable is missing, which is strictly
|
|
# better than booting with an empty password. .env lives on the host and is never
|
|
# synced from this repository, so ansible/playbooks/webapp.yml asserts it is
|
|
# there before doing anything.
|
|
services:
|
|
db:
|
|
container_name: webapp-db
|
|
image: postgres:17-alpine
|
|
restart: unless-stopped
|
|
# ./pgdata is deliberately NOT pre-created by the playbook: Postgres refuses
|
|
# to start unless its data directory is 0700 or 0750, and the image gets that
|
|
# right on first start. See "Common mistakes" in skills/adding-a-stack.
|
|
volumes:
|
|
- ./pgdata:/var/lib/postgresql/data
|
|
environment:
|
|
POSTGRES_DB: webapp
|
|
POSTGRES_USER: webapp
|
|
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:?set it in .env on the host}
|
|
healthcheck:
|
|
test: ["CMD-SHELL", "pg_isready -U webapp"]
|
|
interval: 10s
|
|
timeout: 5s
|
|
retries: 5
|
|
networks:
|
|
- backend
|
|
|
|
web:
|
|
container_name: webapp
|
|
# Built from the payload rather than pulled. stack_build in the playbook
|
|
# decides when a rebuild happens: on an update run, not on every deploy.
|
|
build:
|
|
context: ./app
|
|
image: example/webapp:local
|
|
restart: unless-stopped
|
|
depends_on:
|
|
db:
|
|
condition: service_healthy
|
|
environment:
|
|
DATABASE_URL: postgres://webapp:${POSTGRES_PASSWORD:?set it in .env on the host}@db:5432/webapp
|
|
SECRET_KEY: ${SECRET_KEY:?set it in .env on the host}
|
|
# Set by the role to stack_dest, so a path handed to a sibling container is
|
|
# the path on the host and not wherever the SSH session happened to land.
|
|
UPLOAD_HOST_DIR: ${PWD}/uploads
|
|
VIRTUAL_HOST: app.example.com
|
|
VIRTUAL_PORT: "8080"
|
|
LETSENCRYPT_HOST: app.example.com
|
|
volumes:
|
|
- ./uploads:/var/lib/webapp/uploads
|
|
networks:
|
|
- backend
|
|
- proxy-net
|
|
|
|
networks:
|
|
backend:
|
|
proxy-net:
|
|
external: true
|