docs: 补充其他部署方式(二进制、自建镜像、分离、离线)
新增「其他部署方式」分组,共 5 页: - 方式对比与选型:5 种方式对照、服务依赖表、服务间通信易错点 - 二进制部署:各服务 Go 版本/CGO/构建目录/产物名对照表, admin-svr 需 CGO 的说明,交叉编译限制,systemd unit 模板, 静态前端交给 nginx,升级回滚流程 - 自建镜像:各仓 Dockerfile 位置与构建上下文、构建参数、 镜像命名规则、批量构建脚本、常见问题 - 分离部署:中间件独立,业务机精简 compose,配置改为外部地址 - 离线部署:镜像导出导入、校验、内网镜像仓库方案 同时记录一个实际阻塞:openapi/app/admin-ui 共 5 个 Dockerfile 的 FROM 仍指向私有镜像仓库,外部环境无法构建,页内给出替换方法。
This commit is contained in:
@@ -87,6 +87,17 @@ export default defineConfig({
|
|||||||
{ text: '启动与验证', link: '/deploy/install' },
|
{ text: '启动与验证', link: '/deploy/install' },
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
text: '其他部署方式',
|
||||||
|
collapsed: false,
|
||||||
|
items: [
|
||||||
|
{ text: '方式对比与选型', link: '/deploy/alternatives' },
|
||||||
|
{ text: '二进制部署', link: '/deploy/binary' },
|
||||||
|
{ text: '自建镜像', link: '/deploy/build-image' },
|
||||||
|
{ text: '分离部署', link: '/deploy/split' },
|
||||||
|
{ text: '离线部署', link: '/deploy/offline' },
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
text: '运维',
|
text: '运维',
|
||||||
collapsed: false,
|
collapsed: false,
|
||||||
|
|||||||
@@ -0,0 +1,64 @@
|
|||||||
|
---
|
||||||
|
title: 其他部署方式
|
||||||
|
description: 二进制部署、自建镜像、分离部署与离线部署
|
||||||
|
outline: deep
|
||||||
|
---
|
||||||
|
|
||||||
|
# 其他部署方式
|
||||||
|
|
||||||
|
[启动与验证](install) 描述的是 **Docker Compose 单机部署**,也是推荐方式。本组文档覆盖其他场景。
|
||||||
|
|
||||||
|
## 方式对比
|
||||||
|
|
||||||
|
| 方式 | 适用场景 | 复杂度 | 参考 |
|
||||||
|
| --- | --- | --- | --- |
|
||||||
|
| **单机 Compose**(推荐) | 试用、中小规模生产 | 低 | [启动与验证](install) |
|
||||||
|
| **二进制部署** | 不能装 Docker,或需纳入 systemd 体系 | 中 | [二进制部署](binary) |
|
||||||
|
| **自建镜像** | 需改代码、加依赖、适配私有基础镜像 | 中 | [自建镜像](build-image) |
|
||||||
|
| **分离部署** | 数据库走云托管,或中间件已有独立集群 | 中 | [分离部署](split) |
|
||||||
|
| **离线部署** | 服务器无法访问镜像仓库 | 中 | [离线部署](offline) |
|
||||||
|
|
||||||
|
## 服务依赖关系
|
||||||
|
|
||||||
|
选择部署方式前需了解各服务依赖哪些组件:
|
||||||
|
|
||||||
|
| 服务 | 依赖 |
|
||||||
|
| --- | --- |
|
||||||
|
| admin-svr | MySQL、Redis、RabbitMQ |
|
||||||
|
| openapi | MySQL、Redis、RabbitMQ |
|
||||||
|
| worker-svr | MySQL、Redis、RabbitMQ |
|
||||||
|
| app-server | MySQL、Redis |
|
||||||
|
| upstream-chan | MySQL、Redis、Consul |
|
||||||
|
| upstream-proxy | MySQL、Redis、Consul |
|
||||||
|
| admin-ui | admin-svr(反向代理) |
|
||||||
|
| nginx | admin-ui、openapi、app-web、docs |
|
||||||
|
| sms | 无 |
|
||||||
|
| docs | 无 |
|
||||||
|
| onelink-mock | 无 |
|
||||||
|
|
||||||
|
## 通用前提
|
||||||
|
|
||||||
|
无论哪种方式,这三项不变:
|
||||||
|
|
||||||
|
1. **配置文件必须能被服务读到**——容器部署时挂载到 `/app/config`,二进制部署时放在工作目录的 `config/`
|
||||||
|
2. **`JWT_SIGNING_KEY` 在 admin-svr、openapi、app-server 三处必须一致**
|
||||||
|
3. **数据库需先完成初始化**——`schema/` 脚本按顺序执行一次
|
||||||
|
|
||||||
|
## 服务间通信方式
|
||||||
|
|
||||||
|
配置文件里通过**服务名**互访,例如:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
database:
|
||||||
|
default:
|
||||||
|
link: "mysql:u_iotlcm:...@tcp(mysql:3306)/db_iotlcm"
|
||||||
|
upstream:
|
||||||
|
proxy:
|
||||||
|
address: "upstream-proxy:8510"
|
||||||
|
```
|
||||||
|
|
||||||
|
这些名称在单机 Compose 中由 Docker 网络解析。**切换到二进制部署或分离部署时必须改为实际地址**(`127.0.0.1` 或内网 IP),这是最容易遗漏的一步。
|
||||||
|
|
||||||
|
::: danger 最常见的部署失败原因
|
||||||
|
只改了数据库地址,忘了改 `upstream-proxy:8510`、`upstream-chan:8110` 这类服务名。症状是服务能启动、数据库也通,但批次执行、智能诊断全部超时。
|
||||||
|
:::
|
||||||
@@ -0,0 +1,321 @@
|
|||||||
|
---
|
||||||
|
title: 二进制部署
|
||||||
|
description: 直接编译 Go 程序运行,不依赖 Docker
|
||||||
|
outline: deep
|
||||||
|
---
|
||||||
|
|
||||||
|
# 二进制部署
|
||||||
|
|
||||||
|
不使用容器,把各服务编译为可执行文件,用 systemd 托管。
|
||||||
|
|
||||||
|
## 适用场景
|
||||||
|
|
||||||
|
- 服务器不允许安装 Docker
|
||||||
|
- 需要把服务纳入既有的 systemd / 进程管理体系统一运维
|
||||||
|
- 需要针对特定 CPU 架构或内核参数做优化
|
||||||
|
|
||||||
|
## 构建环境
|
||||||
|
|
||||||
|
| 项 | 要求 |
|
||||||
|
| --- | --- |
|
||||||
|
| Go | 按各服务 `go.mod` 要求,最低 1.23(见下表) |
|
||||||
|
| GCC | admin-svr 需要(`CGO_ENABLED=1`,内存库用 SQLite) |
|
||||||
|
| 系统 | 建议与目标服务器同发行版,避免 libc 差异 |
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Debian / Ubuntu
|
||||||
|
apt-get install -y build-essential
|
||||||
|
|
||||||
|
# CentOS / Rocky
|
||||||
|
yum groupinstall -y "Development Tools"
|
||||||
|
```
|
||||||
|
|
||||||
|
::: tip 其余服务可静态编译
|
||||||
|
除 admin-svr 外,其余服务 `CGO_ENABLED=0`,产物为静态二进制,可直接拷到任意同架构 Linux 运行。
|
||||||
|
:::
|
||||||
|
|
||||||
|
## 各服务构建参数
|
||||||
|
|
||||||
|
| 服务 | 仓库 | Go 版本 | CGO | 构建目录 | 产物名 | 监听端口 |
|
||||||
|
| --- | --- | --- | --- | --- | --- | --- |
|
||||||
|
| admin-svr | `iotlcm-admin-svr` | 1.23 | **需开启** | `server/` | `iotlcmadmin_svc` | 8008 |
|
||||||
|
| openapi | `iotlcm-openapi` | 1.23 | 关闭 | 根目录 | `iotlcm-openapi` | 8000 |
|
||||||
|
| worker-svr | `iotlcm-worker-svr` | 1.25 | 关闭 | 根目录 | `iotlcm-worker-svr` | 无(队列消费) |
|
||||||
|
| upstream-chan | `iotlcm-upstream-chan` | 1.25 | 关闭 | 根目录 | `iotlcmupstreamchan_svc` | 8110 / 8310 |
|
||||||
|
| upstream-proxy | `iotlcm-upstream-proxy` | 1.25 | 关闭 | 根目录 | `iotlcmupstreamproxy_svc` | 8510 |
|
||||||
|
| app-server | `iotlcm-app` | 1.23 | 关闭 | `server/` | `iotlcm-app-server` | 8010 |
|
||||||
|
| sms | `iotlcm-sms` | 1.25 | 关闭 | 根目录 | `iotlcm-sms` | 11190 / 11200 |
|
||||||
|
| bot | `iotlcm-bot` | 1.23 | 关闭 | `cmd/iotlcm-bot` | `iotlcm-bot` | 无 |
|
||||||
|
|
||||||
|
::: warning 仓库里的 Dockerfile 不能直接照搬
|
||||||
|
部分仓库的 Dockerfile 基础镜像指向私有仓库(见[自建镜像](build-image)),二进制构建不受影响,但 `FROM` 行需要替换。
|
||||||
|
:::
|
||||||
|
|
||||||
|
## 构建
|
||||||
|
|
||||||
|
### admin-svr(需要 CGO)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git clone https://git.5iot.com/iotlcm-public/iotlcm-admin-svr.git
|
||||||
|
cd iotlcm-admin-svr/server
|
||||||
|
|
||||||
|
CGO_ENABLED=1 GOOS=linux GOARCH=amd64 \
|
||||||
|
go build -trimpath \
|
||||||
|
-ldflags "-s -w \
|
||||||
|
-X main.BuildVersion=$(git describe --tags --always) \
|
||||||
|
-X main.CommitID=$(git rev-parse --short HEAD) \
|
||||||
|
-X main.BuildTime=$(date -u '+%Y-%m-%dT%H:%M:%SZ')" \
|
||||||
|
-o iotlcmadmin_svc .
|
||||||
|
```
|
||||||
|
|
||||||
|
### 其余服务(静态编译)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git clone https://git.5iot.com/iotlcm-public/iotlcm-openapi.git
|
||||||
|
cd iotlcm-openapi
|
||||||
|
|
||||||
|
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 \
|
||||||
|
go build -trimpath \
|
||||||
|
-ldflags "-s -w \
|
||||||
|
-X main.BuildVersion=$(git describe --tags --always) \
|
||||||
|
-X main.CommitID=$(git rev-parse --short HEAD) \
|
||||||
|
-X main.BuildTime=$(date -u '+%Y-%m-%dT%H:%M:%SZ')" \
|
||||||
|
-o iotlcm-openapi .
|
||||||
|
```
|
||||||
|
|
||||||
|
替换仓库名与产物名即可用于其他服务,`bot` 需要指定子目录:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd iotlcm-bot
|
||||||
|
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -trimpath -o iotlcm-bot ./cmd/iotlcm-bot
|
||||||
|
```
|
||||||
|
|
||||||
|
### 交叉编译说明
|
||||||
|
|
||||||
|
| 服务 | 能否交叉编译 |
|
||||||
|
| --- | --- |
|
||||||
|
| admin-svr(CGO) | ❌ 需在目标架构上编译,或用对应架构的交叉工具链 |
|
||||||
|
| 其余(静态) | ✅ 可直接 `GOOS=linux GOARCH=arm64` |
|
||||||
|
|
||||||
|
查看服务器架构:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
uname -m # x86_64 → amd64;aarch64 → arm64
|
||||||
|
```
|
||||||
|
|
||||||
|
## 部署布局
|
||||||
|
|
||||||
|
```text
|
||||||
|
/opt/iotlcm/
|
||||||
|
├── admin-svr/
|
||||||
|
│ ├── iotlcmadmin_svc
|
||||||
|
│ ├── config/config.yaml ← 从 config.example/admin-svr 复制
|
||||||
|
│ ├── logs/
|
||||||
|
│ ├── upload/
|
||||||
|
│ └── cache/
|
||||||
|
├── openapi/
|
||||||
|
│ ├── iotlcm-openapi
|
||||||
|
│ ├── config/config.yaml
|
||||||
|
│ └── logs/
|
||||||
|
├── worker-svr/
|
||||||
|
│ ├── iotlcm-worker-svr
|
||||||
|
│ ├── config/config.yaml
|
||||||
|
│ └── logs/
|
||||||
|
├── upstream-chan/
|
||||||
|
├── upstream-proxy/
|
||||||
|
├── app-server/
|
||||||
|
│ ├── iotlcm-app-server
|
||||||
|
│ ├── config/config.yaml
|
||||||
|
│ └── resource/
|
||||||
|
│ ├── log/server/
|
||||||
|
│ └── upload/
|
||||||
|
├── sms/
|
||||||
|
└── bot/
|
||||||
|
```
|
||||||
|
|
||||||
|
**配置文件放 `config/config.yaml`**(相对工作目录),这是 GoFrame 的默认搜索路径。启动时工作目录必须在服务目录内。
|
||||||
|
|
||||||
|
### 目录准备
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo mkdir -p /opt/iotlcm/{admin-svr,openapi,worker-svr,upstream-chan,upstream-proxy,app-server,sms,bot}
|
||||||
|
sudo useradd -r -s /sbin/nologin iotlcm
|
||||||
|
sudo chown -R iotlcm:iotlcm /opt/iotlcm
|
||||||
|
```
|
||||||
|
|
||||||
|
## 修改配置中的服务地址
|
||||||
|
|
||||||
|
容器部署时配置里写的是服务名(`mysql:3306`、`upstream-proxy:8510`),二进制部署必须改为实际地址:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
# admin-svr / openapi / worker-svr / app-server
|
||||||
|
database:
|
||||||
|
default:
|
||||||
|
link: "mysql:u_iotlcm:<口令>@tcp(127.0.0.1:3306)/db_iotlcm?charset=utf8mb4&parseTime=True&loc=Asia%2FShanghai"
|
||||||
|
redis:
|
||||||
|
default:
|
||||||
|
address: "127.0.0.1:6379"
|
||||||
|
rabbitmq:
|
||||||
|
dsn: "amqp://<用户>:<口令>@127.0.0.1:5672/"
|
||||||
|
|
||||||
|
# upstream-chan / upstream-proxy
|
||||||
|
registry:
|
||||||
|
address: "127.0.0.1:8500"
|
||||||
|
|
||||||
|
# 上游服务地址
|
||||||
|
upstream:
|
||||||
|
proxy:
|
||||||
|
address: "127.0.0.1:8510"
|
||||||
|
gateway:
|
||||||
|
address: "127.0.0.1:8110"
|
||||||
|
```
|
||||||
|
|
||||||
|
::: danger logger.path 也要改
|
||||||
|
配置里的 `logger.path` 在容器版本中是 `/app/logs`,二进制部署要改为实际路径,例如 `/opt/iotlcm/admin-svr/logs`,否则会因目录不存在启动失败。
|
||||||
|
:::
|
||||||
|
|
||||||
|
## systemd 托管
|
||||||
|
|
||||||
|
以为 `admin-svr` 为例,保存为 `/etc/systemd/system/iotlcm-admin-svr.service`:
|
||||||
|
|
||||||
|
```ini
|
||||||
|
[Unit]
|
||||||
|
Description=IotLCM Admin Service
|
||||||
|
After=network-online.target mysql.service redis.service
|
||||||
|
Wants=network-online.target
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=simple
|
||||||
|
User=iotlcm
|
||||||
|
Group=iotlcm
|
||||||
|
WorkingDirectory=/opt/iotlcm/admin-svr
|
||||||
|
ExecStart=/opt/iotlcm/admin-svr/iotlcmadmin_svc
|
||||||
|
Restart=always
|
||||||
|
RestartSec=5s
|
||||||
|
LimitNOFILE=65535
|
||||||
|
|
||||||
|
# 环境变量(JWT 密钥等敏感值建议放独立文件)
|
||||||
|
EnvironmentFile=-/etc/iotlcm/admin-svr.env
|
||||||
|
|
||||||
|
# 日志交给 journald,也可用配置里的文件日志
|
||||||
|
StandardOutput=journal
|
||||||
|
StandardError=journal
|
||||||
|
|
||||||
|
# 安全加固
|
||||||
|
NoNewPrivileges=true
|
||||||
|
PrivateTmp=true
|
||||||
|
ProtectSystem=full
|
||||||
|
ProtectHome=true
|
||||||
|
ReadWritePaths=/opt/iotlcm/admin-svr
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
||||||
|
```
|
||||||
|
|
||||||
|
`/etc/iotlcm/admin-svr.env`:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
JWT_SIGNING_KEY=<与其它服务一致的密钥>
|
||||||
|
```
|
||||||
|
|
||||||
|
启用:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo systemctl daemon-reload
|
||||||
|
sudo systemctl enable --now iotlcm-admin-svr
|
||||||
|
sudo systemctl status iotlcm-admin-svr
|
||||||
|
```
|
||||||
|
|
||||||
|
### 各服务的差异点
|
||||||
|
|
||||||
|
| 服务 | 特殊处理 |
|
||||||
|
| --- | --- |
|
||||||
|
| admin-svr | 需 `ReadWritePaths` 包含 upload 与 logs 目录 |
|
||||||
|
| worker-svr | 无监听端口,`After` 需包含 rabbitmq |
|
||||||
|
| upstream-chan / proxy | `After` 需包含 consul |
|
||||||
|
| app-server | 需 `resource/log/server` 与 `resource/upload` 可写 |
|
||||||
|
| bot | `ExecStart` 需带参数:`/opt/iotlcm/bot/iotlcm-bot watch --config /opt/iotlcm/bot/config/config.yaml` |
|
||||||
|
|
||||||
|
### 启动顺序
|
||||||
|
|
||||||
|
```text
|
||||||
|
MySQL / Redis / RabbitMQ / Consul
|
||||||
|
↓
|
||||||
|
admin-svr、openapi、worker-svr、upstream-chan、upstream-proxy、app-server、sms
|
||||||
|
↓
|
||||||
|
admin-ui、app-web、docs(静态文件,由 nginx 托管)
|
||||||
|
```
|
||||||
|
|
||||||
|
用 systemd 依赖表达:
|
||||||
|
|
||||||
|
```ini
|
||||||
|
[Unit]
|
||||||
|
After=iotlcm-admin-svr.service
|
||||||
|
Requires=iotlcm-admin-svr.service
|
||||||
|
```
|
||||||
|
|
||||||
|
## 静态前端
|
||||||
|
|
||||||
|
`admin-ui`、`app-web`、`docs` 是静态文件,二进制部署时不需要跑容器,把构建产物交给 nginx:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# admin-ui:需 Node 构建
|
||||||
|
cd iotlcm-admin-ui/vue
|
||||||
|
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`。
|
||||||
|
|
||||||
|
## 验证
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 进程状态
|
||||||
|
systemctl status iotlcm-admin-svr
|
||||||
|
journalctl -u iotlcm-admin-svr -n 50 --no-pager
|
||||||
|
|
||||||
|
# 端口监听
|
||||||
|
ss -lntp | grep -E '8008|8000|8510|8110'
|
||||||
|
|
||||||
|
# 接口
|
||||||
|
curl -s -o /dev/null -w '%{http_code}\n' http://127.0.0.1:8008/api.json
|
||||||
|
```
|
||||||
|
|
||||||
|
## 与容器部署的差异
|
||||||
|
|
||||||
|
| 项 | 容器部署 | 二进制部署 |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| 配置路径 | `/app/config`(挂载) | `<服务目录>/config` |
|
||||||
|
| 日志路径 | `/app/logs` | 需在配置里改成实际路径 |
|
||||||
|
| 服务互访 | 服务名(Docker DNS) | `127.0.0.1` 或内网 IP |
|
||||||
|
| 进程管理 | Docker restart policy | systemd |
|
||||||
|
| 升级 | 换镜像 + `up -d` | 停服务 → 换二进制 → 起服务 |
|
||||||
|
| 时区 | 镜像已内置 | 依赖宿主机 tzdata |
|
||||||
|
|
||||||
|
## 升级流程
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 1. 备份配置与程序
|
||||||
|
sudo tar czf /backup/iotlcm-admin-svr-$(date +%F).tar.gz -C /opt/iotlcm admin-svr
|
||||||
|
|
||||||
|
# 2. 停服务
|
||||||
|
sudo systemctl stop iotlcm-admin-svr
|
||||||
|
|
||||||
|
# 3. 替换二进制
|
||||||
|
sudo cp iotlcmadmin_svc /opt/iotlcm/admin-svr/
|
||||||
|
sudo chown iotlcm:iotlcm /opt/iotlcm/admin-svr/iotlcmadmin_svc
|
||||||
|
|
||||||
|
# 4. 起服务并验证
|
||||||
|
sudo systemctl start iotlcm-admin-svr
|
||||||
|
sudo systemctl status iotlcm-admin-svr
|
||||||
|
```
|
||||||
|
|
||||||
|
## 回滚
|
||||||
|
|
||||||
|
保留上一版二进制,回滚只需换回:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo systemctl stop iotlcm-admin-svr
|
||||||
|
sudo cp /opt/iotlcm/admin-svr/iotlcmadmin_svc.bak /opt/iotlcm/admin-svr/iotlcmadmin_svc
|
||||||
|
sudo systemctl start iotlcm-admin-svr
|
||||||
|
```
|
||||||
@@ -0,0 +1,241 @@
|
|||||||
|
---
|
||||||
|
title: 自建镜像
|
||||||
|
description: 从源码构建各服务的 Docker 镜像
|
||||||
|
outline: deep
|
||||||
|
---
|
||||||
|
|
||||||
|
# 自建镜像
|
||||||
|
|
||||||
|
平台镜像由官方仓库分发。如有定制需求(改代码、加依赖、适配私有基础镜像),可从源码自行构建。
|
||||||
|
|
||||||
|
## 构建环境
|
||||||
|
|
||||||
|
| 项 | 要求 |
|
||||||
|
| --- | --- |
|
||||||
|
| Docker | 20.10 以上 |
|
||||||
|
| 网络 | 需访问基础镜像仓库与 Go/npm 依赖源 |
|
||||||
|
| 磁盘 | 单服务构建约 1~2 GB(含构建缓存) |
|
||||||
|
|
||||||
|
## 各服务构建文件
|
||||||
|
|
||||||
|
| 服务 | 仓库 | Dockerfile | 构建上下文 |
|
||||||
|
| --- | --- | --- | --- |
|
||||||
|
| admin-svr | `iotlcm-admin-svr` | `server/build/Dockerfile` | `server/` |
|
||||||
|
| openapi | `iotlcm-openapi` | `build/Dockerfile` | 仓库根目录 |
|
||||||
|
| worker-svr | `iotlcm-worker-svr` | `build/Dockerfile` | 仓库根目录 |
|
||||||
|
| upstream-chan | `iotlcm-upstream-chan` | `build/Dockerfile` | 仓库根目录 |
|
||||||
|
| upstream-proxy | `iotlcm-upstream-proxy` | `build/Dockerfile` | 仓库根目录 |
|
||||||
|
| app-server | `iotlcm-app` | `server/Dockerfile` | `server/` |
|
||||||
|
| app-web | `iotlcm-app` | `app/Dockerfile` | `app/` |
|
||||||
|
| admin-ui | `iotlcm-admin-ui` | `vue/build/Dockerfile` | `vue/` |
|
||||||
|
| sms | `iotlcm-sms` | `build/Dockerfile` | 仓库根目录 |
|
||||||
|
| bot | `iotlcm-bot` | `Dockerfile` | 仓库根目录 |
|
||||||
|
| docs | `iotlcm-docs` | `Dockerfile` | 仓库根目录 |
|
||||||
|
| onelink-mock | `iotlcm-onelink-mock` | `Dockerfile` | 仓库根目录 |
|
||||||
|
|
||||||
|
## ⚠️ 先处理私有基础镜像
|
||||||
|
|
||||||
|
**当前部分仓库的 Dockerfile 仍指向私有镜像仓库**,外部环境无法拉取,直接构建会失败:
|
||||||
|
|
||||||
|
| 仓库 | 文件 | 问题 |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| `iotlcm-openapi` | `manifest/docker/Dockerfile` | `FROM` 指向私有仓库 |
|
||||||
|
| `iotlcm-app` | `app/Dockerfile` | 2 处 `FROM` 指向私有仓库 |
|
||||||
|
| `iotlcm-app` | `server/Dockerfile` | 2 处 `FROM` 指向私有仓库 |
|
||||||
|
| `iotlcm-admin-ui` | `vue/build/Dockerfile` | 2 处 `FROM` 指向私有仓库 |
|
||||||
|
| `iotlcm-admin-ui` | `vue/build/DockerfileNoBuild` | `FROM` 指向私有仓库 |
|
||||||
|
|
||||||
|
构建前把这些 `FROM` 改为公共镜像:
|
||||||
|
|
||||||
|
```dockerfile
|
||||||
|
# 修改前(私有仓库,外部不可达)
|
||||||
|
FROM crpi-xxxxxxxx.cn-beijing.personal.cr.aliyuncs.com/xxx/golangalpine:1.25.7-alpine3.23 AS builder
|
||||||
|
|
||||||
|
# 修改后(公共镜像)
|
||||||
|
FROM golang:1.25-alpine AS builder
|
||||||
|
```
|
||||||
|
|
||||||
|
```dockerfile
|
||||||
|
FROM crpi-xxxxxxxx.cn-beijing.personal.cr.aliyuncs.com/xxx/nginx:1.30.0-alpine
|
||||||
|
|
||||||
|
# 改为
|
||||||
|
FROM nginx:1.30-alpine
|
||||||
|
```
|
||||||
|
|
||||||
|
::: tip 其余仓库的 Dockerfile 已可用
|
||||||
|
`admin-svr`、`worker-svr`、`upstream-chan`、`upstream-proxy`、`sms`、`bot`、`docs`、`onelink-mock` 的 Dockerfile 基础镜像均为公共镜像,可直接构建。
|
||||||
|
:::
|
||||||
|
|
||||||
|
## 构建命令
|
||||||
|
|
||||||
|
### 后端服务
|
||||||
|
|
||||||
|
```bash
|
||||||
|
COMMIT=$(git rev-parse --short HEAD)
|
||||||
|
VERSION=$(git describe --tags --always)
|
||||||
|
BUILD_TIME=$(date -u '+%Y-%m-%dT%H:%M:%SZ')
|
||||||
|
|
||||||
|
docker build \
|
||||||
|
--build-arg BuildVersion=$VERSION \
|
||||||
|
--build-arg CommitID=$COMMIT \
|
||||||
|
--build-arg BuildTime=$BUILD_TIME \
|
||||||
|
-t your-registry/iotlcm/iotlcm-openapi:$VERSION \
|
||||||
|
.
|
||||||
|
```
|
||||||
|
|
||||||
|
`admin-svr` 与 `app-server` 需指定上下文目录:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd iotlcm-admin-svr
|
||||||
|
docker build \
|
||||||
|
--build-arg BuildVersion=$VERSION \
|
||||||
|
--build-arg CommitID=$COMMIT \
|
||||||
|
--build-arg BuildTime=$BUILD_TIME \
|
||||||
|
-t your-registry/iotlcm/iotlcm-admin-svr:$VERSION \
|
||||||
|
-f server/build/Dockerfile server/
|
||||||
|
```
|
||||||
|
|
||||||
|
### 前端服务
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd iotlcm-admin-ui/vue
|
||||||
|
docker build -t your-registry/iotlcm/iotlcm-admin-ui:$VERSION -f build/Dockerfile .
|
||||||
|
```
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd iotlcm-app/app
|
||||||
|
docker build -t your-registry/iotlcm/iotlcm-app-web:$VERSION .
|
||||||
|
```
|
||||||
|
|
||||||
|
### 构建参数说明
|
||||||
|
|
||||||
|
| 参数 | 用途 |
|
||||||
|
| --- | --- |
|
||||||
|
| `BuildVersion` | 写入二进制,可通过版本接口查询 |
|
||||||
|
| `CommitID` | 提交号,便于追溯 |
|
||||||
|
| `BuildTime` | 构建时间 |
|
||||||
|
|
||||||
|
`openapi`、`worker-svr` 等仓库支持用 `GOPROXY` 构建参数替换代理:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker build --build-arg GOPROXY=https://goproxy.cn,direct -t ... .
|
||||||
|
```
|
||||||
|
|
||||||
|
## 镜像命名规则
|
||||||
|
|
||||||
|
部署编排按以下名称拉取镜像,自建时需保持一致:
|
||||||
|
|
||||||
|
| 服务 | 镜像名 |
|
||||||
|
| --- | --- |
|
||||||
|
| admin-svr | `<REGISTRY>/iotlcm/iotlcm-admin-svr:<TAG>` |
|
||||||
|
| admin-ui | `<REGISTRY>/iotlcm/iotlcm-admin-ui:<TAG>` |
|
||||||
|
| openapi | `<REGISTRY>/iotlcm/iotlcm-openapi:<TAG>` |
|
||||||
|
| app-server | `<REGISTRY>/iotlcm/iotlcm-app-server:<TAG>` |
|
||||||
|
| app-web | `<REGISTRY>/iotlcm/iotlcm-app-web:<TAG>` |
|
||||||
|
| upstream-chan | `<REGISTRY>/iotlcm/iotlcm-upstream-chan:<TAG>` |
|
||||||
|
| upstream-proxy | `<REGISTRY>/iotlcm/iotlcm-upstream-proxy:<TAG>` |
|
||||||
|
| worker-svr | `<REGISTRY>/iotlcm/iotlcm-worker-svr:<TAG>` |
|
||||||
|
| sms | `<REGISTRY>/iotlcm/iotlcm-sms:<TAG>` |
|
||||||
|
| bot | `<REGISTRY>/iotlcm/iotlcm-bot:<TAG>` |
|
||||||
|
| docs | `<REGISTRY>/iotlcm/iotlcm-docs:<TAG>` |
|
||||||
|
| onelink-mock | `<REGISTRY>/iotlcm/iotlcm-onelink-mock:<TAG>` |
|
||||||
|
|
||||||
|
基础组件(`library/mysql`、`library/redis` 等)直接使用上游官方镜像,无需自建。
|
||||||
|
|
||||||
|
## 推送到自己的仓库
|
||||||
|
|
||||||
|
```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` 改为:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
REGISTRY=harbor.internal.example.com
|
||||||
|
TAG=1.0.3
|
||||||
|
```
|
||||||
|
|
||||||
|
## 批量构建脚本
|
||||||
|
|
||||||
|
```bash
|
||||||
|
#!/bin/bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
REGISTRY=${REGISTRY:?请设置 REGISTRY}
|
||||||
|
TAG=${TAG:-$(date +%Y%m%d)}
|
||||||
|
WORKDIR=${WORKDIR:-./repos}
|
||||||
|
|
||||||
|
# 服务:仓库:上下文:产物镜像名
|
||||||
|
SERVICES=(
|
||||||
|
"admin-svr:iotlcm-admin-svr:server/:iotlcm-admin-svr"
|
||||||
|
"openapi:iotlcm-openapi:.:iotlcm-openapi"
|
||||||
|
"worker-svr:iotlcm-worker-svr:.:iotlcm-worker-svr"
|
||||||
|
"upstream-chan:iotlcm-upstream-chan:.:iotlcm-upstream-chan"
|
||||||
|
"upstream-proxy:iotlcm-upstream-proxy:.:iotlcm-upstream-proxy"
|
||||||
|
"app-server:iotlcm-app:server/:iotlcm-app-server"
|
||||||
|
"sms:iotlcm-sms:.:iotlcm-sms"
|
||||||
|
"bot:iotlcm-bot:.:iotlcm-bot"
|
||||||
|
)
|
||||||
|
|
||||||
|
mkdir -p "$WORKDIR"
|
||||||
|
|
||||||
|
for item in "${SERVICES[@]}"; do
|
||||||
|
IFS=':' read -r name repo ctx image <<< "$item"
|
||||||
|
echo "=== 构建 $name ==="
|
||||||
|
|
||||||
|
if [ ! -d "$WORKDIR/$repo" ]; then
|
||||||
|
git clone "https://git.5iot.com/iotlcm-public/$repo.git" "$WORKDIR/$repo"
|
||||||
|
fi
|
||||||
|
|
||||||
|
VERSION=$(git -C "$WORKDIR/$repo" describe --tags --always 2>/dev/null || echo unknown)
|
||||||
|
COMMIT=$(git -C "$WORKDIR/$repo" rev-parse --short HEAD 2>/dev/null || echo unknown)
|
||||||
|
|
||||||
|
find "$WORKDIR/$repo" -name Dockerfile -exec \
|
||||||
|
sed -i 's#FROM crpi-[^ ]*/\([a-z]*\):\([0-9.]*-alpine[0-9.]*\)#FROM \1:\2#' {} \;
|
||||||
|
|
||||||
|
docker build \
|
||||||
|
--build-arg BuildVersion="$VERSION" \
|
||||||
|
--build-arg CommitID="$COMMIT" \
|
||||||
|
--build-arg BuildTime="$(date -u '+%Y-%m-%dT%H:%M:%SZ')" \
|
||||||
|
-t "$REGISTRY/iotlcm/$image:$TAG" \
|
||||||
|
-f "$WORKDIR/$repo/${ctx}Dockerfile" \
|
||||||
|
"$WORKDIR/$repo/$ctx"
|
||||||
|
done
|
||||||
|
|
||||||
|
echo "全部完成,镜像标签:$REGISTRY/iotlcm/*:$TAG"
|
||||||
|
```
|
||||||
|
|
||||||
|
::: warning 脚本里的 sed 只能应急
|
||||||
|
上面的 `sed` 是粗略替换,把私有仓库地址映射为公共镜像名。仅适用于地址格式规整的情况,用前先 `git diff` 确认改对了。正式做法应把 Dockerfile 的修正提交回仓库。
|
||||||
|
:::
|
||||||
|
|
||||||
|
## 验证构建结果
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 镜像大小
|
||||||
|
docker images | grep iotlcm
|
||||||
|
|
||||||
|
# 二进制能否启动
|
||||||
|
docker run --rm your-registry/iotlcm/iotlcm-openapi:$TAG --help 2>&1 | head
|
||||||
|
|
||||||
|
# 检查架构
|
||||||
|
docker inspect your-registry/iotlcm/iotlcm-openapi:$TAG \
|
||||||
|
--format '{{.Architecture}}/{{.Os}}'
|
||||||
|
```
|
||||||
|
|
||||||
|
构建后按[启动与验证](install)的清单做一次完整部署验证,不要只看镜像是否构建成功。
|
||||||
|
|
||||||
|
## 常见问题
|
||||||
|
|
||||||
|
| 现象 | 原因 | 处理 |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| `pull access denied` / `unauthorized` | Dockerfile 里是私有仓库地址 | 按上文替换 `FROM` |
|
||||||
|
| `go mod download` 超时 | 网络无法访问 Go 模块代理 | 加 `--build-arg GOPROXY=https://goproxy.cn,direct` |
|
||||||
|
| `npm ci` 失败 | 前端仓库 lock 文件与 package.json 不一致 | 改用 `npm install`,并注意提交 lock 变更 |
|
||||||
|
| 镜像体积过大 | 未使用多阶段构建,或缓存未清理 | 确认用的是仓库自带的 Dockerfile(均为多阶段) |
|
||||||
|
| 容器启动后立即退出 | 镜像内缺少配置文件 | 容器认为 `config/config.yaml` 必须存在,需挂载或用占位配置 |
|
||||||
|
| `exec format error` | 构建架构与运行架构不一致 | 加 `--platform linux/amd64` |
|
||||||
@@ -0,0 +1,171 @@
|
|||||||
|
---
|
||||||
|
title: 离线部署
|
||||||
|
description: 服务器无法访问镜像仓库时的部署方式
|
||||||
|
outline: deep
|
||||||
|
---
|
||||||
|
|
||||||
|
# 离线部署
|
||||||
|
|
||||||
|
服务器无法访问外部镜像仓库时使用。核心思路:**在有网机器上导出镜像 → 传到目标机 → 导入**。
|
||||||
|
|
||||||
|
## 适用场景
|
||||||
|
|
||||||
|
- 生产服务器在内网,不能访问外网
|
||||||
|
- 镜像仓库在内网不可达,或需要走审批才能拉取
|
||||||
|
- 需要把某一批镜像固化下来,保证多台机器部署一致
|
||||||
|
|
||||||
|
## 一、确定镜像清单
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker compose config --images | sort -u
|
||||||
|
```
|
||||||
|
|
||||||
|
输出示例(含可选 profile 时用 `--profile` 指定):
|
||||||
|
|
||||||
|
```text
|
||||||
|
registry.example.com/iotlcm/iotlcm-admin-svr:1.0.3
|
||||||
|
registry.example.com/iotlcm/iotlcm-admin-ui:1.0.3
|
||||||
|
registry.example.com/iotlcm/iotlcm-app-server:1.0.3
|
||||||
|
...
|
||||||
|
registry.example.com/library/mysql:8.0
|
||||||
|
registry.example.com/library/redis:7.2
|
||||||
|
```
|
||||||
|
|
||||||
|
把清单保存下来,作为这次部署的镜像基线:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker compose config --images | sort -u > images.txt
|
||||||
|
```
|
||||||
|
|
||||||
|
## 二、在有网机器导出
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 拉取全部镜像
|
||||||
|
docker compose pull
|
||||||
|
|
||||||
|
# 导出为单个压缩包
|
||||||
|
docker save $(cat images.txt) | gzip > iotlcm-images-$(date +%Y%m%d).tar.gz
|
||||||
|
```
|
||||||
|
|
||||||
|
单包体积参考:全部 14 个服务约 **1.5~2 GB**(压缩后)。
|
||||||
|
|
||||||
|
若目标机磁盘紧张,可按服务分包:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
for img in $(cat images.txt); do
|
||||||
|
name=$(echo "$img" | tr '/:' '__')
|
||||||
|
docker save "$img" | gzip > "img-${name}.tar.gz"
|
||||||
|
done
|
||||||
|
```
|
||||||
|
|
||||||
|
## 三、传输
|
||||||
|
|
||||||
|
```bash
|
||||||
|
scp iotlcm-images-*.tar.gz user@target-host:/opt/iotlcm/
|
||||||
|
```
|
||||||
|
|
||||||
|
无网络直连时用移动介质拷入,注意校验完整性:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 源端生成校验值
|
||||||
|
sha256sum iotlcm-images-*.tar.gz > images.sha256
|
||||||
|
|
||||||
|
# 目标端校验
|
||||||
|
sha256sum -c images.sha256
|
||||||
|
```
|
||||||
|
|
||||||
|
## 四、在目标机导入
|
||||||
|
|
||||||
|
```bash
|
||||||
|
gunzip -c iotlcm-images-*.tar.gz | docker load
|
||||||
|
```
|
||||||
|
|
||||||
|
分包的逐个导入:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
for f in img-*.tar.gz; do gunzip -c "$f" | docker load; done
|
||||||
|
```
|
||||||
|
|
||||||
|
验证:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker images | grep iotlcm
|
||||||
|
```
|
||||||
|
|
||||||
|
## 五、部署
|
||||||
|
|
||||||
|
导入后镜像已在本机,compose 不会再尝试拉取:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cp .env.example .env
|
||||||
|
vi .env # REGISTRY 与 TAG 需与导入的镜像标签完全一致
|
||||||
|
cp -r config.example config
|
||||||
|
vi config/*/config.yaml
|
||||||
|
|
||||||
|
docker compose up -d
|
||||||
|
```
|
||||||
|
|
||||||
|
::: warning REGISTRY 与 TAG 必须与导入的镜像名一致
|
||||||
|
`docker load` 只恢复镜像名,不会改标签。若 `.env` 里写 `TAG=latest` 而导入的是 `1.0.3`,compose 会认为镜像不存在并尝试拉取,离线环境直接失败。
|
||||||
|
|
||||||
|
用这条命令核对:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker compose config --images | sort -u > expected.txt
|
||||||
|
docker images --format '{{.Repository}}:{{.Tag}}' | sort -u > actual.txt
|
||||||
|
comm -23 expected.txt actual.txt # 输出为空才说明镜像齐全
|
||||||
|
```
|
||||||
|
:::
|
||||||
|
|
||||||
|
## 六、长期方案:内网镜像仓库
|
||||||
|
|
||||||
|
如果需要经常部署或多机部署,建议搭内网镜像仓库,而不是每次传 tar 包。
|
||||||
|
|
||||||
|
### 同步镜像
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 在能访问外网的机器
|
||||||
|
for img in $(cat images.txt); do
|
||||||
|
docker pull "$img"
|
||||||
|
newimg="${img/registry.example.com/harbor.internal.example.com}"
|
||||||
|
docker tag "$img" "$newimg"
|
||||||
|
docker push "$newimg"
|
||||||
|
done
|
||||||
|
```
|
||||||
|
|
||||||
|
然后目标机的 `.env` 改为:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
REGISTRY=harbor.internal.example.com
|
||||||
|
```
|
||||||
|
|
||||||
|
### 差异更新
|
||||||
|
|
||||||
|
版本升级时只需推送变化的镜像:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker compose pull
|
||||||
|
# 对比 images.txt 找出新增/变更的标签,只同步这些
|
||||||
|
```
|
||||||
|
|
||||||
|
## 七、常见问题
|
||||||
|
|
||||||
|
| 现象 | 原因 | 处理 |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| `docker compose up` 卡在 `Pulling` | 镜像标签不匹配,compose 尝试联网拉取 | 按上文核对 `expected.txt` 与 `actual.txt` |
|
||||||
|
| `no space left on device` | 镜像包 + 解压后镜像双份占盘 | 导入后删除 tar 包,或换挂载点 |
|
||||||
|
| `load` 后 `docker images` 为空 | 压缩包损坏 | 用 `sha256sum -c` 校验 |
|
||||||
|
| 容器启动报 `exec format error` | 架构不匹配(x86 镜像跑在 ARM) | 在目标架构上重新导出 |
|
||||||
|
| 导出包过大 | 包含多个无用层 | 用 `docker save` 只导出必要标签 |
|
||||||
|
|
||||||
|
## 八、离线环境的其他准备
|
||||||
|
|
||||||
|
镜像只是第一步,以下也需提前准备:
|
||||||
|
|
||||||
|
| 资源 | 说明 |
|
||||||
|
| --- | --- |
|
||||||
|
| 部署仓代码 | `git clone` 或直接打包 `iotlcm-deploy/` 目录带过去 |
|
||||||
|
| 配置模板 | 已包含在部署仓 `config.example/` |
|
||||||
|
| 数据库脚本 | 已包含在部署仓 `schema/` |
|
||||||
|
| Docker 与 Compose | 目标机需预先安装,离线安装包需单独准备 |
|
||||||
|
| 时区数据 | 若使用 `Asia/Shanghai`,确认容器内 tzdata 完整(官方镜像已内置) |
|
||||||
@@ -0,0 +1,182 @@
|
|||||||
|
---
|
||||||
|
title: 分离部署
|
||||||
|
description: 中间件独立部署,业务服务单独一台或多台
|
||||||
|
outline: deep
|
||||||
|
---
|
||||||
|
|
||||||
|
# 分离部署
|
||||||
|
|
||||||
|
把 MySQL、Redis、RabbitMQ、Consul 放到独立主机或使用云托管,业务服务单独部署。
|
||||||
|
|
||||||
|
## 适用场景
|
||||||
|
|
||||||
|
- 数据库已有云托管实例(RDS、云 Redis、云 MQ)
|
||||||
|
- 中间件已有独立集群,不希望在业务机上再跑一套
|
||||||
|
- 业务机配置较低,不适合同时承载数据库
|
||||||
|
|
||||||
|
## 部署结构
|
||||||
|
|
||||||
|
```text
|
||||||
|
┌─────────────────────┐ ┌──────────────────────┐
|
||||||
|
│ 中间件主机 / 云服务 │ │ 业务主机 │
|
||||||
|
│ │ │ │
|
||||||
|
│ MySQL :3306 │◄───────┤ admin-svr :8008 │
|
||||||
|
│ Redis :6379 │ │ admin-ui :80 │
|
||||||
|
│ RabbitMQ :5672 │ │ openapi :8000 │
|
||||||
|
│ Consul :8500 │ │ app-server :8010 │
|
||||||
|
│ │ │ worker-svr │
|
||||||
|
└─────────────────────┘ │ upstream-chan/-proxy│
|
||||||
|
└──────────────────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
## 一、准备中间件
|
||||||
|
|
||||||
|
在中间件侧完成(云托管通常已就绪):
|
||||||
|
|
||||||
|
| 组件 | 需准备 |
|
||||||
|
| --- | --- |
|
||||||
|
| MySQL | 建库 `db_iotlcm`、执行 `schema/` 脚本、建应用账号 `u_iotlcm` |
|
||||||
|
| Redis | 开启认证,记录地址与口令 |
|
||||||
|
| RabbitMQ | 建用户与 vhost,记录地址与口令 |
|
||||||
|
| Consul | 单机模式即可,记录地址 |
|
||||||
|
|
||||||
|
### 初始化数据库
|
||||||
|
|
||||||
|
在能连到目标 MySQL 的机器上执行:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 按文件名顺序执行全部脚本
|
||||||
|
for f in schema/0*.sql; do
|
||||||
|
echo "执行 $f"
|
||||||
|
mysql -h <MySQL地址> -uroot -p<口令> < "$f"
|
||||||
|
done
|
||||||
|
```
|
||||||
|
|
||||||
|
::: warning `.sh` 脚本需单独执行
|
||||||
|
`schema/04-users.sh` 与 `schema/05-reset-passwords.sh` 依赖环境变量,不能直接重定向执行:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
MYSQL_ROOT_PASSWORD='<口令>' MYSQL_APP_PASSWORD='<应用口令>' \
|
||||||
|
MYSQL_HOST=<地址> bash schema/04-users.sh
|
||||||
|
```
|
||||||
|
:::
|
||||||
|
|
||||||
|
## 二、准备业务机 Compose
|
||||||
|
|
||||||
|
复制 `docker-compose.yml`,删除四个中间件服务(`mysql`、`redis`、`rabbitmq`、`consul`),并移除各处 `depends_on` 对它们的引用。
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
# docker-compose.app.yml
|
||||||
|
services:
|
||||||
|
admin-svr:
|
||||||
|
image: '${REGISTRY}/iotlcm/iotlcm-admin-svr:${TAG}'
|
||||||
|
# ... 保留 ports / volumes / environment
|
||||||
|
# 删除 depends_on 中对 mysql/redis/rabbitmq 的依赖
|
||||||
|
```
|
||||||
|
|
||||||
|
::: tip 网络要求
|
||||||
|
业务机必须能访问中间件主机的对应端口。若有防火墙,放行:
|
||||||
|
|
||||||
|
- 业务机 → 中间件:3306、6379、5672、8500
|
||||||
|
- 外部 → 业务机:仅反向代理端口(80 / 443)
|
||||||
|
:::
|
||||||
|
|
||||||
|
## 三、修改配置指向外部地址
|
||||||
|
|
||||||
|
这是本节最关键的一步。所有配置里以**服务名**书写的地址都要改成实际地址。
|
||||||
|
|
||||||
|
### admin-svr
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
database:
|
||||||
|
default:
|
||||||
|
link: "mysql:u_iotlcm:<口令>@tcp(<MySQL地址>:3306)/db_iotlcm?charset=utf8mb4&parseTime=True&loc=Asia%2FShanghai"
|
||||||
|
|
||||||
|
redis:
|
||||||
|
default:
|
||||||
|
address: "<Redis地址>:6379"
|
||||||
|
pass: "<Redis口令>"
|
||||||
|
|
||||||
|
rabbitmq:
|
||||||
|
dsn: "amqp://<用户>:<口令>@<RabbitMQ地址>:5672/"
|
||||||
|
```
|
||||||
|
|
||||||
|
### openapi
|
||||||
|
|
||||||
|
同上三处:`database.default.link`、`redis.default.address`、`rabbitmq.dsn`。
|
||||||
|
|
||||||
|
### worker-svr
|
||||||
|
|
||||||
|
同上三处。注意 `tsdb.tdengine.dsn` 若使用 TDengine 也要改为实际地址。
|
||||||
|
|
||||||
|
### app-server
|
||||||
|
|
||||||
|
改 `database.default.link` 与 `redis.default`。
|
||||||
|
|
||||||
|
### upstream-chan / upstream-proxy
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
registry:
|
||||||
|
type: "consul"
|
||||||
|
address: "<Consul地址>:8500"
|
||||||
|
```
|
||||||
|
|
||||||
|
同时改 `database.default.link` 与 `redis.default`。
|
||||||
|
|
||||||
|
### 服务互访地址
|
||||||
|
|
||||||
|
若业务服务分散在多台机器,`admin-svr`、`worker-svr`、`app-server` 配置里的上游地址也要改:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
upstream:
|
||||||
|
proxy:
|
||||||
|
address: "<upstream-proxy所在主机>:8510"
|
||||||
|
gateway:
|
||||||
|
address: "<upstream-chan所在主机>:8110"
|
||||||
|
```
|
||||||
|
|
||||||
|
`upstream-proxy` 的 `gateway.address` 同理。
|
||||||
|
|
||||||
|
::: danger 最容易出的错
|
||||||
|
只改数据库地址,忘了改 `upstream-proxy:8510`、`upstream-chan:8110` 这类服务名。症状是服务能启动、数据库也通,但批次执行、智能诊断全部超时。
|
||||||
|
:::
|
||||||
|
|
||||||
|
## 四、启动
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cp .env.example .env
|
||||||
|
vi .env # REGISTRY、TAG、各类口令
|
||||||
|
cp -r config.example config
|
||||||
|
vi config/*/config.yaml # 按上节改为外部地址
|
||||||
|
|
||||||
|
docker compose -f docker-compose.app.yml up -d
|
||||||
|
```
|
||||||
|
|
||||||
|
此时 `.env` 中的 `MYSQL_*`、`REDIS_PASSWORD`、`RABBITMQ_PASSWORD` 不再用于启动中间件容器,但仍作为配置中的变量来源,**取值要与中间件实际口令一致**。
|
||||||
|
|
||||||
|
## 五、验证
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker compose -f docker-compose.app.yml ps
|
||||||
|
|
||||||
|
# 数据库连通性
|
||||||
|
docker compose -f docker-compose.app.yml exec admin-svr sh -c 'nc -zv <MySQL地址> 3306'
|
||||||
|
docker compose -f docker-compose.app.yml exec admin-svr sh -c 'nc -zv <Redis地址> 6379'
|
||||||
|
|
||||||
|
# Redis 认证
|
||||||
|
docker compose -f docker-compose.app.yml exec admin-svr sh -c 'redis-cli -h <地址> -a "<口令>" ping'
|
||||||
|
|
||||||
|
# 服务日志
|
||||||
|
docker compose -f docker-compose.app.yml logs --tail=50 admin-svr
|
||||||
|
```
|
||||||
|
|
||||||
|
浏览器登录管理端,确认能查卡、能发起业务办理。
|
||||||
|
|
||||||
|
## 六、注意事项
|
||||||
|
|
||||||
|
| 项 | 说明 |
|
||||||
|
| --- | --- |
|
||||||
|
| 网络延迟 | 业务机到中间件的延迟建议 < 5ms。跨地域部署会造成批次执行明显变慢 |
|
||||||
|
| 连接池 | 外部数据库延迟较高时,适当调大 `database.default.maxIdle` 与 `maxOpen` |
|
||||||
|
| 备份 | 分离后数据库备份由中间件侧负责,本仓的 `backup.sh` 需调整连接参数 |
|
||||||
|
| 时钟 | 各机器需开启 NTP 同步,否则全量同步的时间窗口判断会出错 |
|
||||||
Reference in New Issue
Block a user