# ============================================================ # Weather Data System - Docker Compose 部署编排 # # 前置条件: # 1. 安装 Docker Engine 20.10+ 和 Docker Compose v2 # 2. 复制 .env 文件并修改配置 # 3. 确保 JAR 文件已构建到对应 target/ 目录 # 4. 确保前端已构建到 weather-data-ui/dist/ # # 启动: docker compose up -d # 停止: docker compose down # 日志: docker compose logs -f [服务名] # ============================================================ services: # ========================================================== # MySQL 数据库 # ========================================================== mysql: image: mysql:8.0 container_name: weather-mysql restart: unless-stopped environment: MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD} MYSQL_DATABASE: ${MYSQL_DATABASE:-weather_data_system} MYSQL_USER: ${MYSQL_USER:-weather} MYSQL_PASSWORD: ${MYSQL_PASSWORD} TZ: Asia/Shanghai ports: - "${MYSQL_PORT:-3306}:3306" volumes: - mysql-data:/var/lib/mysql - ./deploy/mysql/init:/docker-entrypoint-initdb.d:ro # 初始化 SQL command: - --character-set-server=utf8mb4 - --collation-server=utf8mb4_unicode_ci - --default-time-zone=+08:00 - --max-allowed-packet=128M healthcheck: test: ["CMD", "mysqladmin", "ping", "-h", "localhost", "-u", "root", "-p${MYSQL_ROOT_PASSWORD}"] interval: 10s timeout: 5s retries: 10 start_period: 60s networks: - weather-net # ========================================================== # Redis 缓存 # ========================================================== redis: image: redis:7-alpine container_name: weather-redis restart: unless-stopped command: - redis-server - --appendonly yes - --requirepass ${REDIS_PASSWORD} ports: - "${REDIS_PORT:-6379}:6379" volumes: - redis-data:/data healthcheck: test: ["CMD", "redis-cli", "-a", "${REDIS_PASSWORD}", "ping"] interval: 10s timeout: 5s retries: 5 networks: - weather-net # ========================================================== # 管理后台 (Spring Boot Admin) # ========================================================== admin: build: context: ./system-admin dockerfile: Dockerfile image: weather-data-admin:${APP_VERSION:-latest} container_name: weather-admin restart: unless-stopped depends_on: mysql: condition: service_healthy redis: condition: service_healthy environment: SPRING_PROFILES_ACTIVE: ${SPRING_PROFILES_ACTIVE:-prod} JAVA_OPTS: ${JAVA_OPTS:--Xms256m -Xmx512m -XX:+UseG1GC} TZ: Asia/Shanghai # 覆盖 application.yml 中的数据库/Redis 配置 SPRING_DATASOURCE_DRUID_URL: jdbc:mysql://mysql:3306/${MYSQL_DATABASE:-weather_data_system}?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&nullCatalogMeansCurrent=true&rewriteBatchedStatements=true SPRING_DATASOURCE_DRUID_USERNAME: ${MYSQL_USER:-weather} SPRING_DATASOURCE_DRUID_PASSWORD: ${MYSQL_PASSWORD} SPRING_DATA_REDIS_HOST: redis SPRING_DATA_REDIS_PORT: 6379 SPRING_DATA_REDIS_PASSWORD: ${REDIS_PASSWORD} ports: - "${ADMIN_PORT:-8080}:8080" volumes: - admin-logs:/app/logs - admin-uploads:/app/upload networks: - weather-net # ========================================================== # API 服务 # ========================================================== api: build: context: ./system-api dockerfile: Dockerfile image: weather-data-api:${APP_VERSION:-latest} container_name: weather-api restart: unless-stopped depends_on: mysql: condition: service_healthy redis: condition: service_healthy environment: SPRING_PROFILES_ACTIVE: ${SPRING_PROFILES_ACTIVE:-prod} JAVA_OPTS: ${JAVA_OPTS:--Xms256m -Xmx512m -XX:+UseG1GC} TZ: Asia/Shanghai SPRING_DATASOURCE_DRUID_URL: jdbc:mysql://mysql:3306/${MYSQL_DATABASE:-weather_data_system}?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&nullCatalogMeansCurrent=true&rewriteBatchedStatements=true SPRING_DATASOURCE_DRUID_USERNAME: ${MYSQL_USER:-weather} SPRING_DATASOURCE_DRUID_PASSWORD: ${MYSQL_PASSWORD} SPRING_DATA_REDIS_HOST: redis SPRING_DATA_REDIS_PORT: 6379 SPRING_DATA_REDIS_PASSWORD: ${REDIS_PASSWORD} ports: - "${API_PORT:-8081}:8081" volumes: - api-logs:/app/logs - api-uploads:/app/upload networks: - weather-net # ========================================================== # 前端 UI # ========================================================== ui: build: context: ./weather-data-ui dockerfile: ${UI_DOCKERFILE:-Dockerfile.offline} image: weather-data-ui:${APP_VERSION:-latest} container_name: weather-ui restart: unless-stopped depends_on: - admin - api networks: - weather-net # ========================================================== # Gateway - 统一入口 Nginx 反向代理 # ========================================================== gateway: image: nginx:alpine container_name: weather-gateway restart: unless-stopped depends_on: - ui - admin - api ports: - "${GATEWAY_PORT:-80}:80" volumes: - ./deploy/nginx/nginx.conf:/etc/nginx/conf.d/default.conf:ro - gateway-logs:/var/log/nginx healthcheck: test: ["CMD", "wget", "-qO-", "http://localhost/"] interval: 30s timeout: 5s retries: 3 networks: - weather-net # ============================================================ # 数据卷 (持久化存储) # ============================================================ volumes: mysql-data: name: weather-mysql-data redis-data: name: weather-redis-data admin-logs: name: weather-admin-logs admin-uploads: name: weather-admin-uploads api-logs: name: weather-api-logs api-uploads: name: weather-api-uploads gateway-logs: name: weather-gateway-logs # ============================================================ # 网络 # ============================================================ networks: weather-net: name: weather-net driver: bridge