services: # 数据库 postgres: image: postgres:17 container_name: bs-postgres restart: always environment: POSTGRES_USER: ${DB_USER} POSTGRES_PASSWORD: ${DB_PASSWORD} POSTGRES_DB: ${DB_NAME} ports: - "${DB_PORT}:5432" volumes: - ${DB_DATA_PATH}:${CONTAINER_BASE_PATH}/postgresql/data #此处使用主机的实际路径,不用再写顶层的volumes labels: # Traefik 配置 - "traefik.enable=true" - "traefik.docker.network=bs-network" - "traefik.http.routers.postgres.rule=Host(`localhost`) && PathPrefix(`/postgres`)" - "traefik.http.services.postgres.loadbalancer.server.port=5432" healthcheck: test: ["CMD-SHELL", "pg_isready -U ${DB_USER} -d ${DB_NAME}"] interval: 30s timeout: 10s retries: 5 networks: - bs-network # redis redis: image: redis:8.4.1-alpine container_name: bs-redis restart: always ports: - "${REDIS_PORT}:6379" command: > redis-server --requirepass ${REDIS_PASSWORD} --dir ${CONTAINER_BASE_PATH}/data --logfile ${CONTAINER_BASE_PATH}/redis/logs/redis-server.log environment: - TZ=Asia/Shanghai volumes: # 数据持久化:宿主机路径 -> 容器/data(Redis默认数据目录) - type: bind source: ../redis/data target: ${CONTAINER_BASE_PATH}/data/ bind: create_host_path: true # 自动创建宿主机目录(无需手动建) # 日志挂载:宿主机路径 -> 容器日志目录 - type: bind source: ../redis/logs target: ${CONTAINER_BASE_PATH}/redis/logs/ bind: create_host_path: true # 自动创建日志目录 labels: # Traefik 配置 - "traefik.enable=true" - "traefik.docker.network=bs-network" - "traefik.http.routers.redis.rule=Host(`localhost`) && PathPrefix(`/redis`)" - "traefik.http.services.redis.loadbalancer.server.port=6379" healthcheck: test: ["CMD", "redis-cli", "-a", "${REDIS_PASSWORD}", "PING"] interval: 30s timeout: 10s retries: 5 networks: - bs-network # Traefik 服务 traefik: image: traefik:v3.6 container_name: bs-traefik restart: always ports: # HTTP 端口 - "80:80" # HTTPS 端口 - "443:443" # 仪表板端口 - "8080:8080" volumes: # 挂载 Docker 套接字以监控容器(Windows 兼容路径) - //var/run/docker.sock:/var/run/docker.sock command: # 启用 Docker 提供者 - "--providers.docker=true" # 启用仪表板 - "--api.dashboard=true" # 允许通过 HTTP 访问仪表板(开发环境) - "--api.insecure=true" # 设置入口点 - "--entrypoints.web.address=:80" - "--entrypoints.websecure.address=:443" # 允许不安全的 HTTP(开发环境) - "--entrypoints.web.http.redirections.entryPoint.to=websecure" - "--entrypoints.web.http.redirections.entryPoint.scheme=https" networks: - bs-network # Auth 服务 auth: build: context: ../backend/auth dockerfile: Dockerfile container_name: bs-auth restart: always ports: - "${AUTH_PORT}:8000" volumes: # 挂载宿主机代码目录到容器,实现实时同步 - type: bind source: ../backend/auth target: ${CONTAINER_BASE_PATH}/auth bind: create_host_path: true environment: - DB_HOST=postgres - DB_PORT=5432 - DB_USER=${DB_USER} - DB_PASSWORD=${DB_PASSWORD} - DB_NAME=${DB_NAME} - REDIS_HOST=redis - REDIS_PORT=6379 - REDIS_PASSWORD=${REDIS_PASSWORD} - PYTHONUNBUFFERED=1 # 禁用 Python 输出缓存,确保日志实时显示 - UVICORN_RELOAD_DIRS=/app # 辅助指定热重载监听目录 depends_on: - postgres - redis labels: # Traefik 配置 - "traefik.enable=true" - "traefik.docker.network=bs-network" - "traefik.http.routers.auth.rule=Host(`localhost`) && PathPrefix(`/auth`)" - "traefik.http.services.auth.loadbalancer.server.port=8000" healthcheck: test: ["CMD", "curl", "-f", "http://localhost:8000/health"] interval: 30s timeout: 10s retries: 3 networks: - bs-network # Nginx:托管前端静态资源(../frontend/dist),/api 转发到 auth nginx: image: nginx:latest container_name: bs-nginx restart: always ports: - "${FRONTEND_PORT}:80" volumes: - type: bind source: ../frontend/dist target: /usr/share/nginx/html read_only: true - type: bind source: ./nginx/default.conf target: /etc/nginx/conf.d/default.conf read_only: true depends_on: - auth networks: - bs-network networks: bs-network: driver: bridge