services: # ── 数据层 ── postgres: image: postgres:15-alpine environment: POSTGRES_DB: craftlabs_platform POSTGRES_USER: craftlabs POSTGRES_PASSWORD: ${DB_PASSWORD:-craftlabs} volumes: - pg_data:/var/lib/postgresql/data - ./init.sql:/docker-entrypoint-initdb.d/init.sql:ro ports: - "5432:5432" restart: unless-stopped healthcheck: test: ["CMD-SHELL", "pg_isready -U craftlabs -d craftlabs_platform"] interval: 10s timeout: 5s retries: 5 redis: image: redis:7-alpine command: redis-server --appendonly yes --requirepass ${REDIS_PASSWORD:-} volumes: - redis_data:/data ports: - "6379:6379" restart: unless-stopped healthcheck: test: ["CMD", "redis-cli", "ping"] interval: 10s timeout: 5s retries: 5 # ── 应用层 ── backend: build: context: ./delivery-platform-api dockerfile: Dockerfile image: craftlabs/delivery-platform-api:latest environment: SPRING_DATASOURCE_URL: jdbc:postgresql://postgres:5432/craftlabs_platform SPRING_DATASOURCE_USERNAME: craftlabs SPRING_DATASOURCE_PASSWORD: ${DB_PASSWORD:-craftlabs} SPRING_DATA_REDIS_HOST: redis SPRING_DATA_REDIS_PASSWORD: ${REDIS_PASSWORD:-} PLATFORM_JWT_SECRET: ${PLATFORM_JWT_SECRET:-dev-secret-at-least-32-chars-long} depends_on: postgres: condition: service_healthy redis: condition: service_healthy ports: - "8080:8080" restart: unless-stopped webhook: build: context: ./license-webhook-ingress dockerfile: Dockerfile image: craftlabs/license-webhook-ingress:latest environment: SPRING_DATASOURCE_URL: jdbc:postgresql://postgres:5432/craftlabs_platform SPRING_DATASOURCE_USERNAME: craftlabs SPRING_DATASOURCE_PASSWORD: ${DB_PASSWORD:-craftlabs} CRAFTLABS_WEBHOOK_EXPECTED_TOKEN: ${CRAFTLABS_WEBHOOK_EXPECTED_TOKEN:-} depends_on: postgres: condition: service_healthy ports: - "8081:8081" restart: unless-stopped frontend: build: context: ../web/delivery-platform-ui dockerfile: Dockerfile image: craftlabs/delivery-platform-ui:latest ports: - "80:80" depends_on: - backend restart: unless-stopped # ── 接入层 ── nginx: image: nginx:alpine volumes: - ./nginx/default.conf:/etc/nginx/conf.d/default.conf:ro ports: - "443:443" depends_on: - backend - webhook - frontend restart: unless-stopped # ── 监控层(可选) ── prometheus: image: prom/prometheus:latest volumes: - ./prometheus/prometheus.yml:/etc/prometheus/prometheus.yml:ro - prometheus_data:/prometheus command: - '--config.file=/etc/prometheus/prometheus.yml' - '--storage.tsdb.path=/prometheus' ports: - "9090:9090" restart: unless-stopped grafana: image: grafana/grafana:latest environment: GF_SECURITY_ADMIN_PASSWORD: ${GRAFANA_ADMIN_PASSWORD:-admin} volumes: - ./grafana/datasources:/etc/grafana/provisioning/datasources:ro - grafana_data:/var/lib/grafana ports: - "3000:3000" depends_on: - prometheus restart: unless-stopped volumes: pg_data: redis_data: prometheus_data: grafana_data: