init: IotLCM 开源版部署仓
内容: - docker-compose.yml:14 个基础/业务服务 + 3 个可选 profile(with-mock 挡板、with-bot、with-nginx) - .env.example:集中管理镜像仓库、口令、端口;必填项缺失时 compose 直接报错退出 - config.example/:10 份配置模板,全部为占位值与注释说明 - schema/:12 个初始化脚本,按文件名顺序由 MySQL initdb 自动执行 脱敏处理: - 生产/内网 IP、镜像仓库地址、公司名、真实域名全部清除 - 演示账号保留 18 个(出库与划拨依赖账号与部门树的关联), 昵称/邮箱/手机号/登录IP/头像改为占位或编造值 - 数据库账号与 admin 口令改为初始化时按 .env 注入计算 - 通道模板与 Mock 通道的上游密钥置空 - Mock 通道地址指向 compose 内 onelink-mock 服务 部署时用 --profile with-mock 启动运营商接口挡板,即可在无真实运营商环境时跑通全链路。
This commit is contained in:
@@ -0,0 +1,397 @@
|
||||
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:
|
||||
image: '${REGISTRY:-your-registry}/library/mysql:8.0'
|
||||
container_name: iotlcm-mysql
|
||||
restart: always
|
||||
ports:
|
||||
- "${MYSQL_PORT:-3306}:3306"
|
||||
environment:
|
||||
MYSQL_ROOT_PASSWORD: '${MYSQL_ROOT_PASSWORD:?必须在 .env 中设置}'
|
||||
MYSQL_DATABASE: '${MYSQL_DATABASE:-db_iotlcm}'
|
||||
MYSQL_APP_PASSWORD: '${MYSQL_APP_PASSWORD:?必须在 .env 中设置}'
|
||||
MYSQL_ADMIN_PASSWORD: '${MYSQL_ADMIN_PASSWORD:?必须在 .env 中设置}'
|
||||
TZ: '${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", "-p${MYSQL_ROOT_PASSWORD}"]
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
retries: 10
|
||||
start_period: 40s
|
||||
|
||||
redis:
|
||||
image: '${REGISTRY:-your-registry}/library/redis:7.2'
|
||||
container_name: iotlcm-redis
|
||||
restart: always
|
||||
ports:
|
||||
- "${REDIS_PORT:-6379}:6379"
|
||||
environment:
|
||||
TZ: '${TZ:-Asia/Shanghai}'
|
||||
command:
|
||||
- redis-server
|
||||
- --requirepass
|
||||
- '${REDIS_PASSWORD:?必须在 .env 中设置}'
|
||||
- --appendonly
|
||||
- "yes"
|
||||
volumes:
|
||||
- ./data/redis:/data
|
||||
networks:
|
||||
- iotlcm-network
|
||||
healthcheck:
|
||||
test: ["CMD", "redis-cli", "-a", "${REDIS_PASSWORD}", "ping"]
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
|
||||
rabbitmq:
|
||||
image: '${REGISTRY:-your-registry}/library/rabbitmq:4.3.5-management'
|
||||
container_name: iotlcm-rabbitmq
|
||||
hostname: rabbitmq
|
||||
restart: always
|
||||
ports:
|
||||
- "${RABBITMQ_PORT:-5672}:5672"
|
||||
- "${RABBITMQ_MGMT_PORT:-15672}:15672"
|
||||
environment:
|
||||
RABBITMQ_DEFAULT_USER: '${RABBITMQ_USER:-iotlcm}'
|
||||
RABBITMQ_DEFAULT_PASS: '${RABBITMQ_PASSWORD:?必须在 .env 中设置}'
|
||||
TZ: '${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: '${REGISTRY:-your-registry}/library/consul:1.22'
|
||||
container_name: iotlcm-consul
|
||||
restart: always
|
||||
ports:
|
||||
- "${CONSUL_PORT:-8500}:8500"
|
||||
environment:
|
||||
TZ: '${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: '${REGISTRY:-your-registry}/iotlcm/iotlcm-admin-svr:${TAG:-latest}'
|
||||
container_name: iotlcm-admin-svr
|
||||
restart: always
|
||||
ports:
|
||||
- "127.0.0.1:${ADMIN_SVR_PORT:-8008}:8008"
|
||||
environment:
|
||||
TZ: '${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: '${REGISTRY:-your-registry}/iotlcm/iotlcm-admin-ui:${TAG:-latest}'
|
||||
container_name: iotlcm-admin-ui
|
||||
restart: always
|
||||
ports:
|
||||
- "127.0.0.1:${ADMIN_UI_PORT:-8009}:80"
|
||||
environment:
|
||||
TZ: '${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: '${REGISTRY:-your-registry}/iotlcm/iotlcm-openapi:${TAG:-latest}'
|
||||
container_name: iotlcm-openapi
|
||||
restart: always
|
||||
ports:
|
||||
- "127.0.0.1:${OPENAPI_PORT:-8000}:8000"
|
||||
environment:
|
||||
TZ: '${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: '${REGISTRY:-your-registry}/iotlcm/iotlcm-upstream-chan:${TAG:-latest}'
|
||||
container_name: iotlcm-upstream-chan
|
||||
restart: always
|
||||
ports:
|
||||
- "${CHAN_HTTP_PORT:-8110}:8110"
|
||||
- "${CHAN_GRPC_PORT:-8310}:8310"
|
||||
environment:
|
||||
TZ: '${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: '${REGISTRY:-your-registry}/iotlcm/iotlcm-upstream-proxy:${TAG:-latest}'
|
||||
container_name: iotlcm-upstream-proxy
|
||||
restart: always
|
||||
ports:
|
||||
- "${PROXY_PORT:-8510}:8510"
|
||||
environment:
|
||||
TZ: '${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: '${REGISTRY:-your-registry}/iotlcm/iotlcm-worker-svr:${TAG:-latest}'
|
||||
container_name: iotlcm-worker-svr
|
||||
restart: always
|
||||
environment:
|
||||
TZ: '${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: '${REGISTRY:-your-registry}/iotlcm/iotlcm-app-server:${TAG:-latest}'
|
||||
container_name: iotlcm-app-server
|
||||
restart: always
|
||||
ports:
|
||||
- "127.0.0.1:${APP_SERVER_PORT:-8010}:8010"
|
||||
environment:
|
||||
TZ: '${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: '${REGISTRY:-your-registry}/iotlcm/iotlcm-app-web:${TAG:-latest}'
|
||||
container_name: iotlcm-app-web
|
||||
restart: always
|
||||
ports:
|
||||
- "127.0.0.1:${APP_WEB_PORT:-8018}:80"
|
||||
environment:
|
||||
TZ: '${TZ:-Asia/Shanghai}'
|
||||
volumes:
|
||||
- ./data/logs/app-web:/var/log/nginx
|
||||
networks:
|
||||
- iotlcm-network
|
||||
|
||||
sms:
|
||||
image: '${REGISTRY:-your-registry}/iotlcm/iotlcm-sms:${TAG:-latest}'
|
||||
container_name: iotlcm-sms
|
||||
hostname: iotlcm-sms
|
||||
restart: always
|
||||
environment:
|
||||
TZ: '${TZ:-Asia/Shanghai}'
|
||||
HTTP_ADDR: ':11190'
|
||||
GRPC_ADDR: ':11200'
|
||||
ports:
|
||||
- "${SMS_HTTP_PORT:-11190}:11190"
|
||||
- "${SMS_GRPC_PORT:-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: '${REGISTRY:-your-registry}/iotlcm/iotlcm-bot:${TAG:-latest}'
|
||||
container_name: iotlcm-bot
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
TZ: '${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: '${REGISTRY:-your-registry}/iotlcm/iotlcm-docs:${TAG:-latest}'
|
||||
container_name: iotlcm-docs
|
||||
restart: unless-stopped
|
||||
ports:
|
||||
- "127.0.0.1:${DOCS_PORT:-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: '${REGISTRY:-your-registry}/iotlcm/iotlcm-onelink-mock:${TAG:-latest}'
|
||||
container_name: iotlcm-onelink-mock
|
||||
restart: unless-stopped
|
||||
ports:
|
||||
- "127.0.0.1:${MOCK_PORT:-8080}:8080"
|
||||
environment:
|
||||
TZ: '${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: '${REGISTRY:-your-registry}/library/nginx:1.30'
|
||||
container_name: iotlcm-nginx
|
||||
restart: always
|
||||
ports:
|
||||
- "${NGINX_HTTP_PORT:-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
|
||||
Reference in New Issue
Block a user