version: '3.8' services: postgres: image: postgres:16-alpine container_name: blog-postgres restart: always environment: POSTGRES_USER: blog POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-blog} POSTGRES_DB: linkshare POSTGRES_INITDB_ARGS: '--encoding=UTF-8' volumes: - ./volumes/postgres:/var/lib/postgresql/data - ./scripts/init-db.sql:/docker-entrypoint-initdb.d/init.sql:ro ports: - '${POSTGRES_PORT:-5432}:5432' healthcheck: test: ['CMD-SHELL', 'pg_isready -U blog -d linkshare'] interval: 10s timeout: 5s retries: 5 start_period: 40s networks: - blog-network redis: image: redis:7-alpine container_name: blog-redis restart: always ports: - '${REDIS_PORT:-6379}:6379' volumes: - ./volumes/redis:/data command: redis-server --appendonly yes --maxmemory 256mb --maxmemory-policy allkeys-lru healthcheck: test: ['CMD', 'redis-cli', 'ping'] interval: 10s timeout: 5s retries: 5 start_period: 40s networks: - blog-network api: build: context: . dockerfile: Dockerfile.api args: NODE_ENV: production container_name: blog-api restart: always ports: - '${API_PORT:-3001}:3001' environment: NODE_ENV: production DATABASE_URL: postgresql://blog:${POSTGRES_PASSWORD:-blog}@postgres:5432/linkshare?schema=public REDIS_HOST: redis REDIS_PORT: 6379 SESSION_COOKIE_SECURE: ${SESSION_COOKIE_SECURE:-true} APP_BASE_URL: ${APP_BASE_URL:-https://api.yourdomain.com} env_file: - .env depends_on: postgres: condition: service_healthy redis: condition: service_healthy command: > sh -c " echo '⏳ Waiting for database...' && sleep 15 && echo '🔧 Running database migrations...' && bunx prisma migrate deploy && echo '🌱 Seeding database...' && bunx prisma db seed || echo '⚠️ Seed skipped (data may already exist)' && echo '🚀 Starting application...' && node dist/main " healthcheck: test: [ 'CMD', 'node', '-e', "require('http').get('http://localhost:3001/health', (r) => {if(r.statusCode!==200)process.exit(1)})", ] interval: 30s timeout: 10s retries: 3 start_period: 60s networks: - blog-network # 资源限制 deploy: resources: limits: cpus: '2' memory: 2G reservations: cpus: '0.5' memory: 512M # 日志配置 logging: driver: 'json-file' options: max-size: '10m' max-file: '3' compress: 'true' volumes: postgres: driver: local redis: driver: local networks: blog-network: driver: bridge