services: postgres: image: postgis/postgis:17-3.5 container_name: ciyuan-postgres environment: POSTGRES_USER: "${POSTGRES_USER:-shiran}" POSTGRES_PASSWORD: "${POSTGRES_PASSWORD:-change-me-postgres-password}" POSTGRES_DB: "${POSTGRES_DB:-ciyuan_viewfinder}" PGDATA: /var/lib/postgresql/data/pgdata expose: - "5432" volumes: - pgdata:/var/lib/postgresql/data - ./pg_backup:/backups - ./docker/postgres/init:/docker-entrypoint-initdb.d:ro healthcheck: test: ["CMD-SHELL", "pg_isready -U $${POSTGRES_USER} -d $${POSTGRES_DB}"] interval: 10s timeout: 5s retries: 10 restart: unless-stopped networks: - ciyuan-net redis: image: redis:7-alpine container_name: ciyuan-redis expose: - "6379" volumes: - redisdata:/data healthcheck: test: ["CMD", "redis-cli", "ping"] interval: 10s timeout: 5s retries: 10 restart: unless-stopped networks: - ciyuan-net minio: image: minio/minio:latest container_name: ciyuan-minio command: server /data --console-address ":9001" environment: MINIO_ROOT_USER: "${MINIO_ROOT_USER:-minioadmin}" MINIO_ROOT_PASSWORD: "${MINIO_ROOT_PASSWORD:-minioadmin}" expose: - "9000" - "9001" volumes: - miniodata:/data restart: unless-stopped networks: - ciyuan-net server: build: context: ./server container_name: ciyuan-server environment: DATABASE_URL: "postgresql+asyncpg://${POSTGRES_USER:-shiran}:${POSTGRES_PASSWORD:-change-me-postgres-password}@postgres:5432/${POSTGRES_DB:-ciyuan_viewfinder}" DATABASE_URL_SYNC: "postgresql://${POSTGRES_USER:-shiran}:${POSTGRES_PASSWORD:-change-me-postgres-password}@postgres:5432/${POSTGRES_DB:-ciyuan_viewfinder}" REDIS_URL: redis://redis:6379/0 SECRET_KEY: "${SECRET_KEY:-change-me-before-production}" ACCESS_TOKEN_EXPIRE_MINUTES: "${ACCESS_TOKEN_EXPIRE_MINUTES:-43200}" REFRESH_TOKEN_EXPIRE_DAYS: "${REFRESH_TOKEN_EXPIRE_DAYS:-60}" STORAGE_BACKEND: local LOCAL_STORAGE_PATH: /app/uploads S3_ENDPOINT: http://minio:9000 S3_ACCESS_KEY: "${MINIO_ROOT_USER:-minioadmin}" S3_SECRET_KEY: "${MINIO_ROOT_PASSWORD:-minioadmin}" S3_BUCKET: "${S3_BUCKET:-ciyuan-viewfinder}" TENCENT_MAP_KEY: "${TENCENT_MAP_KEY:-}" LOG_LEVEL: "${LOG_LEVEL:-INFO}" LOG_JSON: "${LOG_JSON:-false}" expose: - "8000" volumes: - server_uploads:/app/uploads depends_on: postgres: condition: service_healthy redis: condition: service_healthy minio: condition: service_started healthcheck: test: [ "CMD", "python", "-c", "import urllib.request; urllib.request.urlopen('http://127.0.0.1:8000/', timeout=5)", ] interval: 15s timeout: 10s retries: 10 start_period: 30s restart: unless-stopped networks: - ciyuan-net admin-web: build: context: ./admin-web args: VITE_API_BASE: /api/v1 container_name: ciyuan-admin-web expose: - "80" depends_on: server: condition: service_healthy restart: unless-stopped networks: - ciyuan-net clients: build: context: ./clients container_name: ciyuan-clients expose: - "80" depends_on: server: condition: service_healthy restart: unless-stopped networks: - ciyuan-net nginx: image: nginx:1.27-alpine container_name: ciyuan-nginx ports: - "${CLIENT_WEB_PORT:-5173}:80" - "${ADMIN_WEB_PORT:-5174}:81" volumes: - ./docker/nginx/default.conf:/etc/nginx/conf.d/default.conf:ro depends_on: server: condition: service_healthy admin-web: condition: service_started clients: condition: service_started restart: unless-stopped networks: - ciyuan-net volumes: pgdata: redisdata: miniodata: server_uploads: networks: ciyuan-net: driver: bridge