version: '3.8' services: # Shared base image (OS packages + PHP + compiled Swoole/UV + Composer). It is # slow to build because it compiles the PHP extensions from source, so build # it ONCE and reuse it. The phlix service FROMs the tag produced here, so a # locally-built base is picked up automatically: # # docker compose build phlix-base # slow, but only when extensions change # docker compose build phlix # fast — reuses the base, no recompile # # Alternatively pull the published base instead of building it: # docker pull ghcr.io/detain/phlix-base:latest phlix-base: build: context: . dockerfile: docker/Dockerfile.base image: ghcr.io/detain/phlix-base:latest profiles: ["build"] phlix: build: context: . dockerfile: docker/Dockerfile container_name: phlix-server # The container runs the Workerman daemon directly (no nginx, no php-fpm), # so the ports to publish are the ones start.php binds — 8096 (HTTP: # REST + SPA + static; it has ZERO WebSocket-upgrade logic) and 8097 # (SyncPlay WebSocket — a SEPARATE plaintext listener, not a path on # 8096). Nothing has ever listened on 80 or 443 inside the image. # This file is the DEVELOPMENT stack: both mappings bind 127.0.0.1 only, # and the DB credentials below are fixed dev values that must never be # reused in a real deployment (see docker/examples/ for the hardened, # ${VAR:?}-gated production examples). ports: - "127.0.0.1:8096:8096" - "127.0.0.1:8097:8097" environment: - PHLIX_DATABASE_HOST=mysql - PHLIX_DATABASE_PORT=3306 - PHLIX_DATABASE_NAME=phlix - PHLIX_DATABASE_USER=phlix - PHLIX_DATABASE_PASSWORD=phlix_secret # Dev stack: strict migrations OFF so a schema hiccup still boots the # app with the loud PHLIX-MIGRATION-FAILURE banner (images default to # strict; the hardened examples set =1 explicitly). - PHLIX_MIGRATIONS_STRICT=0 volumes: - phlix_config:/var/phlix/config - phlix_data:/var/phlix/data - phlix_backups:/var/phlix/backups - media_library:/media depends_on: mysql: condition: service_healthy # The Phlix container's PID 1 exits 70 when a supervised program enters # FATAL (a total application outage), and 0 on a clean stop — see # docker/README.md "What the container's exit code means". # `unless-stopped` restarts on ANY exit, so a persistent fault becomes a # restart loop that re-runs the migration chain each cycle. Swap to # `on-failure:5` if you would rather it stay `Exited (70)` for monitoring. restart: unless-stopped mysql: image: mysql:8.0 container_name: phlix-mysql environment: MYSQL_ROOT_PASSWORD: root MYSQL_DATABASE: phlix MYSQL_USER: phlix MYSQL_PASSWORD: phlix_secret volumes: - mysql_data:/var/lib/mysql healthcheck: test: ["CMD", "mysqladmin", "ping", "-h", "localhost"] interval: 10s timeout: 5s retries: 5 restart: unless-stopped volumes: phlix_config: phlix_data: phlix_backups: media_library: mysql_data: