services: postgres: image: postgres:16-alpine container_name: yakpanel-postgres restart: unless-stopped environment: POSTGRES_USER: ${POSTGRES_USER} POSTGRES_PASSWORD: ${POSTGRES_PASSWORD} POSTGRES_DB: ${POSTGRES_DB} ports: - "${POSTGRES_PORT}:5432" volumes: - yakpanel_postgres_data:/var/lib/postgresql/data healthcheck: test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DB}"] interval: 10s timeout: 5s retries: 10 redis: image: redis:7-alpine container_name: yakpanel-redis restart: unless-stopped command: ["redis-server", "--appendonly", "yes"] ports: - "${REDIS_PORT}:6379" volumes: - yakpanel_redis_data:/data healthcheck: test: ["CMD", "redis-cli", "ping"] interval: 10s timeout: 5s retries: 10 nats: image: nats:2.10-alpine container_name: yakpanel-nats restart: unless-stopped command: ["-js"] ports: - "${NATS_PORT}:4222" - "${NATS_MONITOR_PORT}:8222" minio: image: minio/minio:latest container_name: yakpanel-minio restart: unless-stopped command: server /data --console-address ":9001" environment: MINIO_ROOT_USER: ${MINIO_ROOT_USER} MINIO_ROOT_PASSWORD: ${MINIO_ROOT_PASSWORD} ports: - "${MINIO_PORT}:9000" - "${MINIO_CONSOLE_PORT}:9001" volumes: - yakpanel_minio_data:/data # Full web control panel: FastAPI (service hostname "backend" for nginx upstream) backend: build: ./YakPanel-server/backend container_name: yakpanel-panel-api restart: unless-stopped command: [ "sh", "-lc", "python scripts/seed_admin.py && exec uvicorn app.main:app --host 0.0.0.0 --port 8888", ] volumes: - ./YakPanel-server/backend:/app - yakpanel_panel_data:/app/data environment: REDIS_URL: redis://redis:6379/0 DATABASE_URL: sqlite+aiosqlite:///./data/default.db CORS_EXTRA_ORIGINS: ${PANEL_CORS_EXTRA_ORIGINS:-} depends_on: redis: condition: service_healthy panel-worker: build: ./YakPanel-server/backend container_name: yakpanel-panel-worker restart: unless-stopped command: ["celery", "-A", "app.tasks.celery_app", "worker", "-l", "info"] volumes: - ./YakPanel-server/backend:/app - yakpanel_panel_data:/app/data environment: REDIS_URL: redis://redis:6379/0 DATABASE_URL: sqlite+aiosqlite:///./data/default.db depends_on: redis: condition: service_healthy backend: condition: service_started panel-scheduler: build: ./YakPanel-server/backend container_name: yakpanel-panel-scheduler restart: unless-stopped command: ["celery", "-A", "app.tasks.celery_app", "beat", "-l", "info"] volumes: - ./YakPanel-server/backend:/app - yakpanel_panel_data:/app/data environment: REDIS_URL: redis://redis:6379/0 DATABASE_URL: sqlite+aiosqlite:///./data/default.db depends_on: redis: condition: service_healthy backend: condition: service_started panel-ui: build: context: ./YakPanel-server/frontend dockerfile: Dockerfile container_name: yakpanel-panel-frontend restart: unless-stopped ports: - "${PANEL_UI_PORT}:80" depends_on: - backend api: image: php:8.3-cli-alpine container_name: yakpanel-api restart: unless-stopped working_dir: /var/www/panel-api command: ["php", "-S", "0.0.0.0:8080", "-t", "public"] volumes: - ./panel-api:/var/www/panel-api ports: - "${API_PORT}:8080" depends_on: postgres: condition: service_healthy redis: condition: service_healthy db-migrate: condition: service_completed_successfully agent-gateway: image: golang:1.23-alpine container_name: yakpanel-agent-gateway restart: unless-stopped working_dir: /src command: ["sh", "-lc", "go run ./cmd/agent-gateway"] volumes: - ./control-plane-go:/src depends_on: redis: condition: service_healthy prometheus: image: prom/prometheus:latest container_name: yakpanel-prometheus restart: unless-stopped command: - --config.file=/etc/prometheus/prometheus.yml - --storage.tsdb.path=/prometheus volumes: - ./deploy/prometheus/prometheus.yml:/etc/prometheus/prometheus.yml:ro - yakpanel_prometheus_data:/prometheus ports: - "${PROMETHEUS_PORT}:9090" depends_on: - cadvisor grafana: image: grafana/grafana:latest container_name: yakpanel-grafana restart: unless-stopped environment: GF_SECURITY_ADMIN_USER: ${GRAFANA_ADMIN_USER} GF_SECURITY_ADMIN_PASSWORD: ${GRAFANA_ADMIN_PASSWORD} GF_USERS_ALLOW_SIGN_UP: "false" volumes: - yakpanel_grafana_data:/var/lib/grafana - ./deploy/grafana/provisioning/datasources:/etc/grafana/provisioning/datasources:ro ports: - "${GRAFANA_PORT}:3000" depends_on: - prometheus cadvisor: image: gcr.io/cadvisor/cadvisor:latest container_name: yakpanel-cadvisor restart: unless-stopped privileged: true ports: - "${CADVISOR_PORT}:8080" volumes: - /:/rootfs:ro - /var/run:/var/run:rw - /sys:/sys:ro - /var/lib/docker/:/var/lib/docker:ro db-migrate: image: postgres:16-alpine container_name: yakpanel-db-migrate restart: "no" working_dir: /workspace environment: PGPASSWORD: ${POSTGRES_PASSWORD} command: [ "sh", "-lc", "psql -h postgres -U ${POSTGRES_USER} -d ${POSTGRES_DB} -f architecture/2026/02-core-schema.sql && psql -h postgres -U ${POSTGRES_USER} -d ${POSTGRES_DB} -f architecture/2026/11-identity-core-schema.sql && psql -h postgres -U ${POSTGRES_USER} -d ${POSTGRES_DB} -f architecture/2026/14-server-plane-schema-additions.sql && psql -h postgres -U ${POSTGRES_USER} -d ${POSTGRES_DB} -f architecture/2026/18-saas-hardening-schema.sql" ] volumes: - ./:/workspace depends_on: postgres: condition: service_healthy volumes: yakpanel_postgres_data: yakpanel_redis_data: yakpanel_minio_data: yakpanel_panel_data: yakpanel_prometheus_data: yakpanel_grafana_data: