name: iotlcm # ============================================================ # IotLCM 单机部署编排 # # 快速开始: # 1. docker compose up -d # 配置文件和初始口令均已内置;正式部署前按 README.md 修改默认口令。 # # 首次启动会自动建库并导入 schema(见 schema/README.md)。 # # 可选服务(默认不启动): # docker compose --profile with-mock up -d # 运营商接口挡板 # docker compose --profile with-nginx up -d # 自带反向代理 # ============================================================ services: # ---------------- 基础组件 ---------------- mysql: # 基础组件统走同一镜像仓库(`/iotlcm/`),版本在此固定 image: 'crpi-qflrqrxoohlkkvgc.cn-chengdu.personal.cr.aliyuncs.com/iotlcm/iotlcm:mysql-8.0' container_name: iotlcm-mysql restart: always ports: - "3306:3306" environment: MYSQL_ROOT_PASSWORD: 'Iotlcm2026Default' MYSQL_DATABASE: 'db_iotlcm' TZ: 'Asia/Shanghai' volumes: - ./data/mysql:/var/lib/mysql # 仅在 data/mysql 为空(首次启动)时执行 schema/init.sql - ./schema:/docker-entrypoint-initdb.d:ro command: - --character-set-server=utf8mb4 - --collation-server=utf8mb4_general_ci - --default-time-zone=+08:00 networks: - iotlcm-network healthcheck: test: ["CMD-SHELL", "MYSQL_PWD=\"$$MYSQL_ROOT_PASSWORD\" mysqladmin ping -h 127.0.0.1 -u root --silent"] interval: 10s timeout: 5s retries: 10 start_period: 40s redis: image: 'crpi-qflrqrxoohlkkvgc.cn-chengdu.personal.cr.aliyuncs.com/iotlcm/iotlcm:redis-7.2' container_name: iotlcm-redis restart: always ports: - "6379:6379" environment: TZ: 'Asia/Shanghai' command: - redis-server - --requirepass - 'Iotlcm2026Default' - --appendonly - "yes" volumes: - ./data/redis:/data networks: - iotlcm-network healthcheck: test: ["CMD", "redis-cli", "-a", "Iotlcm2026Default", "ping"] interval: 10s timeout: 5s retries: 5 rabbitmq: image: 'crpi-qflrqrxoohlkkvgc.cn-chengdu.personal.cr.aliyuncs.com/iotlcm/iotlcm:rabbitmq-4.3.5-management' container_name: iotlcm-rabbitmq hostname: rabbitmq restart: always ports: - "5672:5672" - "15672:15672" environment: RABBITMQ_DEFAULT_USER: 'iotlcm' RABBITMQ_DEFAULT_PASS: 'Iotlcm2026Default' TZ: 'Asia/Shanghai' volumes: - ./data/rabbitmq:/var/lib/rabbitmq networks: - iotlcm-network healthcheck: test: ["CMD", "rabbitmq-diagnostics", "-q", "ping"] interval: 30s timeout: 10s retries: 5 start_period: 30s consul: image: 'crpi-qflrqrxoohlkkvgc.cn-chengdu.personal.cr.aliyuncs.com/iotlcm/iotlcm:consul-1.22' container_name: iotlcm-consul restart: always ports: - "8500:8500" environment: TZ: 'Asia/Shanghai' CONSUL_LOCAL_CONFIG: | { "node_name": "iotlcm-node", "bind_addr": "0.0.0.0", "client_addr": "0.0.0.0", "datacenter": "dc1", "data_dir": "/consul/data", "server": true, "bootstrap_expect": 1, "ui": true, "connect": { "enabled": true } } volumes: - ./data/consul:/consul/data networks: - iotlcm-network # ---------------- 业务服务 ---------------- admin-svr: image: 'crpi-qflrqrxoohlkkvgc.cn-chengdu.personal.cr.aliyuncs.com/iotlcm/iotlcm:iotlcm-admin-svr-v1.0.4' container_name: iotlcm-admin-svr restart: always ports: - "127.0.0.1:8008:8008" environment: TZ: 'Asia/Shanghai' volumes: - ./config/admin-svr:/app/config:ro - ./data/logs/admin-svr:/app/logs - ./data/upload:/app/upload - ./data/upload:/app/resource/upload networks: - iotlcm-network depends_on: mysql: condition: service_healthy redis: condition: service_healthy rabbitmq: condition: service_healthy admin-ui: image: 'crpi-qflrqrxoohlkkvgc.cn-chengdu.personal.cr.aliyuncs.com/iotlcm/iotlcm:iotlcm-admin-ui-v1.0.4' container_name: iotlcm-admin-ui restart: always ports: - "127.0.0.1:8009:80" environment: TZ: 'Asia/Shanghai' volumes: - ./config/admin-ui/default.conf:/etc/nginx/conf.d/default.conf:ro - ./data/logs/admin-ui:/var/log/nginx - ./data/upload:/app/upload networks: - iotlcm-network depends_on: - admin-svr openapi: image: 'crpi-qflrqrxoohlkkvgc.cn-chengdu.personal.cr.aliyuncs.com/iotlcm/iotlcm:iotlcm-openapi-v1.0.4' container_name: iotlcm-openapi restart: always ports: - "127.0.0.1:8000:8000" environment: TZ: 'Asia/Shanghai' volumes: - ./config/openapi:/app/config:ro - ./data/logs/openapi:/app/logs networks: - iotlcm-network depends_on: mysql: condition: service_healthy redis: condition: service_healthy rabbitmq: condition: service_healthy upstream-chan: image: 'crpi-qflrqrxoohlkkvgc.cn-chengdu.personal.cr.aliyuncs.com/iotlcm/iotlcm:iotlcm-upstream-chan-v1.0.4' container_name: iotlcm-upstream-chan restart: always ports: - "8110:8110" - "8310:8310" environment: TZ: 'Asia/Shanghai' volumes: - ./config/upstream-chan:/app/config:ro - ./data/logs/upstream-chan:/app/logs - ./data/upload:/app/upload - ./data/upload:/app/resource/upload networks: - iotlcm-network depends_on: mysql: condition: service_healthy redis: condition: service_healthy consul: condition: service_started upstream-proxy: image: 'crpi-qflrqrxoohlkkvgc.cn-chengdu.personal.cr.aliyuncs.com/iotlcm/iotlcm:iotlcm-upstream-proxy-v1.0.4' container_name: iotlcm-upstream-proxy restart: always ports: - "8510:8510" environment: TZ: 'Asia/Shanghai' volumes: - ./config/upstream-proxy:/app/config:ro - ./data/logs/upstream-proxy:/app/logs - ./data/upload:/app/upload - ./data/upload:/app/resource/upload - ./data/tmp:/app/tmp networks: - iotlcm-network depends_on: mysql: condition: service_healthy redis: condition: service_healthy consul: condition: service_started worker-svr: image: 'crpi-qflrqrxoohlkkvgc.cn-chengdu.personal.cr.aliyuncs.com/iotlcm/iotlcm:iotlcm-worker-svr-v1.0.4' container_name: iotlcm-worker-svr restart: always environment: TZ: 'Asia/Shanghai' volumes: - ./config/worker-svr:/app/config:ro - ./data/logs/worker-svr:/app/logs - ./data/logs/worker-svr/full-sync:/app/logs/full-sync - ./data/upload:/app/upload - ./data/upload:/app/resource/upload networks: - iotlcm-network depends_on: mysql: condition: service_healthy redis: condition: service_healthy rabbitmq: condition: service_healthy app-server: image: 'crpi-qflrqrxoohlkkvgc.cn-chengdu.personal.cr.aliyuncs.com/iotlcm/iotlcm:iotlcm-app-server-v1.0.2' container_name: iotlcm-app-server restart: always ports: - "127.0.0.1:8010:8010" environment: TZ: 'Asia/Shanghai' APP_UPLOAD_DIR: /app/resource/upload volumes: - ./config/app-server:/app/config:ro - ./data/upload:/app/resource/upload - ./data/logs/app-server:/app/resource/log/server networks: - iotlcm-network depends_on: mysql: condition: service_healthy redis: condition: service_healthy app-web: image: 'crpi-qflrqrxoohlkkvgc.cn-chengdu.personal.cr.aliyuncs.com/iotlcm/iotlcm:iotlcm-app-web-v1.0.2' container_name: iotlcm-app-web restart: always ports: - "127.0.0.1:8018:80" environment: TZ: 'Asia/Shanghai' volumes: - ./data/logs/app-web:/var/log/nginx networks: - iotlcm-network sms: image: 'crpi-qflrqrxoohlkkvgc.cn-chengdu.personal.cr.aliyuncs.com/iotlcm/iotlcm:iotlcm-sms-v1.0.4' container_name: iotlcm-sms hostname: iotlcm-sms restart: always environment: TZ: 'Asia/Shanghai' HTTP_ADDR: ':11190' GRPC_ADDR: ':11200' ports: - "11190:11190" - "11200:11200" volumes: - ./config/sms:/app/config:ro - ./data/logs/sms:/app/logs tmpfs: - /tmp security_opt: - no-new-privileges:true healthcheck: test: ["CMD", "wget", "--quiet", "--output-document=/dev/null", "http://127.0.0.1:11190/healthz"] interval: 10s timeout: 3s retries: 3 start_period: 5s networks: - iotlcm-network bot: image: 'crpi-qflrqrxoohlkkvgc.cn-chengdu.personal.cr.aliyuncs.com/iotlcm/iotlcm:iotlcm-bot-v1.0.4' container_name: iotlcm-bot restart: unless-stopped environment: TZ: 'Asia/Shanghai' command: ["watch", "--config", "/app/config/config.yaml"] volumes: - ./config/bot/config.yaml:/app/config/config.yaml:ro - ./data/logs/worker-svr/full-sync:/data/full-sync:ro - ./data/bot-state:/data/state networks: - iotlcm-network profiles: - with-bot docs: image: 'crpi-qflrqrxoohlkkvgc.cn-chengdu.personal.cr.aliyuncs.com/iotlcm/iotlcm:iotlcm-docs-v1.0.4' container_name: iotlcm-docs restart: unless-stopped ports: - "127.0.0.1:8019:80" networks: - iotlcm-network # ---------------- 可选:运营商接口挡板 ---------------- # 模拟中国移动 OneLink 接口,用于在没有真实运营商环境时联调整条链路: # admin-svr → worker-svr → upstream-chan → onelink-mock # # 启用:docker compose --profile with-mock up -d # 启用后 upstream-chan 的 sim_yd_mock_v5.url 指向 http://onelink-mock:8080/v5/ # (config/upstream-chan 已预置该地址) onelink-mock: image: 'crpi-qflrqrxoohlkkvgc.cn-chengdu.personal.cr.aliyuncs.com/iotlcm/iotlcm:iotlcm-onelink-mock-v1.0.4' container_name: iotlcm-onelink-mock restart: unless-stopped ports: - "127.0.0.1:8080:8080" environment: TZ: 'Asia/Shanghai' BAFFLE_ADDR: ':8080' BAFFLE_SQLITE_PATH: /app/data/onelink_mock.db volumes: - ./data/mock:/app/data - ./data/logs/mock:/app/logs networks: - iotlcm-network healthcheck: test: ["CMD", "wget", "--quiet", "--output-document=/dev/null", "http://127.0.0.1:8080/api.json"] interval: 30s timeout: 5s retries: 3 start_period: 10s profiles: - with-mock # ---------------- 可选:反向代理 ---------------- # 若宿主机已有 nginx / 面板,可不启动本容器, # 参考 config/nginx/iotlcm.conf 把 location 段落到宿主机配置。 nginx: image: 'crpi-qflrqrxoohlkkvgc.cn-chengdu.personal.cr.aliyuncs.com/iotlcm/iotlcm:nginx-1.30' container_name: iotlcm-nginx restart: always ports: - "80:80" volumes: - ./config/nginx:/etc/nginx/conf.d:ro - ./data/logs/nginx:/var/log/nginx - ./data/upload:/app/upload networks: - iotlcm-network depends_on: - admin-ui - openapi - app-web - docs profiles: - with-nginx networks: iotlcm-network: driver: bridge name: iotlcm-network