docker-compose.example.yml
Rama main · réplica de lectura del repositorio original.
services:
# Serves the web application (nginx + php-fpm) and runs the scheduler.
# Does NOT process queued jobs — that's handled by the `horizon` service below.
rtb.prod:
restart: always
image: herrlevin/reisetagebuch:latest
env_file: .env
volumes:
- storage:/var/www/html/storage
depends_on:
- pgsql
- redis
healthcheck:
test: ['CMD', 'curl', '-fsS', '-o', '/dev/null', 'http://localhost/up']
interval: 30s
timeout: 5s
start_period: 10s
retries: 3
# Processes queued jobs via Laravel Horizon. Uses the same image as `rtb.prod`, but
# overrides the container command to run only `artisan horizon`, skipping migrations,
# nginx and php-fpm.
#
# Scale to multiple Horizon workers with:
# docker compose -f docker-compose.example.yml up -d --scale horizon=3
# Each replica registers itself as its own Horizon "master supervisor" in Redis, so
# they coordinate automatically and won't double-process jobs.
horizon:
restart: always
image: herrlevin/reisetagebuch:latest
command: ['php', 'artisan', 'horizon']
# at least as long as config/horizon.php's supervisor `timeout` (60s) so Docker doesn't
# SIGKILL mid-shutdown.
stop_grace_period: 65s
env_file: .env
volumes:
- storage:/var/www/html/storage
depends_on:
pgsql:
condition: service_started
redis:
condition: service_started
rtb.prod:
# Only waits for rtb.prod's healthcheck (nginx responding), not for its
# migrations to finish. On first deploy, run migrations explicitly before
# starting workers, e.g.: docker compose run --rm rtb.prod php artisan migrate
condition: service_healthy
healthcheck:
# Exit codes from horizon:status: 0 = running, 1 = paused, 2 = inactive.
# Since master supervisors are named after the container hostname but
# horizon:status checks all of them, this reports the whole fleet's state,
# not just this replica's — a crashed process still exits the container
# (PID 1), so `restart: always` handles that case independently.
test: ['CMD', 'php', 'artisan', 'horizon:status']
interval: 30s
timeout: 10s
start_period: 10s
retries: 3
pgsql:
restart: always
platform: 'linux/amd64' # Force x86_64 architecture for Postgres, because they don't support arm64 yet
image: 'postgis/postgis:18-master'
environment:
PGPASSWORD: '${DB_PASSWORD:-secret}'
POSTGRES_DB: '${DB_DATABASE}'
POSTGRES_USER: '${DB_USERNAME}'
POSTGRES_PASSWORD: '${DB_PASSWORD:-secret}'
volumes:
- pgsql:/var/lib/postgresql
healthcheck:
test:
- CMD
- pg_isready
- '-q'
- '-d'
- '${DB_DATABASE}'
- '-U'
- '${DB_USERNAME}'
retries: 3
timeout: 5s
redis:
restart: always
image: 'redis:alpine'
volumes:
- redis:/data
command: ['redis-server', '--requirepass', '${REDIS_PASSWORD}']
healthcheck:
test:
- CMD
- redis-cli
- '--no-auth-warning'
- '-a'
- '${REDIS_PASSWORD}'
- ping
retries: 3
timeout: 5s
# The device directories must exist on the host before the first `docker compose up`
# mkdir -p ./app/storage ./pgsql ./redis
volumes:
storage:
driver: local
driver_opts:
type: none
o: bind
device: ./app/storage
pgsql:
driver: local
driver_opts:
type: none
o: bind
device: ./pgsql
redis:
driver: local
driver_opts:
type: none
o: bind
device: ./redis