5ddad0c5e5
目标:git clone 后 docker compose up -d 直接可用,无需任何手工准备。
变更:
- config.example/ → config/,config.example.yaml → config.yaml
不再需要 cp -r 与逐份修改
- 删除 .env / .env.example,值全部内置到 docker-compose.yml
(GoFrame 不展开配置文件中的 ${VAR},环境变量方案在 Go 侧不可用)
- 配置文件里的 ${VAR} 全部替换为字面默认值
- schema/04-users.sh 与 05-reset-passwords.sh 改为脚本内字面口令,
不再读取环境变量
- 新增 schema/13-seed-flow-package.sql 占位文件,说明套餐表为空的原因与补齐方式
- .gitignore 不再排除 config/ 与 .env(已无 .env)
- README 改为「一键启动」+「上线前必改」两张表
已验证:docker compose config 通过;compose 口令、各配置文件 DSN、
初始化脚本三处口令哈希一致;库名与 schema 中一致。
397 lines
11 KiB
YAML
397 lines
11 KiB
YAML
name: iotlcm
|
||
|
||
# ============================================================
|
||
# IotLCM 单机部署编排
|
||
#
|
||
# 快速开始:
|
||
# 1. cp .env.example .env # 填写镜像仓库与各项口令
|
||
# 2. cp -r config.example config # 逐份填写配置(见各文件内注释)
|
||
# 3. docker compose up -d
|
||
#
|
||
# 首次启动会自动建库并导入 schema(见 schema/README.md)。
|
||
#
|
||
# 可选服务(默认不启动):
|
||
# docker compose --profile with-mock up -d # 运营商接口挡板
|
||
# docker compose --profile with-nginx up -d # 自带反向代理
|
||
# ============================================================
|
||
|
||
services:
|
||
# ---------------- 基础组件 ----------------
|
||
mysql:
|
||
# 基础组件统走同一镜像仓库(`<REGISTRY>/library/`),版本在 .env 里固定
|
||
image: 'crpi-qflrqrxoohllkvgc.cn-chengdu.personal.cr.aliyuncs.com/library/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:/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", "mysqladmin", "ping", "-h", "127.0.0.1", "-piotlcm_root_2026"]
|
||
interval: 10s
|
||
timeout: 5s
|
||
retries: 10
|
||
start_period: 40s
|
||
|
||
redis:
|
||
image: 'crpi-qflrqrxoohllkvgc.cn-chengdu.personal.cr.aliyuncs.com/library/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-qflrqrxoohllkvgc.cn-chengdu.personal.cr.aliyuncs.com/library/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-qflrqrxoohllkvgc.cn-chengdu.personal.cr.aliyuncs.com/library/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-qflrqrxoohllkvgc.cn-chengdu.personal.cr.aliyuncs.com/iotlcm/iotlcm-admin-svr:latest'
|
||
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-qflrqrxoohllkvgc.cn-chengdu.personal.cr.aliyuncs.com/iotlcm/iotlcm-admin-ui:latest'
|
||
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-qflrqrxoohllkvgc.cn-chengdu.personal.cr.aliyuncs.com/iotlcm/iotlcm-openapi:latest'
|
||
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-qflrqrxoohllkvgc.cn-chengdu.personal.cr.aliyuncs.com/iotlcm/iotlcm-upstream-chan:latest'
|
||
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-qflrqrxoohllkvgc.cn-chengdu.personal.cr.aliyuncs.com/iotlcm/iotlcm-upstream-proxy:latest'
|
||
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-qflrqrxoohllkvgc.cn-chengdu.personal.cr.aliyuncs.com/iotlcm/iotlcm-worker-svr:latest'
|
||
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-qflrqrxoohllkvgc.cn-chengdu.personal.cr.aliyuncs.com/iotlcm/iotlcm-app-server:latest'
|
||
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-qflrqrxoohllkvgc.cn-chengdu.personal.cr.aliyuncs.com/iotlcm/iotlcm-app-web:latest'
|
||
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-qflrqrxoohllkvgc.cn-chengdu.personal.cr.aliyuncs.com/iotlcm/iotlcm-sms:latest'
|
||
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-qflrqrxoohllkvgc.cn-chengdu.personal.cr.aliyuncs.com/iotlcm/iotlcm-bot:latest'
|
||
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-qflrqrxoohllkvgc.cn-chengdu.personal.cr.aliyuncs.com/iotlcm/iotlcm-docs:latest'
|
||
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.example/upstream-chan 已预置该地址)
|
||
onelink-mock:
|
||
image: 'crpi-qflrqrxoohllkvgc.cn-chengdu.personal.cr.aliyuncs.com/iotlcm/iotlcm-onelink-mock:latest'
|
||
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.example/nginx/iotlcm.conf 把 location 段落到宿主机配置。
|
||
nginx:
|
||
image: 'crpi-qflrqrxoohllkvgc.cn-chengdu.personal.cr.aliyuncs.com/library/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
|