x-logging: &default-logging driver: json-file options: max-size: "10m" max-file: "3" services: app: logging: *default-logging image: ghcr.io/meshcore-beacon/beacon-server:latest env_file: .env ports: - "127.0.0.1:8080:8080" volumes: - ./data/app/config.yaml:/app/config.yaml:ro depends_on: db: condition: service_healthy redis: condition: service_healthy restart: unless-stopped db: logging: *default-logging image: postgres:16-alpine environment: POSTGRES_USER: beacon POSTGRES_PASSWORD: CHANGE_PASS POSTGRES_DB: beacon volumes: - ./data/postgres/:/var/lib/postgresql/data ports: - "127.0.0.1:5432:5432" healthcheck: test: ["CMD-SHELL", "pg_isready -U beacon"] interval: 5s timeout: 5s retries: 5 restart: unless-stopped redis: logging: *default-logging image: redis:7-alpine volumes: - ./data/redis/:/data ports: - "127.0.0.1:6379:6379" healthcheck: test: ["CMD", "redis-cli", "ping"] interval: 5s timeout: 5s retries: 5 restart: unless-stopped caddy: logging: *default-logging image: caddy:2-alpine ports: - "80:80" - "443:443" environment: - DOMAIN=${DOMAIN:?DOMAIN environment variable is required} env_file: .env volumes: - ./data/Caddy/CaddyFile/Caddyfile.proxy:/etc/caddy/Caddyfile - ./data/Caddy/conf.d:/etc/caddy/conf.d:ro - ./data/Caddy/logs:/var/log/caddy - ./data/Caddy/data:/data/caddy/ - ./data/Caddy/config:/config/caddy/ depends_on: web: condition: service_started restart: unless-stopped web: logging: *default-logging image: ghcr.io/meshcore-beacon/beacon-web:latest env_file: .env environment: - VITE_API_BASE=${VITE_API_BASE:?VITE_API_BASE environment variable is required} - VITE_WS_URL=${VITE_WS_URL:?VITE_WS_URL environment variable is required} depends_on: db: condition: service_healthy redis: condition: service_healthy app: condition: service_started restart: unless-stopped # Fixed subnet so data/app/config.yaml can trust Caddy in server.trusted_proxies. # Pick another private /24 if this one is already in use on the host. networks: default: ipam: config: - subnet: 172.30.0.0/24