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:
Dai0814
2026-10-28 14:20:06 +08:00
parent e43640d0fe
commit f169afc1bc
6 changed files with 990 additions and 0 deletions
+171
View File
@@ -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 完整(官方镜像已内置) |