version: '3.8'

services:
  # MySQL Database Service
  mysql-db:
    image: mysql:5.7
    container_name: mqtt_mysql_db
    restart: unless-stopped
    environment:
      MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD:-supersecretpassword} # 请通过环境变量或OneDev Secrets在生产中设置此密码
      MYSQL_DATABASE: ${MYSQL_DATABASE:-mqtt_power}
      MYSQL_USER: ${MYSQL_USER:-appuser}
      MYSQL_PASSWORD: ${MYSQL_PASSWORD:-apppassword} # 请通过环境变量或OneDev Secrets在生产中设置此密码
    ports:
      # 仅在需要从外部直接访问数据库时暴露端口 (例如用于调试或外部工具)
      # 对于应用容器，它们将通过Docker内部网络连接
      - "33061:3306" # 示例：将容器的3306映射到主机的33061
    volumes:
      - mysql_data:/var/lib/mysql
      # 挂载初始化SQL脚本，当容器首次启动且数据目录为空时执行
      - ./springboot-init-main/sql/mqtt_power.sql:/docker-entrypoint-initdb.d/init_schema.sql
    networks:
      - app-network
    healthcheck:
      test: ["CMD", "mysqladmin" ,"ping", "-h", "localhost", "-u$$MYSQL_USER", "-p$$MYSQL_PASSWORD"]
      interval: 10s
      timeout: 5s
      retries: 5

  # EMQX MQTT Broker Service
  emqx:
    image: emqx/emqx:5.6.0 # 使用较新的 EMQX 5 版本
    container_name: mqtt_emqx_broker
    restart: unless-stopped
    ports:
      - "1883:1883"  # MQTT default port
      - "8083:8083"  # MQTT over WebSocket
      - "8084:8084"  # MQTT over SSL/TLS WebSocket
      - "8883:8883"  # MQTT over SSL/TLS
      - "18083:18083" # EMQX Dashboard / HTTP API
    volumes:
      - emqx_data:/opt/emqx/data
      - emqx_log:/opt/emqx/log
      # 如果有自定义配置，可以挂载 emqx.conf 或 mounted_plugins 等
      # - ./emqx_conf/emqx.conf:/opt/emqx/etc/emqx.conf
    networks:
      - app-network
    healthcheck:
      test: ["CMD", "/opt/emqx/bin/emqx_ctl", "status"]
      interval: 30s
      timeout: 10s
      retries: 3
    environment:
      EMQX_NODE_NAME: "emqx@node1.emqx.io" # 可以自定义节点名
      EMQX_LISTENER__TCP__EXTERNAL: "1883"
      EMQX_LISTENER__WS__EXTERNAL: "8083"
      EMQX_DASHBOARD__LISTENER__HTTP: "18083"
      # 更多 EMQX 配置可以通过环境变量设置，参考 EMQX 文档

  # Backend Spring Boot Application Service
  backend-app:
    image: mqtt-springboot-app:latest # 修改为本地镜像名
    container_name: mqtt_springboot_app_prod
    restart: unless-stopped
    depends_on:
      mysql-db: # 确保数据库先启动并健康
        condition: service_healthy
      emqx: # 确保 MQTT Broker 先启动并健康
        condition: service_healthy
    ports:
      - "7529:7529"
    environment:
      # Spring Boot Profile
      SPRING_PROFILES_ACTIVE: prod # 或者其他生产环境profile
      # Database connection (连接到此 compose 文件中的 mysql-db 服务)
      DB_HOST: mysql-db
      DB_PORT: 3306
      DB_NAME: ${MYSQL_DATABASE:-mqtt_power}
      DB_USER: ${MYSQL_USER:-appuser}
      DB_PASSWORD: ${MYSQL_PASSWORD:-apppassword} # 确保与 mysql-db 中 MYSQL_PASSWORD 一致
      # MQTT Broker connection (连接到此 compose 文件中的 emqx 服务)
      MQTT_BROKER_URL: tcp://emqx:1883
      # MQTT_USERNAME: # 如果 EMQX 设置了认证
      # MQTT_PASSWORD: # 如果 EMQX 设置了认证
      # 其他后端应用所需的环境变量
      # ...
    networks:
      - app-network
    # 如果需要，可以添加 healthcheck
    # healthcheck:
    #   test: ["CMD", "curl", "-f", "http://localhost:7529/api/actuator/health"] # 假设有 actuator health 端点
    #   interval: 30s
    #   timeout: 10s
    #   retries: 3

  # Frontend Next.js Application Service
  frontend-app:
    image: mqtt-nextjs-app:latest # 修改为本地镜像名
    container_name: mqtt_nextjs_app_prod
    restart: unless-stopped
    ports:
      - "3000:3000"
    environment:
      # API 地址，指向后端服务的容器名和端口 (如果前端直接调用API)
      # 如果 Next.js 使用了 next.config.js/mjs 中的 rewrites 代理 /api 到后端，则这里可能不需要
      # NEXT_PUBLIC_API_URL: http://backend-app:7529/api
      # 如果前端需要连接 MQTT Broker (例如通过 WebSocket)
      NEXT_PUBLIC_MQTT_WS_URL: ws://emqx:8083/mqtt # 指向 EMQX 的 WebSocket 端口
      # 其他前端应用所需的环境变量
      # ...
    networks:
      - app-network
    depends_on: # 可选，如果前端启动时需要后端已启动
      - backend-app
      # - emqx # 如果前端直接依赖 MQTT Broker

volumes:
  mysql_data: # 持久化 MySQL 数据
  emqx_data:  # 持久化 EMQX 数据
  emqx_log:   # 持久化 EMQX 日志

networks:
  app-network:
    driver: bridge 