diff --git a/docs/deploy/binary.md b/docs/deploy/binary.md index d3f1ee8..6a427a9 100644 --- a/docs/deploy/binary.md +++ b/docs/deploy/binary.md @@ -109,7 +109,7 @@ uname -m # x86_64 → amd64;aarch64 → arm64 /opt/iotlcm/ ├── admin-svr/ │ ├── iotlcmadmin_svc -│ ├── config/config.yaml ← 从 config.example/admin-svr 复制 +│ ├── config/config.yaml ← 从 config/admin-svr 复制 │ ├── logs/ │ ├── upload/ │ └── cache/ @@ -265,7 +265,7 @@ npm ci && npm run build sudo cp -r apps/web-antd/dist /var/www/iotlcm/admin-ui ``` -nginx 配置参考部署仓的 `config.example/admin-ui/default.conf` 与 `config.example/nginx/iotlcm.conf`,把 `proxy_pass http://admin-svr:8008` 改为 `http://127.0.0.1:8008`。 +nginx 配置参考部署仓的 `config/admin-ui/default.conf` 与 `config/nginx/iotlcm.conf`,把 `proxy_pass http://admin-svr:8008` 改为 `http://127.0.0.1:8008`。 ## 验证 diff --git a/docs/deploy/build-image.md b/docs/deploy/build-image.md index aaefb66..8d790ac 100644 --- a/docs/deploy/build-image.md +++ b/docs/deploy/build-image.md @@ -123,49 +123,91 @@ docker build --build-arg GOPROXY=https://goproxy.cn,direct -t ... . ## 镜像命名规则 -部署编排按以下名称拉取镜像,自建时需保持一致: +部署编排按以下名称拉取镜像,自建时需保持一致。`<镜像仓库>` 即官方仓库前缀 `crpi-qflrqrxoohllkvgc.cn-chengdu.personal.cr.aliyuncs.com`: | 服务 | 镜像名 | | --- | --- | -| admin-svr | `/iotlcm/iotlcm-admin-svr:` | -| admin-ui | `/iotlcm/iotlcm-admin-ui:` | -| openapi | `/iotlcm/iotlcm-openapi:` | -| app-server | `/iotlcm/iotlcm-app-server:` | -| app-web | `/iotlcm/iotlcm-app-web:` | -| upstream-chan | `/iotlcm/iotlcm-upstream-chan:` | -| upstream-proxy | `/iotlcm/iotlcm-upstream-proxy:` | -| worker-svr | `/iotlcm/iotlcm-worker-svr:` | -| sms | `/iotlcm/iotlcm-sms:` | -| bot | `/iotlcm/iotlcm-bot:` | -| docs | `/iotlcm/iotlcm-docs:` | -| onelink-mock | `/iotlcm/iotlcm-onelink-mock:` | +| admin-svr | `<镜像仓库>/iotlcm/iotlcm-admin-svr:` | +| admin-ui | `<镜像仓库>/iotlcm/iotlcm-admin-ui:` | +| openapi | `<镜像仓库>/iotlcm/iotlcm-openapi:` | +| app-server | `<镜像仓库>/iotlcm/iotlcm-app-server:` | +| app-web | `<镜像仓库>/iotlcm/iotlcm-app-web:` | +| upstream-chan | `<镜像仓库>/iotlcm/iotlcm-upstream-chan:` | +| upstream-proxy | `<镜像仓库>/iotlcm/iotlcm-upstream-proxy:` | +| worker-svr | `<镜像仓库>/iotlcm/iotlcm-worker-svr:` | +| sms | `<镜像仓库>/iotlcm/iotlcm-sms:` | +| bot | `<镜像仓库>/iotlcm/iotlcm-bot:` | +| docs | `<镜像仓库>/iotlcm/iotlcm-docs:` | +| onelink-mock | `<镜像仓库>/iotlcm/iotlcm-onelink-mock:` | -基础组件(`library/mysql`、`library/redis` 等)直接使用上游官方镜像,无需自建。 +基础组件(`mysql`、`redis`、`rabbitmq`、`consul`、`nginx`)不需要构建,只需从上游同步到 `<镜像仓库>/library/`,见下节。 + +## 同步基础组件 + +平台编排不再从 Docker Hub 直连基础组件(公网不稳定,且 `8.0` 这类 tag 会随补丁升级而漂)。部署前先把五个镜像同步到官方仓库: + +```bash +REPO=crpi-qflrqrxoohllkvgc.cn-chengdu.personal.cr.aliyuncs.com + +docker login --username=sdqmx $REPO + +# 按 docker-compose.yml 中固定的版本拉取并推送 +sync_image() { + local src=$1 dst=$2 + docker pull "$src" + docker tag "$src" "$REPO/library/$dst" + docker push "$REPO/library/$dst" +} + +sync_image mysql:8.0 mysql:8.0 +sync_image redis:7.2 redis:7.2 +sync_image rabbitmq:4.3.5-management rabbitmq:4.3.5-management +sync_image hashicorp/consul:1.22 consul:1.22 +sync_image nginx:1.30 nginx:1.30 +``` + +::: warning 同步时把版本号固定到补丁位 +`mysql:8.0` 这类浮动 tag 会随上游发新补丁而变化。建议同步时锁定到具体补丁版(如 `mysql:8.0.43`),并把 `docker-compose.yml` 的 `MYSQL_VERSION` 同步改为 `8.0.43`,保证多台机器拉到的镜像完全一致。 +::: + +同步完成后校验: + +```bash +for img in mysql:8.0 redis:7.2 rabbitmq:4.3.5-management consul:1.22 nginx:1.30; do + docker manifest inspect "$REPO/library/$img" >/dev/null 2>&1 \ + && echo "✅ $img" || echo "❌ $img" +done +``` ## 推送到自己的仓库 -```bash -REGISTRY=harbor.internal.example.com -TAG=1.0.3 - -docker tag iotlcm-openapi:local $REGISTRY/iotlcm/iotlcm-openapi:$TAG -docker push $REGISTRY/iotlcm/iotlcm-openapi:$TAG -``` - -部署时 `.env` 改为: +自建镜像不需要推送回官方仓库。推到自有仓库后,把 `docker-compose.yml` 里的镜像前缀改指向它: ```bash -REGISTRY=harbor.internal.example.com +REG=harbor.internal.example.com TAG=1.0.3 + +docker tag iotlcm-openapi:local $REG/iotlcm/iotlcm-openapi:$TAG +docker login $REG +docker push $REG/iotlcm/iotlcm-openapi:$TAG ``` +```yaml +# docker-compose.yml —— 逐个替换 image 前缀 +image: 'harbor.internal.example.com/iotlcm/iotlcm-openapi:1.0.3' +``` + +::: tip 只覆盖部分服务 +只想替换其中一两个服务时,把对应镜像推到自有仓库,其余保留官方地址。此时把 `docker-compose.yml` 里那几个 `image` 单独写成完整地址,其余保持官方仓库前缀即可。 +::: + ## 批量构建脚本 ```bash #!/bin/bash set -euo pipefail -REGISTRY=${REGISTRY:?请设置 REGISTRY} +REPO=${REPO:?请设置 REPO} TAG=${TAG:-$(date +%Y%m%d)} WORKDIR=${WORKDIR:-./repos} @@ -201,12 +243,12 @@ for item in "${SERVICES[@]}"; do --build-arg BuildVersion="$VERSION" \ --build-arg CommitID="$COMMIT" \ --build-arg BuildTime="$(date -u '+%Y-%m-%dT%H:%M:%SZ')" \ - -t "$REGISTRY/iotlcm/$image:$TAG" \ + -t "$REPO/iotlcm/$image:$TAG" \ -f "$WORKDIR/$repo/${ctx}Dockerfile" \ "$WORKDIR/$repo/$ctx" done -echo "全部完成,镜像标签:$REGISTRY/iotlcm/*:$TAG" +echo "全部完成,镜像标签:$REPO/iotlcm/*:$TAG" ``` ::: warning 脚本里的 sed 只能应急 diff --git a/docs/deploy/configuration.md b/docs/deploy/configuration.md index 10ba0a4..c9d3358 100644 --- a/docs/deploy/configuration.md +++ b/docs/deploy/configuration.md @@ -1,68 +1,66 @@ --- title: 配置说明 -description: 部署环境变量与应用配置文件的填写方式 +description: 部署配置的结构、默认值与修改方式 outline: deep --- # 配置说明 -平台配置分两层: +平台配置分两层,**都随仓库分发、都带可用默认值**,无需复制或初始化即可启动: -| 层 | 位置 | 管什么 | 是否入库 | -| --- | --- | --- | --- | -| 部署层 | `.env` | 镜像仓库、口令、端口、外部服务地址 | 否 | -| 应用层 | `config/<服务>/config.yaml` | 业务参数、连接串、功能开关 | 否 | +| 层 | 位置 | 管什么 | +| --- | --- | --- | +| 编排层 | `docker-compose.yml` | 镜像地址、端口、数据库/Redis/MQ 口令、容器编排 | +| 应用层 | `config/<服务>/config.yaml` | 业务参数、连接串、功能开关 | -两者分别由 `.env.example` 与 `config.example/` 复制而来,`.gitignore` 已排除。**不要把自己的配置提交回仓库。** +::: warning 配置里是字面值,不是环境变量 +配置文件与编排文件里直接写的是具体值,**不使用 `${VAR}` 占位**。 -## 一、环境变量 +原因:GoFrame 不会展开配置文件中的 `${VAR}`(环境变量只用于覆盖配置键,不参与文件内文本替换),用占位符会导致连接串变成字面量 `${X}`,服务直接连不上库。 -```bash -cp .env.example .env +代价是改口令要改多处,见下方「改口令的正确姿势」。 +::: + +## 编排层:`docker-compose.yml` + +### 镜像地址 + +```yaml +image: 'crpi-qflrqrxoohllkvgc.cn-chengdu.personal.cr.aliyuncs.com/library/mysql:8.0' +image: 'crpi-qflrqrxoohllkvgc.cn-chengdu.personal.cr.aliyuncs.com/iotlcm/iotlcm-admin-svr:latest' ``` -### 必填项 +- 基础组件在 `<镜像仓库>/library/` 下 +- 业务镜像在 `<镜像仓库>/iotlcm/` 下 -| 变量 | 说明 | -| --- | --- | -| `REGISTRY` | 镜像仓库地址,不含协议与末尾斜杠 | -| `TAG` | 镜像标签,生产用具体版本号 | -| `MYSQL_ROOT_PASSWORD` | MySQL root 口令 | -| `MYSQL_APP_PASSWORD` | 应用账号 `u_iotlcm` 的口令 | -| `MYSQL_ADMIN_PASSWORD` | 平台 admin 账号初始口令 | -| `REDIS_PASSWORD` | Redis 口令 | -| `RABBITMQ_PASSWORD` | RabbitMQ 口令 | -| `JWT_SIGNING_KEY` | JWT 签名密钥 | +改用自有仓库时,全局替换前缀即可。 -任一项未设置时 `docker compose` 会直接报错退出,不会用空值或弱口令启动。 +### 默认口令 -生成强口令: - -```bash -openssl rand -base64 24 # 各类密码 -openssl rand -hex 32 # JWT_SIGNING_KEY -``` - -### 可选项 - -| 变量 | 不填的影响 | -| --- | --- | -| `DIAGNOSIS_INTERNAL_TOKEN` | 控制台「智能诊断」不可用 | -| `SMS_ACCESS_KEY_ID` / `SMS_ACCESS_KEY_SECRET` | 无法发送短信验证码 | -| `FEISHU_APP_ID` / `FEISHU_APP_SECRET` / `FEISHU_CHAT_ID` | 不启动 bot 即可 | -| `TDENGINE_*` | 历史流量查询不可用,主流程正常 | +| 变量 | 默认值 | 用途 | +| --- | --- | --- | +| `MYSQL_ROOT_PASSWORD` | 见文件 | MySQL root | +| `MYSQL_DATABASE` | `db_iotlcm` | 库名 | +| `RABBITMQ_DEFAULT_PASS` | 见文件 | RabbitMQ | +| redis `--requirepass` | 见文件 | Redis | ### 端口 -全部端口变量见 `.env.example`,均有默认值。改端口只改 `.env`。 +| 端口 | 服务 | 对外 | +| --- | --- | --- | +| 8008 | admin-svr | 经反向代理 | +| 8009 | admin-ui | **浏览器直接访问这个** | +| 8000 | openapi | 经反向代理 | +| 8010 / 8018 | app-server / app-web | 经反向代理 | +| 8019 | docs | 经反向代理 | +| 8080 | onelink-mock | 仅联调 | +| 3306 / 6379 / 5672 / 8500 | 基础组件 | 仅内网 | +| 8110 / 8310 / 8510 | chan / proxy | 仅内网 | +| 11190 / 11200 | sms | 仅内网 | -## 二、应用配置 +改端口直接改 `docker-compose.yml` 中对应 `ports` 的冒号左侧。 -```bash -cp -r config.example config -``` - -得到 10 份: +## 应用层:`config/` ``` config/ @@ -78,100 +76,109 @@ config/ └── worker-svr/config.yaml ``` -所有配置支持 `${VAR}` 与 `${VAR:default}` 占位,由 compose 从 `.env` 注入。**口令类字段保持占位引用即可,不要写死明文。** - -### 各服务配置要点 +### 各服务要点 #### admin-svr(管理端后端) -| 项 | 说明 | +| 项 | 默认情况 | | --- | --- | -| `database.default.link` | 库连接串,已用 `${MYSQL_APP_PASSWORD}` 拼好 | -| `database.legacyCard.link` | 旧平台库,没有就留空 | -| `jwt.signingKey` | 保持 `${JWT_SIGNING_KEY}` | -| `warning.sms.enabled` | 不用短信改 `false` | -| `warning.wechat.*` | 不用微信订阅消息改 `false` 并留空 | -| `register.email.*` | 邮件验证码的 SMTP,不用则留空 | -| `tsdb.tdengine.dsn` | 不用时序库则留空 | -| `alipay.*` | 不用支付宝整段删除 | -| `upstream.appDiagnosisToken` | 与 proxy 的 `appDiagnosis.internalToken` 一致 | +| `database.default.link` | 指向 `mysql:3306`,口令与应用账号一致 | +| `database.legacyCard.link` | 空,不使用旧平台库 | +| `jwt.signingKey` | 已填固定密钥,需与 openapi、app-server 一致 | +| `warning.sms.enabled` | `true`,未配短信服务商时建议改 `false` | +| `warning.wechat.enabled` | `false` | +| `register.email.*` | 空,不发邮件 | +| `tsdb.tdengine.dsn` | 空,不启用时序库 | +| `alipay.*` | 空,不启用支付 | +| `upstream.appDiagnosisToken` | 已填,需与 upstream-proxy 一致 | #### openapi(对外 API) -| 项 | 说明 | -| --- | --- | -| `jwt.signingKey` | 与 admin-svr 一致 | -| `database.default.link` | 建议单独建只读账号隔离 | +`jwt.signingKey` 与 admin-svr 一致;`database.default.link` 同库。建议另建只读账号用于生产。 #### worker-svr(异步任务) | 项 | 说明 | | --- | --- | -| `batch.inbound.upstreamRateLimit` | **运营商接口限流,必须按上游实际配额设置**,调太大会被限流或封禁 | -| `rabbitmq.batchExecute.maxRetries` | 批次执行失败重试次数 | -| `tsdb.tdengine.dsn` | 不用时序库则留空 | +| `batch.inbound.upstreamConcurrency` | 默认 300,机器弱或上游配额小时调低 | +| `batch.inbound.upstreamRateLimit` | 运营商限流,**必须按上游实际配额设置**,调大易被封禁 | +| `tsdb.tdengine.dsn` | 空,不启用时序库 | #### upstream-chan(运营商对接) | 项 | 说明 | | --- | --- | -| `registry.address` | Consul 地址,默认 `consul:8500` | -| `dependencies.sim_yd_mock_v5.url` | 挡板地址,对接真实运营商时删除本段 | -| `dependencies.token_refresh.skew_seconds` | 运营商 Token 提前刷新窗口 | +| `registry.address` | `consul:8500` | +| `dependencies.sim_yd_mock_v5.url` | 指向挡板 `http://onelink-mock:8080/v5/`,接真实运营商时删除本段 | -运营商通道本身(AppKey、AppSecret、接口地址)不在本文件配置,而是在平台「通道管理」中录入,存数据库。 +运营商通道本身(AppKey、AppSecret、接口地址)在平台「通道管理」中录入,存数据库,不在本文件。 #### upstream-proxy(通道缓存转发) | 项 | 说明 | | --- | --- | | `appDiagnosis.internalToken` | 与 admin-svr 的 `upstream.appDiagnosisToken` 一致 | -| `gateway.batchTimeout` | 批量转发总预算上限,**worker 侧超时必须大于此值** | +| `gateway.batchTimeout` | 默认 20m,**worker 侧超时必须大于此值** | #### app-server(小程序后端) -| 项 | 说明 | -| --- | --- | -| `jwt.signingKey` | 与 admin-svr 一致 | -| `payment.wechat.*` | 不用支付把 `enabled` 改 `false` | -| `appCardRecognition.*` | 拍照识别卡号,不用改 `false` | -| `upstream.onelinkMock.*` | 挡板联调配置,切真实运营商时 `enabled: false` | +`jwt.signingKey` 同上;`payment.wechat.enabled` 默认 `false`;`appCardRecognition.enabled` 默认 `false`(拍照识别需自备视觉模型 API)。 #### sms(短信服务) -| 项 | 说明 | +| 项 | 默认 | | --- | --- | -| `serviceType` | `1`=阿里云,`2`=腾讯云 | -| `accessKeyId` / `accessKeySecret` | 从 `.env` 注入 | -| `signName` | 短信签名,需服务商审核通过 | +| `serviceType` | `1`(阿里云) | +| `accessKeyId` / `accessKeySecret` | 空,需自行填写 | +| `signName` | `示例签名` | -#### bot(飞书通知,可选) +不填则无法发送验证码,其余功能正常。 -`feishu.appId`、`appSecret`、`chatId` 全部从 `.env` 注入。 +#### bot(飞书通知) -#### admin-ui(管理端 nginx) +`feishu.appId` / `appSecret` / `chatId` 均为空。不启动该容器即可。 -`default.conf` 中 `/api/` 反代到 `admin-svr:8008`,`/upload/` 指向共享上传目录。一般无需修改。 +#### admin-ui / nginx -#### nginx(对外入口,可选) +`admin-ui/default.conf` 把 `/api/` 反代到 `admin-svr:8008`;`nginx/iotlcm.conf` 按域名分流,需把 `your-domain.example.com` 换成实际域名。 -`iotlcm.conf` 按域名分三组 server:`api.*` → openapi,`admin.*` → 管理端与文档站,`app.*` → 小程序端。**把示例域名替换为实际域名。** +## 改口令的正确姿势 -不用自带 nginx 时,把其中 `location` 段落复制到宿主机 nginx 配置即可。 +改数据库口令时,以下**三处必须同时改**,漏一处就起不来: -## 三、配置自检 +| 位置 | 内容 | +| --- | --- | +| `docker-compose.yml` | `MYSQL_ROOT_PASSWORD`、redis `--requirepass`、`RABBITMQ_DEFAULT_PASS` | +| `config/*/config.yaml` | 各服务的 `database.default.link`、`redis.default.pass`、`rabbitmq.dsn` | +| `schema/04-users.sh`、`schema/05-reset-passwords.sh` | 脚本内的 `APP_PASSWORD` / `ADMIN_PASSWORD` / `ROOT_PASSWORD` | -启动前验证: +::: tip 一次性全局替换 +```bash +OLD='原口令' +NEW='新口令' + +# 编排 + 配置 +grep -rl "$OLD" docker-compose.yml config/ | xargs sed -i "s/$OLD/$NEW/g" +# 初始化脚本 +grep -rl "$OLD" schema/ | xargs sed -i "s/$OLD/$NEW/g" +``` +::: + +::: danger 口令不能含 @ : / 等字符 +连接串格式为 `mysql:用户:口令@tcp(主机:端口)/库`,口令里的 `@`、`:`、`/` 会被解析成分隔符,导致连接失败。用字母数字组合。 +::: + +## 配置自检 ```bash -# 检查展开结果(不启动容器) -docker compose config - -# 只检查必填项是否齐全 +# 编排语法 docker compose config --quiet + +# 看某个服务最终的配置展开 +docker compose config | sed -n '/admin-svr:/,/^ [a-z]/p' ``` -配置语法错误会导致服务启动后立即退出,用日志定位: +配置语法错误会导致服务启动后立刻退出,看日志定位: ```bash docker compose logs --tail=50 admin-svr diff --git a/docs/deploy/index.md b/docs/deploy/index.md index c41f21c..94668b6 100644 --- a/docs/deploy/index.md +++ b/docs/deploy/index.md @@ -15,10 +15,9 @@ cd iotlcm-deploy ```text iotlcm-deploy/ -├── docker-compose.yml # 服务编排 -├── .env.example # 环境变量模板 -├── config.example/ # 应用配置模板(10 份) -└── schema/ # 数据库初始化脚本(12 个) +├── docker-compose.yml # 服务编排(含默认口令与端口) +├── config/ # 各服务配置,10 份,已带可用默认值 +└── schema/ # 数据库初始化脚本,13 个,首次启动自动执行 ``` ## 部署内容 @@ -37,20 +36,27 @@ iotlcm-deploy/ ## 部署流程 ```bash -cp .env.example .env # 1. 环境变量 -cp -r config.example config # 2. 应用配置 -docker compose up -d # 3. 启动 +git clone <部署仓地址> iotlcm-deploy +cd iotlcm-deploy +docker compose up -d ``` -首次启动自动建库并导入 schema,约 1~2 分钟。 +三步,不需要复制或修改任何文件——配置与编排都随仓库分发且带可用默认值。首次启动自动建库并导入 schema,约 1~2 分钟。 + +启动后访问 `http://<宿主机IP>:8009`,账号 `admin`,口令见 `docker-compose.yml`。 + +::: warning 默认口令只用于试用 +正式部署前必须修改数据库、Redis、RabbitMQ、admin 账号口令与 JWT 密钥,详见[配置说明](configuration)。 +::: ## 文档导航 | 文档 | 内容 | | --- | --- | -| [环境准备](prerequisites) | 硬件、系统、Docker 版本、端口规划 | -| [配置说明](configuration) | `.env` 与 `config/` 各项含义 | +| [环境准备](prerequisites) | 硬件、系统、Docker 版本、镜像仓库、端口规划 | +| [配置说明](configuration) | `docker-compose.yml` 与 `config/` 各项含义 | | [启动与验证](install) | 启动流程、验证清单、首次登录 | +| [其他部署方式](alternatives) | 二进制、自建镜像、分离、离线 | | [可选服务](optional) | 接口挡板、飞书通知、反向代理 | | [升级与备份](operations) | 版本固定、升级回滚、数据备份 | | [故障排查](troubleshooting) | 常见问题与处理 | @@ -88,4 +94,4 @@ docker compose up -d # 3. 启动 | 11190 / 11200 | sms | 仅内网 | | 8080 | onelink-mock | 仅联调 | -端口冲突时修改 `.env` 中对应变量,不要直接改 `docker-compose.yml`。 +端口冲突时修改 `docker-compose.yml` 中对应变量,不要直接改 `docker-compose.yml`。 diff --git a/docs/deploy/install.md b/docs/deploy/install.md index c1f1626..c1a6643 100644 --- a/docs/deploy/install.md +++ b/docs/deploy/install.md @@ -9,6 +9,9 @@ outline: deep ## 启动 ```bash +git clone <部署仓地址> iotlcm-deploy +cd iotlcm-deploy + # 首次部署建议前台启动,便于观察初始化过程 docker compose up @@ -16,10 +19,12 @@ docker compose up docker compose up -d ``` +不需要复制或修改任何文件,配置已带可用默认值。 + ### 首次启动发生什么 1. **MySQL 建库并导入 schema**(约 1~2 分钟) - `schema/` 下 12 个脚本按文件名顺序执行:建表 → 结构补齐 → 创建应用账号 → 重置种子账号口令 → 导入通道模板/字典/菜单等种子数据 + `schema/` 下 13 个脚本按文件名顺序执行:建表 → 结构补齐 → 创建应用账号 → 重置种子账号口令 → 导入通道模板/字典/菜单等种子数据 2. MySQL 通过健康检查后,`admin-svr`、`openapi`、`worker-svr` 依次启动 3. 各服务向 Consul 注册 @@ -137,7 +142,7 @@ curl -s -o /dev/null -w '%{http_code}\n' http://127.0.0.1:11190/healthz | 项 | 值 | | --- | --- | | 账号 | `admin` | -| 口令 | `.env` 中的 `MYSQL_ADMIN_PASSWORD` | +| 口令 | `docker-compose.yml` 中 admin 的默认口令(首次登录后立即修改) | 能进入首页工作台、左侧菜单完整显示即部署成功。 diff --git a/docs/deploy/offline.md b/docs/deploy/offline.md index d223e00..2daae0d 100644 --- a/docs/deploy/offline.md +++ b/docs/deploy/offline.md @@ -97,8 +97,7 @@ docker images | grep iotlcm 导入后镜像已在本机,compose 不会再尝试拉取: ```bash -cp .env.example .env -vi .env # REGISTRY 与 TAG 需与导入的镜像标签完全一致 +# 把 docker-compose.yml 里的镜像地址与 TAG 改成与导入的镜像一致 cp -r config.example config vi config/*/config.yaml @@ -106,7 +105,7 @@ docker compose up -d ``` ::: warning REGISTRY 与 TAG 必须与导入的镜像名一致 -`docker load` 只恢复镜像名,不会改标签。若 `.env` 里写 `TAG=latest` 而导入的是 `1.0.3`,compose 会认为镜像不存在并尝试拉取,离线环境直接失败。 +`docker load` 只恢复镜像名,不会改标签。若 `docker-compose.yml` 里写 `TAG=latest` 而导入的是 `1.0.3`,compose 会认为镜像不存在并尝试拉取,离线环境直接失败。 用这条命令核对: @@ -133,7 +132,7 @@ for img in $(cat images.txt); do done ``` -然后目标机的 `.env` 改为: +然后目标机的 `docker-compose.yml` 改为: ```bash REGISTRY=harbor.internal.example.com @@ -165,7 +164,7 @@ docker compose pull | 资源 | 说明 | | --- | --- | | 部署仓代码 | `git clone` 或直接打包 `iotlcm-deploy/` 目录带过去 | -| 配置模板 | 已包含在部署仓 `config.example/` | +| 配置模板 | 已包含在部署仓 `config/` | | 数据库脚本 | 已包含在部署仓 `schema/` | | Docker 与 Compose | 目标机需预先安装,离线安装包需单独准备 | | 时区数据 | 若使用 `Asia/Shanghai`,确认容器内 tzdata 完整(官方镜像已内置) | diff --git a/docs/deploy/operations.md b/docs/deploy/operations.md index 7ba8ef2..f451bf4 100644 --- a/docs/deploy/operations.md +++ b/docs/deploy/operations.md @@ -14,7 +14,7 @@ outline: deep - 出问题无法确定运行版本 - 回滚时没有明确目标 -`.env` 中指定: +`docker-compose.yml` 中指定: ```bash TAG=1.0.3 @@ -23,7 +23,7 @@ TAG=1.0.3 记录当前部署版本: ```bash -echo "$(date '+%Y-%m-%d %H:%M') TAG=$(grep '^TAG=' .env | cut -d= -f2)" >> deploy-history.log +echo "$(date '+%Y-%m-%d %H:%M') 镜像=$(grep -m1 'iotlcm-admin-svr:' docker-compose.yml)" >> deploy-history.log ``` ## 升级 @@ -33,7 +33,7 @@ echo "$(date '+%Y-%m-%d %H:%M') TAG=$(grep '^TAG=' .env | cut -d= -f2)" >> depl ./backup.sh # 2. 拉新镜像 -vi .env # 修改 TAG +vi docker-compose.yml # 修改镜像 TAG docker compose pull # 3. 更新 @@ -53,7 +53,7 @@ docker compose up -d --no-deps admin-svr ## 回滚 ```bash -vi .env # TAG 改回旧版本 +vi docker-compose.yml # TAG 改回旧版本 docker compose pull docker compose up -d ``` @@ -102,7 +102,7 @@ docker compose exec -T mysql sh -c \ | gzip > "${DEST}/db_iotlcm.sql.gz" echo "[2/3] 备份配置..." -tar czf "${DEST}/config.tar.gz" config/ .env +tar czf "${DEST}/config.tar.gz" config/ docker-compose.yml echo "[3/3] 备份上传文件..." tar czf "${DEST}/upload.tar.gz" data/upload/ 2>/dev/null || echo " 上传目录为空,跳过" @@ -136,7 +136,7 @@ gunzip -c db_iotlcm-20260101.sql.gz | \ | 内容 | 位置 | 重要性 | | --- | --- | --- | | 数据库 | MySQL 容器内 `db_iotlcm` | **最高**,业务数据全部在此 | -| 配置 | `config/` + `.env` | 高,丢失需重新配置 | +| 配置 | `config/` + `docker-compose.yml` | 高,丢失需重新配置 | | 上传文件 | `data/upload/` | 中,附件与图片 | | Redis 数据 | `data/redis/` | 低,缓存可重建 | | RabbitMQ 队列 | `data/rabbitmq/` | 低,未消费消息会丢失 | diff --git a/docs/deploy/optional.md b/docs/deploy/optional.md index d162cb8..50feff2 100644 --- a/docs/deploy/optional.md +++ b/docs/deploy/optional.md @@ -72,7 +72,7 @@ docker compose --profile with-mock stop onelink-mock ### 准备 -在飞书开放平台创建自建应用,获取 `appId`、`appSecret` 与目标群的 `chatId`,填入 `.env`: +在飞书开放平台创建自建应用,获取 `appId`、`appSecret` 与目标群的 `chatId`,填入 `docker-compose.yml`: ```bash FEISHU_APP_ID=cli_xxxxxxxx @@ -110,7 +110,7 @@ bot 读取 `worker-svr` 生成的全量同步归档(`./data/logs/worker-svr/fu docker compose --profile with-nginx up -d ``` -默认监听 80,改 `.env` 的 `NGINX_HTTP_PORT` 可调整。 +默认监听 80,改 `docker-compose.yml` 的 `NGINX_HTTP_PORT` 可调整。 ### 使用宿主机 nginx diff --git a/docs/deploy/prerequisites.md b/docs/deploy/prerequisites.md index 86f0177..1eb0f84 100644 --- a/docs/deploy/prerequisites.md +++ b/docs/deploy/prerequisites.md @@ -35,7 +35,7 @@ outline: deep | 操作系统 | Linux x86_64(CentOS 7+ / Ubuntu 20.04+ / Debian 11+) | | 内核 | 3.10 以上 | | 文件系统 | ext4 / xfs | -| 时区 | 建议 `Asia/Shanghai`,与 `.env` 的 `TZ` 保持一致 | +| 时区 | 建议 `Asia/Shanghai`,与 `docker-compose.yml` 的 `TZ` 保持一致 | ## Docker 要求 @@ -55,22 +55,40 @@ docker compose version ## 镜像仓库 -平台镜像由官方镜像仓库分发,需要: +平台镜像发布在阿里云容器镜像服务,**仓库类型为公开,无需登录即可拉取**。 -1. 能访问镜像仓库地址(内网仓库需先配置网络或代理) -2. 具备拉取权限 +| 项 | 值 | +| --- | --- | +| 公网地址 | `crpi-qflrqrxoohllkvgc.cn-chengdu.personal.cr.aliyuncs.com` | +| VPC 地址 | `crpi-qflrqrxoohllkvgc-vpc.cn-chengdu.personal.cr.aliyuncs.com` | +| 命名空间 | `iotlcm` | +| 地域 | 西南1(成都) | -```bash -docker login <镜像仓库地址> +业务镜像路径为: + +```text +crpi-qflrqrxoohllkvgc.cn-chengdu.personal.cr.aliyuncs.com/iotlcm/iotlcm-admin-svr:1.0.3 +crpi-qflrqrxoohllkvgc.cn-chengdu.personal.cr.aliyuncs.com/iotlcm/iotlcm-openapi:1.0.3 +... ``` -`.env` 的 `REGISTRY` 填写仓库地址,不含 `https://` 与末尾斜杠: +`docker-compose.yml` 里的镜像地址已预置为上述公网地址,一般无需修改。 -```bash -REGISTRY=registry.example.com +::: tip 基础组件也在同一仓库 +MySQL、Redis、RabbitMQ、Consul、nginx 同样托管在 `library/` 命名空间下,不从 Docker Hub 直连(公网不稳定且 tag 会漂)。版本已在编排文件中固定,**必须与仓库里实际同步的标签一致**。 +::: + +::: warning 基础组件需先同步 +部署前 `library/` 下必须已有这五个镜像,否则拉取失败。同步方法见[自建镜像](build-image)的「同步基础组件」一节。 +::: + +::: tip 阿里云 VPC 地址 +若部署在阿里云同地域 ECS 上,可把编排文件里的镜像前缀改为 VPC 地址,走内网流量、不消耗公网带宽: + +```yaml +image: 'crpi-qflrqrxoohllkvgc-vpc.cn-chengdu.personal.cr.aliyuncs.com/library/mysql:8.0' ``` - -基础组件从 `/library/` 拉取(mysql、redis、rabbitmq、consul、nginx),业务镜像从 `/iotlcm/` 拉取。 +::: ## 网络与防火墙 @@ -96,7 +114,7 @@ firewall-cmd --reload | 微信支付 | 在线支付 | 支付功能不可用 | | 飞书 | 运维通知 | 不启动 bot 即可 | -TDengine 需开启 WebSocket 接口(默认 6041),在 `.env` 中配置: +TDengine 需开启 WebSocket 接口(默认 6041),在 `docker-compose.yml` 中配置: ```bash TDENGINE_HOST=tdengine.example.com diff --git a/docs/deploy/split.md b/docs/deploy/split.md index 756506b..3520a00 100644 --- a/docs/deploy/split.md +++ b/docs/deploy/split.md @@ -144,15 +144,14 @@ upstream: ## 四、启动 ```bash -cp .env.example .env -vi .env # REGISTRY、TAG、各类口令 +# 按需修改 docker-compose.app.yml 的镜像地址、端口与口令 cp -r config.example config vi config/*/config.yaml # 按上节改为外部地址 docker compose -f docker-compose.app.yml up -d ``` -此时 `.env` 中的 `MYSQL_*`、`REDIS_PASSWORD`、`RABBITMQ_PASSWORD` 不再用于启动中间件容器,但仍作为配置中的变量来源,**取值要与中间件实际口令一致**。 +此时 `docker-compose.yml` 中的 `MYSQL_*`、`REDIS_PASSWORD`、`RABBITMQ_PASSWORD` 不再用于启动中间件容器,但仍作为配置中的变量来源,**取值要与中间件实际口令一致**。 ## 五、验证 diff --git a/docs/deploy/troubleshooting.md b/docs/deploy/troubleshooting.md index 38b95dc..afb57ef 100644 --- a/docs/deploy/troubleshooting.md +++ b/docs/deploy/troubleshooting.md @@ -27,7 +27,7 @@ docker compose logs mysql | tail -50 | 日志关键词 | 原因 | 处理 | | --- | --- | --- | -| `Access denied` | root 口令与旧数据卷不一致 | 改 `.env` 与卷内一致,或清空 `data/mysql` 重建 | +| `Access denied` | root 口令与旧数据卷不一致 | 改 `docker-compose.yml` 与卷内一致,或清空 `data/mysql` 重建 | | `Can't create/write to file` | 目录权限 | `sudo chown -R 999:999 data/mysql` | | `No space left on device` | 磁盘满 | 清理磁盘 | | `Can't open shared library` | 架构不匹配 | 确认镜像与宿主机架构一致 | @@ -62,7 +62,7 @@ docker compose logs --tail=80 admin-svr | --- | --- | --- | | `possible config files "config" not found` | `config/` 不存在或挂载失败 | `cp -r config.example config`,确认 `config/admin-svr/config.yaml` 存在 | | `dial tcp mysql:3306: connection refused` | MySQL 未就绪 | 等 MySQL healthy | -| `Access denied for user 'u_iotlcm'` | 应用账号口令与库内不一致 | 确认 `.env` 的 `MYSQL_APP_PASSWORD` 与初始化时一致 | +| `Access denied for user 'u_iotlcm'` | 应用账号口令与库内不一致 | 确认 `docker-compose.yml` 的 `MYSQL_APP_PASSWORD` 与初始化时一致 | | `panic: unsupported provider xxx` | 通道模板与镜像版本不匹配 | 确认镜像版本与 schema 版本配套 | ## 功能类 @@ -71,7 +71,7 @@ docker compose logs --tail=80 admin-svr **原因**:`JWT_SIGNING_KEY` 在服务间不一致。 -确认 `admin-svr`、`openapi`、`app-server` 三份配置的 `jwt.signingKey` 都引用 `${JWT_SIGNING_KEY}` 且 `.env` 有值,然后重启: +确认 `admin-svr`、`openapi`、`app-server` 三份配置的 `jwt.signingKey` 都引用 `${JWT_SIGNING_KEY}` 且 `docker-compose.yml` 有值,然后重启: ```bash docker compose restart admin-svr openapi app-server @@ -149,7 +149,7 @@ docker compose logs upstream-chan --tail=50 docker compose logs worker-svr | grep -i 'tdengine\|taos' | tail -20 ``` -确认 `.env` 的 `TDENGINE_*` 已填,且 WebSocket 端口(默认 6041)可达。不用该功能留空即可。 +确认 `docker-compose.yml` 的 `TDENGINE_*` 已填,且 WebSocket 端口(默认 6041)可达。不用该功能留空即可。 ### 短信发不出去 @@ -160,7 +160,7 @@ docker compose logs sms --tail=50 | 报错 | 原因 | | --- | --- | -| `InvalidAccessKeyId` | `.env` 中 AK 未填或错误 | +| `InvalidAccessKeyId` | `docker-compose.yml` 中 AK 未填或错误 | | `isv.SMS_SIGNATURE_ILLEGAL` | `signName` 与服务商审核签名不一致 | | `isv.SMS_TEMPLATE_ILLEGAL` | 模板 ID 未审核通过 | | `缺少 config.templateId` | 场景模板库未配置,调用方需自带 templateId |