version: '3.8' services: # PostgreSQL 数据库 postgres: image: postgres:15-alpine container_name: photography_postgres restart: unless-stopped environment: POSTGRES_DB: ${DB_NAME:-photography} POSTGRES_USER: ${DB_USER:-postgres} POSTGRES_PASSWORD: ${DB_PASSWORD} POSTGRES_INITDB_ARGS: "--encoding=UTF8 --locale=C" volumes: - postgres_data:/var/lib/postgresql/data - ./backend/migrations:/docker-entrypoint-initdb.d ports: - "127.0.0.1:5432:5432" networks: - photography_network healthcheck: test: ["CMD-SHELL", "pg_isready -U ${DB_USER:-postgres} -d ${DB_NAME:-photography}"] interval: 30s timeout: 10s retries: 5 # Redis 缓存 redis: image: redis:7-alpine container_name: photography_redis restart: unless-stopped command: redis-server --appendonly yes --requirepass ${REDIS_PASSWORD} volumes: - redis_data:/data ports: - "127.0.0.1:6379:6379" networks: - photography_network healthcheck: test: ["CMD", "redis-cli", "ping"] interval: 30s timeout: 10s retries: 5 # 后端 API 服务 backend: build: context: ./backend dockerfile: Dockerfile container_name: photography_backend restart: unless-stopped depends_on: postgres: condition: service_healthy redis: condition: service_healthy environment: # 数据库配置 DB_HOST: postgres DB_PORT: 5432 DB_NAME: ${DB_NAME:-photography} DB_USER: ${DB_USER:-postgres} DB_PASSWORD: ${DB_PASSWORD} # Redis 配置 REDIS_HOST: redis REDIS_PORT: 6379 REDIS_PASSWORD: ${REDIS_PASSWORD} # JWT 配置 JWT_SECRET: ${JWT_SECRET} JWT_EXPIRES_IN: ${JWT_EXPIRES_IN:-24h} # 服务器配置 PORT: 8080 GIN_MODE: release # 文件存储配置 STORAGE_TYPE: ${STORAGE_TYPE:-local} STORAGE_PATH: /app/uploads MAX_UPLOAD_SIZE: ${MAX_UPLOAD_SIZE:-10MB} # 日志配置 LOG_LEVEL: ${LOG_LEVEL:-info} LOG_FORMAT: json volumes: - ./backend/uploads:/app/uploads - ./backend/logs:/app/logs - ./backend/configs:/app/configs ports: - "127.0.0.1:8080:8080" networks: - photography_network healthcheck: test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:8080/health"] interval: 30s timeout: 10s retries: 5 start_period: 60s # 数据库备份服务 backup: image: postgres:15-alpine container_name: photography_backup restart: "no" depends_on: - postgres environment: PGPASSWORD: ${DB_PASSWORD} volumes: - ./backups:/backups - ./scripts/backup.sh:/backup.sh networks: - photography_network entrypoint: ["/backup.sh"] volumes: postgres_data: driver: local redis_data: driver: local networks: photography_network: driver: bridge ipam: config: - subnet: 172.20.0.0/16