docker-compose.yaml
Rama master · réplica de lectura del repositorio original.
name: hook0
volumes:
postgres-data:
mailpit-data:
services:
postgres:
image: postgres:18
volumes:
- postgres-data:/var/lib/postgresql
environment:
- POSTGRES_PASSWORD=postgres
- POSTGRES_DB=hook0
ports:
- "5432:5432"
networks:
- hook0
restart: unless-stopped
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres -d $${POSTGRES_DB}"]
timeout: 1s
interval: 5s
mailpit:
image: axllent/mailpit:v1.28
volumes:
- mailpit-data:/data
environment:
- MP_DATABASE=/data/mailpit.db
- POSTGRES_DB=hook0
ports:
- "8025:8025"
- "1025:1025"
networks:
- hook0
restart: unless-stopped
healthcheck:
test: ["CMD-SHELL", "wget --no-verbose --tries=1 --spider --user-agent 'docker-compose-healthcheck' http://localhost:8025/api/v1/info || exit 1"]
timeout: 1s
interval: 5s
api:
build:
context: .
dockerfile: api/Dockerfile
args:
FEATURES: "application-secret-compatibility"
environment:
- IP=0.0.0.0
- PORT=8081
- CORS_ALLOWED_ORIGINS=http://localhost:8001
- DATABASE_URL=postgres://postgres:postgres@postgres:5432/hook0
- SMTP_CONNECTION_URL=smtp://mailpit:1025
- EMAIL_SENDER_ADDRESS=sender@hook0.local
- APP_URL=http://localhost:8001
- BISCUIT_PRIVATE_KEY=bbea79cd66926b219b3219a3186decb36136d774dd7c35a8239e512090fa8854 # DO NOT USE THIS KEY IN PRODUCTION
# Development stack only: the default burst of 5 is what bounds
# address-enumeration sweeps on the endpoints that send mail. The suite
# gives its direct API calls a source address of their own, so only the
# browser-driven ones draw on this quota — signing up included, now that
# registration mails an address the caller names and is held to the same
# allowance as the rest of that family. Raised rather than disabled, and
# not raised out of sight, so a loop that hammers the endpoint still meets
# a 429 here instead of meeting one for the first time in production.
- API_RATE_LIMITING_EMAIL_BURST_SIZE=50
# Development stack only, and the phrase is read rather than only meant:
# a setting whose comment carries it is one `self-hosting` is held not to
# declare, and one the compose file has to be free to shape for this stack
# without shaping a cluster.
#
# One address: this stack's own bridge gateway, which is what a caller on
# this host arrives as. It makes the API trust the client address
# announced in a proxy header when the peer is that gateway, and trust
# nobody else — a peer inside the trusted range can claim any address it
# likes and walk past every per-IP limiter, so the range is the whole of
# the setting's blast radius and it is held to one address.
#
# Not 127.0.0.0/8, and not the bridge pool either. Measured on the three
# ways in, against a container on a network this file shaped:
#
# from this host, through the published port -> the gateway, 172.16.0.1
# from another container on this network -> its own address, .0.2 up
# from off the host, at its LAN address -> the caller's own address
#
# so loopback is never what arrives, and Docker's pool would have covered
# the second line: every sibling on this network, `frontend` and
# `output-worker` included, plus whatever an operator adds to it. The
# gateway is the one address on the network no container can be given.
#
# It is a fixed address rather than a guessed one because the network
# below fixes it. Left to itself Docker draws a /16 from its pool in the
# order they are free, so the gateway is 172.18.0.1 on one machine and
# 172.21.0.1 on the next, and a range wide enough to cover them all is
# the range this is not.
- REVERSE_PROXY_IPS=172.16.0.1/32
ports:
- "8081:8081"
networks:
- hook0
restart: unless-stopped
healthcheck:
test: ["CMD-SHELL", "curl --fail --user-agent 'docker-compose-healthcheck' http://localhost:$${PORT}/api/v1/swagger.json || exit 1"]
timeout: 1s
interval: 5s
depends_on:
postgres:
condition: service_healthy
mailpit:
condition: service_healthy
frontend:
build:
context: .
dockerfile: frontend/Dockerfile
environment:
- API_ENDPOINT=http://localhost:8081/api/v1
ports:
- "8001:80"
networks:
- hook0
restart: unless-stopped
healthcheck:
test: ["CMD-SHELL", "curl --fail --user-agent 'docker-compose-healthcheck' http://localhost || exit 1"]
timeout: 1s
interval: 5s
depends_on:
api:
condition: service_healthy
output-worker:
build:
context: .
dockerfile: output-worker/Dockerfile
environment:
- DATABASE_URL=postgres://postgres:postgres@postgres:5432/hook0
- WORKER_NAME=default
- DISABLE_TARGET_IP_CHECK=true
networks:
- hook0
restart: unless-stopped
depends_on:
postgres:
condition: service_healthy
api:
condition: service_healthy
networks:
hook0:
driver: bridge
# Fixed rather than drawn from Docker's pool, so that the gateway the API is
# told to trust is an address this file knows rather than one that differs
# per machine. 172.16 is inside the pool's range and outside what it hands
# out: a daemon left to itself starts at 172.18 and walks up, so this is the
# one /16 in there it will not give to something else. Should an operator
# have taken it anyway, `docker compose up` refuses naming the overlap,
# which is the way to find out.
ipam:
config:
- subnet: 172.16.0.0/24
gateway: 172.16.0.1