docker-compose.yml
Rama main · réplica de lectura del repositorio original.
services:
# ────────────────────────── front-end ──────────────────────────
caddy:
image: caddy:2.10.0-alpine
container_name: caddy
ports:
- "80:80"
- "443:443"
volumes:
- ./docker/caddy/Caddyfile:/etc/caddy/Caddyfile:ro
- caddy_data:/data # ACME certs
- caddy_config:/config
- ./public:/srv # static assets
networks: [web]
nginx:
image: nginx:1.28.3-alpine
container_name: nginx
depends_on: [caddy, php]
expose:
- "8080"
volumes:
- ./docker/nginx/nginx.conf:/etc/nginx/nginx.conf:ro
- ./public:/srv:ro
networks: [web, app]
# ─────────────────────────── PHP / FPM ─────────────────────────
php:
build: ./docker/php # see Dockerfile below
container_name: php
volumes:
- .:/var/www/html
environment:
APP_ENV: ${APP_ENV:-local}
DB_HOST: db
DB_DATABASE: ${DB_DATABASE:-easymonitor}
DB_USERNAME: ${DB_USERNAME:-easymonitor}
DB_PASSWORD: ${DB_PASSWORD:-secret}
REDIS_HOST: redis
REDIS_PASSWORD: ${REDIS_PASSWORD:-}
networks: [app]
depends_on:
db:
condition: service_started
redis:
condition: service_healthy
# Give Horizon time to finish in-flight jobs and deregister itself
# from Redis (supervisord stopwaitsecs=60) before Docker kills it.
stop_grace_period: 75s
# ────────────────────────── data layer ─────────────────────────
db:
image: timescale/timescaledb:2.26.0-pg18 # PG18 + Timescale 2.26.0
container_name: db
ports:
- "5432:5432"
environment:
POSTGRES_USER: ${DB_USERNAME:-easymonitor}
POSTGRES_PASSWORD: ${DB_PASSWORD:-secret}
POSTGRES_DB: ${DB_DATABASE:-easymonitor}
volumes:
# timescale/timescaledb:*-pg18 sets PGDATA=/var/lib/postgresql/18/docker
# (the image also declares /var/lib/postgresql as a VOLUME, which would
# otherwise swallow the data into an anonymous volume on every restart).
- db_data:/var/lib/postgresql/18/docker
- ./docker/db/init.sh:/docker-entrypoint-initdb.d/999-init.sh:ro
networks: [app]
redis:
image: redis:7.4-alpine
container_name: redis
environment:
REDIS_PASSWORD: ${REDIS_PASSWORD:-}
# Run redis-server with --requirepass only when REDIS_PASSWORD is set.
# The $$ lets the shell (inside the container) see $REDIS_PASSWORD
# instead of Docker Compose trying to substitute it.
command: >
sh -c '
if [ -n "$$REDIS_PASSWORD" ]; then
exec redis-server --appendonly yes --requirepass "$$REDIS_PASSWORD"
else
exec redis-server --appendonly yes
fi
'
volumes:
- redis_data:/data
networks: [app]
# Healthy only once the dataset is loaded: while loading, PING
# answers "LOADING ..." instead of PONG.
healthcheck:
test:
- CMD-SHELL
- '[ -n "$$REDIS_PASSWORD" ] && export REDISCLI_AUTH="$$REDIS_PASSWORD"; redis-cli ping | grep -q PONG'
interval: 5s
timeout: 3s
retries: 30
start_period: 10s
# ──────────────────────────── probe node ───────────────────────────
# The probe node is enabled by default for immediate monitoring capability.
# To disable it, use: docker compose up -d --scale probe=0
probe:
build: ./probe-node
container_name: probe
environment:
NODE_ID: ${PROBE_NODE_ID:-local-node-1}
REDIS_URL: ${PROBE_REDIS_URL:-redis://redis:6379/0}
REDIS_PASSWORD: ${REDIS_PASSWORD:-}
JWT_TOKEN: ${PROBE_JWT_TOKEN:-}
DEFAULT_TIMEOUT: 30s
BATCH_SIZE: 10
MAX_CONCURRENCY: 10
HEALTH_CHECK_PORT: 8080
depends_on:
redis:
condition: service_healthy
networks: [app]
restart: unless-stopped
healthcheck:
test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:8080/health"]
interval: 30s
timeout: 5s
retries: 3
start_period: 5s
networks:
web:
app:
volumes:
db_data:
redis_data:
caddy_data:
caddy_config: