From 5ddad0c5e53c73a29804e74faf0b78deb296e69f Mon Sep 17 00:00:00 2001 From: MiFaZhan Date: Thu, 29 Oct 2026 09:17:26 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E4=B8=80=E9=94=AE=E9=83=A8=E7=BD=B2?= =?UTF-8?q?=E2=80=94=E2=80=94=E9=85=8D=E7=BD=AE=E5=86=85=E7=BD=AE=E9=BB=98?= =?UTF-8?q?=E8=AE=A4=E5=80=BC=EF=BC=8C=E5=8E=BB=E6=8E=89=E7=A4=BA=E4=BE=8B?= =?UTF-8?q?=E5=A4=8D=E5=88=B6=E4=B8=8E=E7=8E=AF=E5=A2=83=E5=8F=98=E9=87=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 目标: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 中一致。 --- .env.example | 95 -------------- .gitignore | 7 +- README.md | 111 ++++++++++------- .../admin-svr/config.yaml | 21 ++-- .../admin-ui/default.conf | 0 .../app-server/config.yaml | 18 +-- .../bot/config.yaml | 6 +- {config.example => config}/nginx/iotlcm.conf | 0 .../openapi/config.yaml | 8 +- .../sms/config.yaml | 6 +- .../upstream-chan/config.yaml | 4 +- .../upstream-proxy/config.yaml | 6 +- .../worker-svr/config.yaml | 14 +-- docker-compose.yml | 117 +++++++++--------- schema/04-users.sh | 30 ++--- schema/05-reset-passwords.sh | 23 ++-- schema/13-seed-flow-package.sql | 35 ++++++ schema/README.md | 50 ++++---- 18 files changed, 252 insertions(+), 299 deletions(-) delete mode 100644 .env.example rename config.example/admin-svr/config.example.yaml => config/admin-svr/config.yaml (87%) rename {config.example => config}/admin-ui/default.conf (100%) rename config.example/app-server/config.example.yaml => config/app-server/config.yaml (92%) rename config.example/bot/config.example.yaml => config/bot/config.yaml (88%) rename {config.example => config}/nginx/iotlcm.conf (100%) rename config.example/openapi/config.example.yaml => config/openapi/config.yaml (86%) rename config.example/sms/config.example.yaml => config/sms/config.yaml (80%) rename config.example/upstream-chan/config.example.yaml => config/upstream-chan/config.yaml (93%) rename config.example/upstream-proxy/config.example.yaml => config/upstream-proxy/config.yaml (92%) rename config.example/worker-svr/config.example.yaml => config/worker-svr/config.yaml (87%) create mode 100644 schema/13-seed-flow-package.sql diff --git a/.env.example b/.env.example deleted file mode 100644 index abb24d3..0000000 --- a/.env.example +++ /dev/null @@ -1,95 +0,0 @@ -# ============================================================ -# IotLCM 部署环境变量 -# -# cp .env.example .env -# -# 标注「必填」的变量未设置时 docker compose 会直接报错退出, -# 避免用弱口令启动。口令建议用 openssl rand -base64 24 生成。 -# ============================================================ - -# ---------- 镜像 ---------- -# 镜像仓库地址(不含末尾斜杠)。 -# 基础组件从 /library/ 拉取,业务镜像从 /iotlcm/ 拉取。 -REGISTRY=your-registry.example.com - -# 镜像标签。生产建议用不可变标签(版本号或 commit sha),不要用 latest。 -TAG=latest - -# ---------- 时区 ---------- -TZ=Asia/Shanghai - -# ---------- 必填:数据库 ---------- -# MySQL root 口令 -MYSQL_ROOT_PASSWORD=change-me-strong-password - -# 数据库名 -MYSQL_DATABASE=db_iotlcm - -# 应用连接账号 u_iotlcm 的口令(首次启动时创建) -MYSQL_APP_PASSWORD=change-me-strong-password - -# admin 初始登录口令(首次启动时写入数据库) -# 登录后请立即在「个人中心」修改 -MYSQL_ADMIN_PASSWORD=change-me-admin-password - -# ---------- 必填:Redis ---------- -REDIS_PASSWORD=change-me-strong-password - -# ---------- 必填:RabbitMQ ---------- -RABBITMQ_USER=iotlcm -RABBITMQ_PASSWORD=change-me-strong-password - -# ---------- 必填:JWT 签名密钥 ---------- -# admin-svr / openapi / app-server 必须使用同一个值,否则令牌跨服务不通用。 -# 生成:openssl rand -hex 32 -# 注意:更换此值会使已签发的所有登录态与接口令牌立即失效。 -JWT_SIGNING_KEY=change-me-run-openssl-rand-hex-32 - -# ---------- 可选:智能诊断内部凭据 ---------- -# admin-svr 与 upstream-proxy 必须一致。留空则该功能不可用。 -DIAGNOSIS_INTERNAL_TOKEN= - -# ---------- 可选:短信服务商 ---------- -# 不启用短信时保持空值,并把配置里的 warning.sms.enabled 改为 false -SMS_ACCESS_KEY_ID= -SMS_ACCESS_KEY_SECRET= - -# ---------- 可选:飞书通知(bot 服务) ---------- -# 不启用 bot 时不填,且不启动该容器 -FEISHU_APP_ID= -FEISHU_APP_SECRET= -FEISHU_CHAT_ID= - -# ---------- 端口(宿主机侧) ---------- -# 仅监听 127.0.0.1 的服务需通过反向代理对外 -ADMIN_SVR_PORT=8008 -ADMIN_UI_PORT=8009 -OPENAPI_PORT=8000 -APP_SERVER_PORT=8010 -APP_WEB_PORT=8018 -DOCS_PORT=8019 -MOCK_PORT=8080 - -# 以下服务监听所有网卡(容器间互访也走这些端口) -MYSQL_PORT=3306 -REDIS_PORT=6379 -RABBITMQ_PORT=5672 -RABBITMQ_MGMT_PORT=15672 -CONSUL_PORT=8500 -CHAN_HTTP_PORT=8110 -CHAN_GRPC_PORT=8310 -PROXY_PORT=8510 -SMS_HTTP_PORT=11190 -SMS_GRPC_PORT=11200 - -# nginx 对外端口(仅 --profile with-nginx) -NGINX_HTTP_PORT=80 - -# ---------- 可选:TDengine(流量历史) ---------- -# 不启用时序库时全部留空,相关历史流量查询功能不可用,不影响主流程。 -TDENGINE_HOST= -TDENGINE_PORT=6041 -TDENGINE_USER=root -TDENGINE_PASSWORD= -TDENGINE_DAILY_DB=iotlcm_daily -TDENGINE_MONTHLY_DB=iotlcm_monthly diff --git a/.gitignore b/.gitignore index 82d5639..e551619 100644 --- a/.gitignore +++ b/.gitignore @@ -1,11 +1,8 @@ # 运行时数据(含数据库文件、日志、上传件) data/ -# 实际配置(由 config.example 复制而来,含真实凭据) -config/ - -# 环境变量文件 -.env +# 本地覆盖配置(如需保留自己的修改而不进版本库,可放 config/local.yaml) +config/*/local.yaml # 编辑器与系统文件 .DS_Store diff --git a/README.md b/README.md index 7331225..87b5eb3 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,41 @@ IotLCM 物联网卡管理平台的部署编排与数据库初始化脚本。使用 Docker Compose 在单机上拉起完整平台。 +## 一键启动 + +```bash +git clone <本仓库地址> iotlcm-deploy +cd iotlcm-deploy +docker compose up -d +``` + +无需复制或修改任何文件,配置里已带可用默认值。首次启动会自动建库、建表、创建应用账号并导入种子数据,约需 1~2 分钟。 + +等待 MySQL 健康后其余服务依次启动,观察进度: + +```bash +docker compose logs -f mysql +``` + +启动完成后访问 `http://<宿主机IP>:8009`: + +| 项 | 值 | +| --- | --- | +| 账号 | `admin` | +| 口令 | `Iotlcm2026Default` | + +> ⚠️ **正式使用前必须修改默认口令**,见下方「上线前必改」。 + +## 可选服务 + +```bash +docker compose --profile with-mock up -d # 运营商接口挡板 +docker compose --profile with-bot up -d # 飞书通知 +docker compose --profile with-nginx up -d # 自带反向代理 +``` + +多个 profile 可组合:`--profile with-mock --profile with-nginx up -d` + ## 部署内容 | 类别 | 服务 | @@ -10,59 +45,42 @@ IotLCM 物联网卡管理平台的部署编排与数据库初始化脚本。使 | 业务服务 | admin-svr(管理端后端)、admin-ui(管理端前端)、openapi(对外 API)、app-server(小程序后端)、app-web(小程序前端)、upstream-chan(运营商对接)、upstream-proxy(通道缓存转发)、worker-svr(异步任务)、sms(短信)、docs(文档站) | | 可选 | onelink-mock(运营商接口挡板)、bot(飞书通知)、nginx(反向代理) | -## 快速开始 - -```bash -# 1. 准备环境变量 -cp .env.example .env -vi .env # 填镜像仓库、各项口令 - -# 2. 准备配置 -cp -r config.example config -vi config/*/config.yaml # 逐份填写(标注「必改」的项) - -# 3. 启动 -docker compose up -d - -# 4. 查看状态 -docker compose ps -``` - -首次启动会自动建库并导入 schema,MySQL 初始化约需 1~2 分钟。等待 `iotlcm-mysql` 健康后其余服务才会启动。 - -启动完成后访问 `http://<宿主机IP>:8009`,账号 `admin`,口令为 `.env` 中的 `MYSQL_ADMIN_PASSWORD`。 - -需要按需开启的可选服务: - -```bash -docker compose --profile with-mock up -d # 运营商接口挡板 -docker compose --profile with-bot up -d # 飞书通知 -docker compose --profile with-nginx up -d # 自带反向代理 -``` - ## 目录结构 ``` iotlcm-deploy/ -├── docker-compose.yml # 服务编排 -├── .env.example # 环境变量模板 → 复制为 .env -├── config.example/ # 配置模板 → 复制为 config/ -│ ├── admin-svr/ -│ ├── admin-ui/ -│ ├── app-server/ -│ ├── bot/ -│ ├── nginx/ -│ ├── openapi/ -│ ├── sms/ -│ ├── upstream-chan/ -│ ├── upstream-proxy/ -│ └── worker-svr/ +├── docker-compose.yml # 服务编排(含全部默认值) +├── config/ # 各服务配置,已带可用默认值 +│ ├── admin-svr/config.yaml +│ ├── admin-ui/default.conf +│ ├── app-server/config.yaml +│ ├── bot/config.yaml +│ ├── nginx/iotlcm.conf +│ ├── openapi/config.yaml +│ ├── sms/config.yaml +│ ├── upstream-chan/config.yaml +│ ├── upstream-proxy/config.yaml +│ └── worker-svr/config.yaml ├── schema/ # 数据库初始化脚本(首次启动自动执行) -├── config/ # 实际配置(不入版本库) -└── data/ # 运行数据(不入版本库) +└── data/ # 运行数据(首次启动自动创建,不入版本库) ``` -`config/` 与 `data/` 在 `.gitignore` 中,不会被提交。 +## 上线前必改 + +默认口令仅用于快速试用。**正式部署前必须修改以下内容**,具体位置见[部署手册](https://git.5iot.com/iotlcm-public/iotlcm-docs): + +| 项 | 位置 | +| --- | --- | +| 数据库口令(root 与应用账号) | `docker-compose.yml` + `config/*/config.yaml` + `schema/04-users.sh` | +| Redis 口令 | `docker-compose.yml` + `config/*/config.yaml` | +| RabbitMQ 口令 | `docker-compose.yml` + `config/*/config.yaml` | +| admin 初始口令 | `docker-compose.yml` + `schema/05-reset-passwords.sh` | +| JWT 签名密钥 | `config/admin-svr`、`config/openapi`、`config/app-server` 三处 | +| 对外域名 | `config/nginx/iotlcm.conf` | + +::: warning 改口令必须多处同步 +因为配置文件里是字面值(未使用环境变量),改口令时**编排、配置、初始化脚本三处必须一致**,漏改会导致服务连不上数据库。 +::: ## 重要提示 @@ -70,7 +88,6 @@ iotlcm-deploy/ - **镜像标签不要用 `latest`**,生产环境请固定到具体版本 - **改 `schema/` 下的脚本不会自动生效**,需要清空 `data/mysql` 重新初始化(会丢失全部数据) - 默认只监听 `127.0.0.1` 的服务需通过反向代理对外 -- 数据库初始化脚本的详细说明见 [`schema/README.md`](schema/README.md) ## 许可 diff --git a/config.example/admin-svr/config.example.yaml b/config/admin-svr/config.yaml similarity index 87% rename from config.example/admin-svr/config.example.yaml rename to config/admin-svr/config.yaml index ba51502..4f23f77 100644 --- a/config.example/admin-svr/config.example.yaml +++ b/config/admin-svr/config.yaml @@ -5,7 +5,7 @@ # # 标注「必改」的项需要按实际环境填写; # 其余为可运行默认值,按需调整。 -# 支持 ${VAR} 与 ${VAR:default} 环境变量占位(由 compose 注入)。 +# 支持 与 环境变量占位(由 compose 注入)。 # ============================================================ system: @@ -52,7 +52,7 @@ logger: # ---------- JWT ---------- # 必改:signingKey 必须与 openapi、app-server 完全一致。 jwt: - signingKey: "${JWT_SIGNING_KEY}" + signingKey: "1f8b3c5d7e9a2b4c6d8e0f1a3b5c7d9e1f8b3c5d7e9a2b4c6d8e0f1a3b5c7d9e" expiresTime: 7d bufferTime: 1d issuer: iotlcm @@ -77,8 +77,7 @@ database: level: "all" stdout: true default: - # 必改:连接串格式为 mysql:用户名:口令 再接 tcp(主机:端口)/库名?参数 - link: "mysql:u_iotlcm:${MYSQL_APP_PASSWORD}@tcp(mysql:3306)/${MYSQL_DATABASE}?charset=utf8mb4&parseTime=True&loc=Asia%2FShanghai" + # 必改:连接串格式为 mysql:用户名:Iotlcm2026Default@tcp(mysql:3306)/db_iotlcm?charset=utf8mb4&parseTime=True&loc=Asia%2FShanghai" debug: false charset: "utf8mb4" dryRun: false @@ -162,7 +161,7 @@ redis: sentinelMasterName: "" address: "redis:6379" db: 0 - pass: "${REDIS_PASSWORD}" + pass: "Iotlcm2026Default" minIdle: 5 maxIdle: 30 maxActive: 5000 @@ -172,7 +171,7 @@ redis: # ---------- RabbitMQ ---------- rabbitmq: enabled: true - dsn: "amqp://${RABBITMQ_USER}:${RABBITMQ_PASSWORD}@rabbitmq:5672/" + dsn: "amqp://iotlcm:Iotlcm2026Default@rabbitmq:5672/" # ---------- TDengine(流量历史) ---------- # 需要 TDengine 3.x 的 WebSocket 接口(6041)。 @@ -181,10 +180,10 @@ tsdb: database: "TdEngine" tdengine: type: "taosWS" - dsn: "${TDENGINE_USER}:${TDENGINE_PASSWORD}@ws(${TDENGINE_HOST}:${TDENGINE_PORT})/" - dbName: "${TDENGINE_DAILY_DB}" - dailyDbName: "${TDENGINE_DAILY_DB}" - monthlyDbName: "${TDENGINE_MONTHLY_DB}" + dsn: ":@ws(:)/" + dbName: "" + dailyDbName: "" + monthlyDbName: "" maxOpenConns: 100 maxIdleConns: 10 @@ -219,7 +218,7 @@ pay: # 指向同 compose 内的服务名,一般无需修改。 upstream: # 控制台智能诊断内部凭据,须与 upstream-proxy 的 appDiagnosis.internalToken 一致 - appDiagnosisToken: "${DIAGNOSIS_INTERNAL_TOKEN}" + appDiagnosisToken: "iotlcm_diagnosis_2026" proxy: address: "upstream-proxy:8510" timeout: 10s diff --git a/config.example/admin-ui/default.conf b/config/admin-ui/default.conf similarity index 100% rename from config.example/admin-ui/default.conf rename to config/admin-ui/default.conf diff --git a/config.example/app-server/config.example.yaml b/config/app-server/config.yaml similarity index 92% rename from config.example/app-server/config.example.yaml rename to config/app-server/config.yaml index 8fab95f..4e85659 100644 --- a/config.example/app-server/config.example.yaml +++ b/config/app-server/config.yaml @@ -53,7 +53,7 @@ logger: # ---------- JWT ---------- # 必改:必须与 admin-svr、openapi 完全一致。 jwt: - signingKey: "${JWT_SIGNING_KEY}" + signingKey: "1f8b3c5d7e9a2b4c6d8e0f1a3b5c7d9e1f8b3c5d7e9a2b4c6d8e0f1a3b5c7d9e" expiresTime: "7d" bufferTime: "1d" issuer: "iotlcm" @@ -88,7 +88,7 @@ database: stdout: true default: # 必改:连接串 - link: "mysql:u_iotlcm:${MYSQL_APP_PASSWORD}@tcp(mysql:3306)/${MYSQL_DATABASE}?charset=utf8mb4&parseTime=True&loc=Asia%2FShanghai" + link: "mysql:u_iotlcm:Iotlcm2026Default@tcp(mysql:3306)/db_iotlcm?charset=utf8mb4&parseTime=True&loc=Asia%2FShanghai" debug: false charset: "utf8mb4" dryRun: false @@ -113,7 +113,7 @@ redis: sentinelMasterName: "" address: "redis:6379" db: 0 - pass: "${REDIS_PASSWORD}" + pass: "Iotlcm2026Default" minIdle: 5 maxIdle: 30 maxActive: 5000 @@ -123,7 +123,7 @@ redis: # ---------- RabbitMQ ---------- rabbitmq: enabled: true - dsn: "amqp://${RABBITMQ_USER}:${RABBITMQ_PASSWORD}@rabbitmq:5672/" + dsn: "amqp://iotlcm:Iotlcm2026Default@rabbitmq:5672/" # ---------- 异步业务 ---------- workerBatchAsync: @@ -197,10 +197,10 @@ tsdb: database: "TdEngine" tdengine: type: "taosWS" - dsn: "${TDENGINE_USER}:${TDENGINE_PASSWORD}@ws(${TDENGINE_HOST}:${TDENGINE_PORT})/" - dbName: "${TDENGINE_DAILY_DB}" - dailyDbName: "${TDENGINE_DAILY_DB}" - monthlyDbName: "${TDENGINE_MONTHLY_DB}" + dsn: ":@ws(:)/" + dbName: "" + dailyDbName: "" + monthlyDbName: "" maxOpenConns: 100 maxIdleConns: 10 @@ -244,7 +244,7 @@ router: # ---------- 上游服务地址 ---------- upstream: # 控制台智能诊断内部凭据,须与 admin-svr 一致 - appDiagnosisToken: "${DIAGNOSIS_INTERNAL_TOKEN}" + appDiagnosisToken: "iotlcm_diagnosis_2026" provider: "onelink_mock" default: clientName: "http://upstream-proxy:8510" diff --git a/config.example/bot/config.example.yaml b/config/bot/config.yaml similarity index 88% rename from config.example/bot/config.example.yaml rename to config/bot/config.yaml index aaca7da..5086033 100644 --- a/config.example/bot/config.example.yaml +++ b/config/bot/config.yaml @@ -21,6 +21,6 @@ pollInterval: 10s # appId / appSecret:应用凭证 # chatId:目标群会话 ID feishu: - appId: "${FEISHU_APP_ID}" - appSecret: "${FEISHU_APP_SECRET}" - chatId: "${FEISHU_CHAT_ID}" + appId: "" + appSecret: "" + chatId: "" diff --git a/config.example/nginx/iotlcm.conf b/config/nginx/iotlcm.conf similarity index 100% rename from config.example/nginx/iotlcm.conf rename to config/nginx/iotlcm.conf diff --git a/config.example/openapi/config.example.yaml b/config/openapi/config.yaml similarity index 86% rename from config.example/openapi/config.example.yaml rename to config/openapi/config.yaml index 33e65b5..863eddd 100644 --- a/config.example/openapi/config.example.yaml +++ b/config/openapi/config.yaml @@ -31,7 +31,7 @@ logger: # 必改:必须与 admin-svr、app-server 完全一致, # 否则 admin 签发的令牌在 openapi 侧校验不通过。 jwt: - signingKey: "${JWT_SIGNING_KEY}" + signingKey: "1f8b3c5d7e9a2b4c6d8e0f1a3b5c7d9e1f8b3c5d7e9a2b4c6d8e0f1a3b5c7d9e" expiresTime: "7d" bufferTime: "1d" issuer: "iotlcm" @@ -45,7 +45,7 @@ database: stdout: true default: # 必改:连接串 - link: "mysql:u_iotlcm:${MYSQL_APP_PASSWORD}@tcp(mysql:3306)/${MYSQL_DATABASE}?charset=utf8mb4&parseTime=True&loc=Asia%2FShanghai" + link: "mysql:u_iotlcm:Iotlcm2026Default@tcp(mysql:3306)/db_iotlcm?charset=utf8mb4&parseTime=True&loc=Asia%2FShanghai" debug: false charset: "utf8mb4" dryRun: false @@ -64,7 +64,7 @@ redis: sentinelMasterName: "" address: "redis:6379" db: 0 - pass: "${REDIS_PASSWORD}" + pass: "Iotlcm2026Default" minIdle: 5 maxIdle: 30 maxActive: 5000 @@ -74,7 +74,7 @@ redis: # ---------- RabbitMQ ---------- rabbitmq: enabled: true - dsn: "amqp://${RABBITMQ_USER}:${RABBITMQ_PASSWORD}@rabbitmq:5672/" + dsn: "amqp://iotlcm:Iotlcm2026Default@rabbitmq:5672/" # ---------- 免登录白名单 ---------- router: diff --git a/config.example/sms/config.example.yaml b/config/sms/config.yaml similarity index 80% rename from config.example/sms/config.example.yaml rename to config/sms/config.yaml index 161ea7e..9f53eae 100644 --- a/config.example/sms/config.example.yaml +++ b/config/sms/config.yaml @@ -12,8 +12,8 @@ serviceType: "1" # ---------- 必改:服务商凭据 ---------- regionId: cn-hangzhou -accessKeyId: "${SMS_ACCESS_KEY_ID}" -accessKeySecret: "${SMS_ACCESS_KEY_SECRET}" +accessKeyId: "" +accessKeySecret: "" # 短信签名,需已在服务商侧审核通过 signName: "示例签名" @@ -25,5 +25,5 @@ signName: "示例签名" # 配置后按 scene 从 t_sms_template_config 表读取模板与签名, # 改库即生效(短 TTL 缓存)。 # 不配置则 scene 功能关闭,调用方必须自带 templateId。 -sceneDbDsn: "u_iotlcm:${MYSQL_APP_PASSWORD}@tcp(mysql:3306)/${MYSQL_DATABASE}?charset=utf8mb4&parseTime=true&loc=Local" +sceneDbDsn: "u_iotlcm:Iotlcm2026Default@tcp(mysql:3306)/db_iotlcm?charset=utf8mb4&parseTime=true&loc=Local" sceneDbCacheTtl: 60s diff --git a/config.example/upstream-chan/config.example.yaml b/config/upstream-chan/config.yaml similarity index 93% rename from config.example/upstream-chan/config.example.yaml rename to config/upstream-chan/config.yaml index 37fa987..b55a4e8 100644 --- a/config.example/upstream-chan/config.example.yaml +++ b/config/upstream-chan/config.yaml @@ -62,7 +62,7 @@ database: stdout: true default: # 必改:连接串 - link: "mysql:u_iotlcm:${MYSQL_APP_PASSWORD}@tcp(mysql:3306)/${MYSQL_DATABASE}?charset=utf8mb4&parseTime=True&loc=Asia%2FShanghai" + link: "mysql:u_iotlcm:Iotlcm2026Default@tcp(mysql:3306)/db_iotlcm?charset=utf8mb4&parseTime=True&loc=Asia%2FShanghai" debug: false charset: "utf8mb4" dryRun: false @@ -87,7 +87,7 @@ redis: sentinelMasterName: "" address: "redis:6379" db: 0 - pass: "${REDIS_PASSWORD}" + pass: "Iotlcm2026Default" minIdle: 5 maxIdle: 30 maxActive: 5000 diff --git a/config.example/upstream-proxy/config.example.yaml b/config/upstream-proxy/config.yaml similarity index 92% rename from config.example/upstream-proxy/config.example.yaml rename to config/upstream-proxy/config.yaml index eda616d..585f7e8 100644 --- a/config.example/upstream-proxy/config.example.yaml +++ b/config/upstream-proxy/config.yaml @@ -20,7 +20,7 @@ system: # 必须与 admin-svr 的 upstream.appDiagnosisToken 一致。 # 生成:openssl rand -hex 16 appDiagnosis: - internalToken: "${DIAGNOSIS_INTERNAL_TOKEN}" + internalToken: "iotlcm_diagnosis_2026" server: name: "iotlcmupstreamproxy-grpc-svc" @@ -65,7 +65,7 @@ database: stdout: true default: # 必改:连接串 - link: "mysql:u_iotlcm:${MYSQL_APP_PASSWORD}@tcp(mysql:3306)/${MYSQL_DATABASE}?charset=utf8mb4&parseTime=True&loc=Asia%2FShanghai" + link: "mysql:u_iotlcm:Iotlcm2026Default@tcp(mysql:3306)/db_iotlcm?charset=utf8mb4&parseTime=True&loc=Asia%2FShanghai" debug: false charset: "utf8mb4" dryRun: false @@ -90,7 +90,7 @@ redis: sentinelMasterName: "" address: "redis:6379" db: 0 - pass: "${REDIS_PASSWORD}" + pass: "Iotlcm2026Default" minIdle: 5 maxIdle: 30 maxActive: 5000 diff --git a/config.example/worker-svr/config.example.yaml b/config/worker-svr/config.yaml similarity index 87% rename from config.example/worker-svr/config.example.yaml rename to config/worker-svr/config.yaml index a01af2a..169a6c2 100644 --- a/config.example/worker-svr/config.example.yaml +++ b/config/worker-svr/config.yaml @@ -42,7 +42,7 @@ database: stdout: true default: # 必改:连接串 - link: "mysql:u_iotlcm:${MYSQL_APP_PASSWORD}@tcp(mysql:3306)/${MYSQL_DATABASE}?charset=utf8mb4&parseTime=True&loc=Asia%2FShanghai" + link: "mysql:u_iotlcm:Iotlcm2026Default@tcp(mysql:3306)/db_iotlcm?charset=utf8mb4&parseTime=True&loc=Asia%2FShanghai" debug: false charset: "utf8mb4" dryRun: false @@ -67,7 +67,7 @@ redis: sentinelMasterName: "" address: "redis:6379" db: 0 - pass: "${REDIS_PASSWORD}" + pass: "Iotlcm2026Default" minIdle: 5 maxIdle: 30 maxActive: 5000 @@ -77,7 +77,7 @@ redis: # ---------- RabbitMQ ---------- rabbitmq: enabled: true - dsn: "amqp://${RABBITMQ_USER}:${RABBITMQ_PASSWORD}@rabbitmq:5672/" + dsn: "amqp://iotlcm:Iotlcm2026Default@rabbitmq:5672/" balanceRecharge: retryDelay: "1m" batchExecute: @@ -122,11 +122,11 @@ tsdb: database: "TdEngine" tdengine: type: "taosWS" - dsn: "${TDENGINE_USER}:${TDENGINE_PASSWORD}@ws(${TDENGINE_HOST}:${TDENGINE_PORT})/" + dsn: ":@ws(:)/" # dbName 只是连接池键名与兜底值,不决定实际访问哪个库 - dbName: "${TDENGINE_DAILY_DB}" - dailyDbName: "${TDENGINE_DAILY_DB}" - monthlyDbName: "${TDENGINE_MONTHLY_DB}" + dbName: "" + dailyDbName: "" + monthlyDbName: "" maxOpenConns: 100 maxIdleConns: 10 diff --git a/docker-compose.yml b/docker-compose.yml index 51ea11f..ac4a62b 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -18,17 +18,16 @@ name: iotlcm services: # ---------------- 基础组件 ---------------- mysql: - image: '${REGISTRY:-your-registry}/library/mysql:8.0' + # 基础组件统走同一镜像仓库(`/library/`),版本在 .env 里固定 + image: 'crpi-qflrqrxoohllkvgc.cn-chengdu.personal.cr.aliyuncs.com/library/mysql:8.0' container_name: iotlcm-mysql restart: always ports: - - "${MYSQL_PORT:-3306}:3306" + - "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}' + MYSQL_ROOT_PASSWORD: 'Iotlcm2026Default' + MYSQL_DATABASE: 'db_iotlcm' + TZ: 'Asia/Shanghai' volumes: - ./data/mysql:/var/lib/mysql # 仅在 data/mysql 为空(首次启动)时执行,按文件名顺序 @@ -40,24 +39,24 @@ services: networks: - iotlcm-network healthcheck: - test: ["CMD", "mysqladmin", "ping", "-h", "127.0.0.1", "-p${MYSQL_ROOT_PASSWORD}"] + test: ["CMD", "mysqladmin", "ping", "-h", "127.0.0.1", "-piotlcm_root_2026"] interval: 10s timeout: 5s retries: 10 start_period: 40s redis: - image: '${REGISTRY:-your-registry}/library/redis:7.2' + image: 'crpi-qflrqrxoohllkvgc.cn-chengdu.personal.cr.aliyuncs.com/library/redis:7.2' container_name: iotlcm-redis restart: always ports: - - "${REDIS_PORT:-6379}:6379" + - "6379:6379" environment: - TZ: '${TZ:-Asia/Shanghai}' + TZ: 'Asia/Shanghai' command: - redis-server - --requirepass - - '${REDIS_PASSWORD:?必须在 .env 中设置}' + - 'Iotlcm2026Default' - --appendonly - "yes" volumes: @@ -65,23 +64,23 @@ services: networks: - iotlcm-network healthcheck: - test: ["CMD", "redis-cli", "-a", "${REDIS_PASSWORD}", "ping"] + test: ["CMD", "redis-cli", "-a", "Iotlcm2026Default", "ping"] interval: 10s timeout: 5s retries: 5 rabbitmq: - image: '${REGISTRY:-your-registry}/library/rabbitmq:4.3.5-management' + image: 'crpi-qflrqrxoohllkvgc.cn-chengdu.personal.cr.aliyuncs.com/library/rabbitmq:4.3.5-management' container_name: iotlcm-rabbitmq hostname: rabbitmq restart: always ports: - - "${RABBITMQ_PORT:-5672}:5672" - - "${RABBITMQ_MGMT_PORT:-15672}:15672" + - "5672:5672" + - "15672:15672" environment: - RABBITMQ_DEFAULT_USER: '${RABBITMQ_USER:-iotlcm}' - RABBITMQ_DEFAULT_PASS: '${RABBITMQ_PASSWORD:?必须在 .env 中设置}' - TZ: '${TZ:-Asia/Shanghai}' + RABBITMQ_DEFAULT_USER: 'iotlcm' + RABBITMQ_DEFAULT_PASS: 'Iotlcm2026Default' + TZ: 'Asia/Shanghai' volumes: - ./data/rabbitmq:/var/lib/rabbitmq networks: @@ -94,13 +93,13 @@ services: start_period: 30s consul: - image: '${REGISTRY:-your-registry}/library/consul:1.22' + image: 'crpi-qflrqrxoohllkvgc.cn-chengdu.personal.cr.aliyuncs.com/library/consul:1.22' container_name: iotlcm-consul restart: always ports: - - "${CONSUL_PORT:-8500}:8500" + - "8500:8500" environment: - TZ: '${TZ:-Asia/Shanghai}' + TZ: 'Asia/Shanghai' CONSUL_LOCAL_CONFIG: | { "node_name": "iotlcm-node", @@ -120,13 +119,13 @@ services: # ---------------- 业务服务 ---------------- admin-svr: - image: '${REGISTRY:-your-registry}/iotlcm/iotlcm-admin-svr:${TAG:-latest}' + 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:${ADMIN_SVR_PORT:-8008}:8008" + - "127.0.0.1:8008:8008" environment: - TZ: '${TZ:-Asia/Shanghai}' + TZ: 'Asia/Shanghai' volumes: - ./config/admin-svr:/app/config:ro - ./data/logs/admin-svr:/app/logs @@ -143,13 +142,13 @@ services: condition: service_healthy admin-ui: - image: '${REGISTRY:-your-registry}/iotlcm/iotlcm-admin-ui:${TAG:-latest}' + 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:${ADMIN_UI_PORT:-8009}:80" + - "127.0.0.1:8009:80" environment: - TZ: '${TZ:-Asia/Shanghai}' + TZ: 'Asia/Shanghai' volumes: - ./config/admin-ui/default.conf:/etc/nginx/conf.d/default.conf:ro - ./data/logs/admin-ui:/var/log/nginx @@ -160,13 +159,13 @@ services: - admin-svr openapi: - image: '${REGISTRY:-your-registry}/iotlcm/iotlcm-openapi:${TAG:-latest}' + image: 'crpi-qflrqrxoohllkvgc.cn-chengdu.personal.cr.aliyuncs.com/iotlcm/iotlcm-openapi:latest' container_name: iotlcm-openapi restart: always ports: - - "127.0.0.1:${OPENAPI_PORT:-8000}:8000" + - "127.0.0.1:8000:8000" environment: - TZ: '${TZ:-Asia/Shanghai}' + TZ: 'Asia/Shanghai' volumes: - ./config/openapi:/app/config:ro - ./data/logs/openapi:/app/logs @@ -181,14 +180,14 @@ services: condition: service_healthy upstream-chan: - image: '${REGISTRY:-your-registry}/iotlcm/iotlcm-upstream-chan:${TAG:-latest}' + image: 'crpi-qflrqrxoohllkvgc.cn-chengdu.personal.cr.aliyuncs.com/iotlcm/iotlcm-upstream-chan:latest' container_name: iotlcm-upstream-chan restart: always ports: - - "${CHAN_HTTP_PORT:-8110}:8110" - - "${CHAN_GRPC_PORT:-8310}:8310" + - "8110:8110" + - "8310:8310" environment: - TZ: '${TZ:-Asia/Shanghai}' + TZ: 'Asia/Shanghai' volumes: - ./config/upstream-chan:/app/config:ro - ./data/logs/upstream-chan:/app/logs @@ -205,13 +204,13 @@ services: condition: service_started upstream-proxy: - image: '${REGISTRY:-your-registry}/iotlcm/iotlcm-upstream-proxy:${TAG:-latest}' + image: 'crpi-qflrqrxoohllkvgc.cn-chengdu.personal.cr.aliyuncs.com/iotlcm/iotlcm-upstream-proxy:latest' container_name: iotlcm-upstream-proxy restart: always ports: - - "${PROXY_PORT:-8510}:8510" + - "8510:8510" environment: - TZ: '${TZ:-Asia/Shanghai}' + TZ: 'Asia/Shanghai' volumes: - ./config/upstream-proxy:/app/config:ro - ./data/logs/upstream-proxy:/app/logs @@ -229,11 +228,11 @@ services: condition: service_started worker-svr: - image: '${REGISTRY:-your-registry}/iotlcm/iotlcm-worker-svr:${TAG:-latest}' + image: 'crpi-qflrqrxoohllkvgc.cn-chengdu.personal.cr.aliyuncs.com/iotlcm/iotlcm-worker-svr:latest' container_name: iotlcm-worker-svr restart: always environment: - TZ: '${TZ:-Asia/Shanghai}' + TZ: 'Asia/Shanghai' volumes: - ./config/worker-svr:/app/config:ro - ./data/logs/worker-svr:/app/logs @@ -251,13 +250,13 @@ services: condition: service_healthy app-server: - image: '${REGISTRY:-your-registry}/iotlcm/iotlcm-app-server:${TAG:-latest}' + 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:${APP_SERVER_PORT:-8010}:8010" + - "127.0.0.1:8010:8010" environment: - TZ: '${TZ:-Asia/Shanghai}' + TZ: 'Asia/Shanghai' APP_UPLOAD_DIR: /app/resource/upload volumes: - ./config/app-server:/app/config:ro @@ -272,30 +271,30 @@ services: condition: service_healthy app-web: - image: '${REGISTRY:-your-registry}/iotlcm/iotlcm-app-web:${TAG:-latest}' + 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:${APP_WEB_PORT:-8018}:80" + - "127.0.0.1:8018:80" environment: - TZ: '${TZ:-Asia/Shanghai}' + TZ: 'Asia/Shanghai' volumes: - ./data/logs/app-web:/var/log/nginx networks: - iotlcm-network sms: - image: '${REGISTRY:-your-registry}/iotlcm/iotlcm-sms:${TAG:-latest}' + image: 'crpi-qflrqrxoohllkvgc.cn-chengdu.personal.cr.aliyuncs.com/iotlcm/iotlcm-sms:latest' container_name: iotlcm-sms hostname: iotlcm-sms restart: always environment: - TZ: '${TZ:-Asia/Shanghai}' + TZ: 'Asia/Shanghai' HTTP_ADDR: ':11190' GRPC_ADDR: ':11200' ports: - - "${SMS_HTTP_PORT:-11190}:11190" - - "${SMS_GRPC_PORT:-11200}:11200" + - "11190:11190" + - "11200:11200" volumes: - ./config/sms:/app/config:ro - ./data/logs/sms:/app/logs @@ -313,11 +312,11 @@ services: - iotlcm-network bot: - image: '${REGISTRY:-your-registry}/iotlcm/iotlcm-bot:${TAG:-latest}' + image: 'crpi-qflrqrxoohllkvgc.cn-chengdu.personal.cr.aliyuncs.com/iotlcm/iotlcm-bot:latest' container_name: iotlcm-bot restart: unless-stopped environment: - TZ: '${TZ:-Asia/Shanghai}' + TZ: 'Asia/Shanghai' command: ["watch", "--config", "/app/config/config.yaml"] volumes: - ./config/bot/config.yaml:/app/config/config.yaml:ro @@ -329,11 +328,11 @@ services: - with-bot docs: - image: '${REGISTRY:-your-registry}/iotlcm/iotlcm-docs:${TAG:-latest}' + 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:${DOCS_PORT:-8019}:80" + - "127.0.0.1:8019:80" networks: - iotlcm-network @@ -345,13 +344,13 @@ services: # 启用后 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}' + 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:${MOCK_PORT:-8080}:8080" + - "127.0.0.1:8080:8080" environment: - TZ: '${TZ:-Asia/Shanghai}' + TZ: 'Asia/Shanghai' BAFFLE_ADDR: ':8080' BAFFLE_SQLITE_PATH: /app/data/onelink_mock.db volumes: @@ -372,11 +371,11 @@ services: # 若宿主机已有 nginx / 面板,可不启动本容器, # 参考 config.example/nginx/iotlcm.conf 把 location 段落到宿主机配置。 nginx: - image: '${REGISTRY:-your-registry}/library/nginx:1.30' + image: 'crpi-qflrqrxoohllkvgc.cn-chengdu.personal.cr.aliyuncs.com/library/nginx:1.30' container_name: iotlcm-nginx restart: always ports: - - "${NGINX_HTTP_PORT:-80}:80" + - "80:80" volumes: - ./config/nginx:/etc/nginx/conf.d:ro - ./data/logs/nginx:/var/log/nginx diff --git a/schema/04-users.sh b/schema/04-users.sh index e47f2ae..759ae4e 100755 --- a/schema/04-users.sh +++ b/schema/04-users.sh @@ -3,31 +3,33 @@ # 业务数据库账号与附加库 # 由 MySQL 容器 docker-entrypoint-initdb.d 在首次启动时执行。 # -# 为什么用 .sh 而不是 .sql: -# MySQL 官方镜像的 initdb 脚本无法在 SQL 里读环境变量, -# 而账号口令必须从 .env 注入,不能写死在仓库里。 +# 口令直接写在本文件(不使用环境变量)。 +# 改口令时必须同时修改以下三处,否则服务连不上库: +# 1. docker-compose.yml 的 MYSQL_APP_PASSWORD +# 2. config/*/config.yaml 里 database link 的口令 +# 3. 本文件下方的 APP_PASSWORD # ============================================================ set -euo pipefail -if [ -z "${MYSQL_APP_PASSWORD:-}" ]; then - echo "[initdb] 错误:未设置 MYSQL_APP_PASSWORD" >&2 - exit 1 -fi +# 与 docker-compose.yml 保持一致 +APP_USER='iotlcm_app' +APP_PASSWORD='Iotlcm2026Default' +ROOT_PASSWORD='Iotlcm2026Default' +DB_NAME='db_iotlcm' -mysql --protocol=socket -uroot -p"${MYSQL_ROOT_PASSWORD}" <&2 - exit 1 -fi +ADMIN_PASSWORD='Iotlcm2026Default' +ROOT_PASSWORD='Iotlcm2026Default' +DB_NAME='db_iotlcm' -PWD_MD5=$(printf '%s' "$MYSQL_ADMIN_PASSWORD" | md5sum | awk '{print $1}') +PWD_MD5=$(printf '%s' "$ADMIN_PASSWORD" | md5sum | awk '{print $1}') -# 逐个账号按其自身 salt 计算哈希(salt 每行不同) -mysql --protocol=socket -uroot -p"${MYSQL_ROOT_PASSWORD}" <" db_iotlcm' < schema/13-seed-flow-package.sql +-- ============================================================ + +SET NAMES utf8mb4; +USE `db_iotlcm`; + +-- 留空,由使用者按上述方式补齐 diff --git a/schema/README.md b/schema/README.md index 667ac62..028e599 100644 --- a/schema/README.md +++ b/schema/README.md @@ -14,22 +14,32 @@ docker compose up -d mysql ## 执行顺序 -按「结构 → 账号 → 种子数据」三阶段编号,文件名顺序即执行顺序。除 01 外全部幂等,可重复执行。 - | 序号 | 文件 | 内容 | | --- | --- | --- | -| 01 | `01-schema.sql` | 建 `db_iotlcm` 库 + 全部表结构 + 基础数据(菜单、字典、角色、租户、演示账号)。自包含:`DROP DATABASE` → `CREATE` → `USE` | +| 01 | `01-schema.sql` | 建库 + 全部表结构 + 基础数据(菜单、字典、角色、租户、演示账号)。自包含:`DROP DATABASE` → `CREATE` → `USE` | | 02 | `02-schema-fix-preview1.sql` | 补 `card_channel_assoc` 表 + 27 列。用存储过程按 `information_schema` 判断,规避 MySQL 8 无 `ADD COLUMN IF NOT EXISTS` | | 03 | `03-schema-align-prod.sql` | 补 `t_sms_template_config` 表 + 修正 `batch_no` 默认值 | -| 04 | `04-users.sh` | 建应用账号 `u_iotlcm`(口令取自 `MYSQL_APP_PASSWORD`)+ 可选库 `iotdb` | -| 05 | `05-reset-passwords.sh` | 把所有种子账号口令重置为 `MYSQL_ADMIN_PASSWORD`(按各账号自身 salt 重算哈希) | +| 04 | `04-users.sh` | 建应用账号 `iotlcm_app` + 可选库 `iotdb` | +| 05 | `05-reset-passwords.sh` | 把所有种子账号口令重置为脚本内设定的口令(按各账号自身 salt 重算哈希) | | 06 | `06-seed-channel-templates.sql` | 通道模板 23 条(上游密钥已置空) | | 07 | `07-seed-dict.sql` | 数据字典:`sys_dict_type` 86 类 + `sys_dict_data` 435 条 | | 08 | `08-seed-mock-channel.sql` | **Mock 通道 `channel_yd_mock`**。演示卡全部挂在该通道上,缺则卡片管理的通道列、筛选、开停复机均不可用 | | 09 | `09-seed-role-chain.sql` | 代理下发模板参数 + 角色下发标记 | | 10 | `10-seed-jobs.sql` | 定时任务 19 条,**默认全部停用**(避免自动全量同步压满机器) | | 11 | `11-seed-menu-align-prod.sql` | 菜单增量 27 条(含达量断网按钮权限、全量同步页) | -| 12 | `12-repair-dept-ancestors.sql` | `sys_dept.ancestors` 尾逗号归一化。全新库为空操作,仅用于修复既有库脏数据 | +| 12 | `12-repair-dept-ancestors.sql` | `sys_dept.ancestors` 尾逗号归一化。全新库为空操作 | +| 13 | `13-seed-flow-package.sql` | **占位文件**,流量套餐为空。需在管理端「套餐定价」中创建 | + +## 口令说明 + +`04-users.sh` 与 `05-reset-passwords.sh` 里的口令是**字面值**(不使用环境变量),必须与以下位置保持一致: + +| 口令 | 需同步的位置 | +| --- | --- | +| 应用账号 `iotlcm_app` | `docker-compose.yml` 的 `MYSQL_ROOT_PASSWORD`(root)与 `config/*/config.yaml` 里 database link 的口令 | +| 种子账号 | `docker-compose.yml` 里 admin 的初始化口令说明、`05-reset-passwords.sh` 的 `ADMIN_PASSWORD` | + +改口令时三处一起改,漏改会导致服务连不上库或登录失败。 ## 种子数据说明 @@ -50,44 +60,30 @@ docker compose up -d mysql | --- | --- | | 账号昵称 | `示例用户01` ~ `示例用户18` | | 邮箱 | `user01@example.com` ~ `user18@example.com` | -| 手机号 | 合法 11 位编造号(`1380000` + 4 位序号,保持互异) | +| 手机号 | 合法 11 位编造号(保持互异) | | 登录 IP | 清空 | | 头像地址 | 清空 | | 公司名 / 组织名 | `示例企业` / `示例代理` | -| 密码哈希 | 初始化时按 `MYSQL_ADMIN_PASSWORD` 重算 | | 通道密钥 | 置空 | ### 空表(正常) -以下表在种子库中为空,属预期状态: - | 表 | 说明 | | --- | --- | -| `t_sim_flow_package_info` | 流量套餐。为空时无法办理套餐/续费/改套餐,需自行在后台「套餐定价」中创建 | -| `t_sim_card` | 卡数据。可通过挡板服务的造卡接口生成测试卡 | -| `t_sim_channels` | 业务通道。Mock 通道由 `08` 脚本插入 | -| 其余 `t_*` 业务表 | 均为空,随业务操作产生数据 | - -## 首次登录 - -| 项 | 值 | -| --- | --- | -| 地址 | `http://<宿主机IP><:ADMIN_UI_PORT>` | -| 账号 | `admin` | -| 口令 | `.env` 里的 `MYSQL_ADMIN_PASSWORD` | - -其余演示账号的登录名见 `sys_user.user_name`,口令同为 `MYSQL_ADMIN_PASSWORD`。**所有账号登录后请立即修改口令。** +| `t_sim_flow_package_info` | 流量套餐,见 `13-seed-flow-package.sql` 说明 | +| `t_sim_card` | 卡数据,可通过挡板服务造卡或自行入库 | +| 其余 `t_*` 业务表 | 随业务操作产生数据 | ## 手动执行 -容器已启动后需要单独执行某个脚本: +容器已启动后单独执行某个脚本: ```bash docker compose exec -T mysql sh -c \ - 'mysql -uroot -p"$MYSQL_ROOT_PASSWORD" db_iotlcm' < schema/07-seed-dict.sql + 'exec mysql -uroot -p"" db_iotlcm' < schema/07-seed-dict.sql ``` -`.sh` 脚本需要环境变量,在容器内执行: +`.sh` 脚本: ```bash docker compose exec mysql bash /docker-entrypoint-initdb.d/04-users.sh