首页 产品 为什么选 OCTO 解决方案 文档 关于
文档中心 / 部署运维 / Docker Compose 离线部署
← 返回文档中心

Docker Compose 离线部署

OCTO 文档中心 · 部署运维

  • octo-deployment/docker/docker-compose.yaml(行号见正文)
  • octo-deployment/docker/docker-compose-setup.sh
  • octo-deployment/docker/README.md
  • octo-deployment/docker/opensearch/Dockerfile(IK 插件本地构建镜像)

OCTO Docker Compose 离线部署指南 v1.0

适用场景:目标服务器处于政企内网 / 隔离网络 / 无外网环境,无法从 Docker Hub、

`mininglamposs` 官方仓库或 `hub2.intra.mlamp.cn` 直接 `docker pull` 镜像。

所有镜像、配置文件、证书需在有外网的跳板机 / 工作站上准备好,通过 U 盘、

摆渡机或离线介质传输到目标机后完成部署。


1. 离线部署场景说明

Registry 用途
docker.io(Docker Hub) MySQL、Redis、Nginx、MinIO、MinIO/mc、BusyBox、PostgreSQL、Apache Kafka、migrate/migrate 等第三方基础镜像
docker.io/mininglamposs/* OCTO 官方业务镜像(server / web / admin / marketplace / smart-summary / speech / search-indexer / fleet / docs-backend)
hub2.intra.mlamp.cn/octo/* 数言内部 Registry 上的镜像(octo-drive、octo-docs-html、octo-doc-indexer、octo-drive-indexer、tika,以及 R8 后部分 preflight 镜像默认指向此仓库)
本地构建(./opensearch/Dockerfile) octo-search-opensearch-ik:2.17.0(OpenSearch 2.17 + IK 中文分词插件,需在有网环境下提前构建)
  • 政务/国企/金融内网:机房与互联网物理隔离,只允许通过指定介质导入文件;
  • 客户私有化部署:客户侧只提供镜像仓库(Harbor 等)或纯离线主机;
  • 安全评测/等保环境:禁止运行时从公网拉取代码或镜像;
  • 边缘/分支节点:带宽低、不稳定,一次打包重复部署多台主机。

2. 前置条件

2.1 目标离线机器要求

组件 最低版本(建议) 备注
操作系统 Linux x86_64(CentOS 7+/RHEL 8+/Ubuntu 20.04+/Debian 11+) 待验证(建议 amd64);ARM64(鲲鹏/飞腾)需在有网机器上构建对应架构镜像后再离线导入
Docker Engine ≥ 20.10(建议 24.x 或更高) 需支持 docker compose v2 插件
Docker Compose(plugin) ≥ v2.20 使用 docker compose(带空格)子命令;不推荐 docker-compose v1
CPU ≥ 8 核(生产 ≥ 16 核) 开启 search / fleet / docs 等模块时需更高配置
内存 ≥ 16 GB(生产 ≥ 32 GB,开启 search 需 ≥ 64 GB) OpenSearch/Kafka 内存占用较大
磁盘 ≥ 100 GB(生产 ≥ 500 GB SSD) MySQL/MinIO/消息/搜索索引体积随数据增长
开放端口 至少 OCTO_HTTP_PORT(默认 28080)、OCTO_HTTPS_PORT(默认 28443) 其它端口默认绑定 127.0.0.1,见《网络端口与防火墙清单》

架构提示:官方发布的 `mininglamposs/*` 镜像是否提供 arm64 版本待验证,

离线场景下强烈建议目标机使用 amd64;如必须在 arm64 部署,需在同架构的

有网机器上拉取或构建镜像,再打包传输。

2.2 有网机器要求

  • 可访问 Docker Hub 与 hub2.intra.mlamp.cn(或已配置可使用的代理);
  • 安装了与目标机同主版本的 Docker / Docker Compose,避免 save/load 后出现不兼容层;
  • 有足够磁盘空间存放 tar 包(全量模块约 15–30 GB);
  • 若需要开启 search 模块,能执行 docker build(构建 IK OpenSearch 镜像)。

2.3 介质/传输方式

  • U 盘 / 移动硬盘:单文件 >4GB,需使用 ext4 / NTFS / exFAT;
  • scp / rsync(经跳板机):如内网存在可中转的堡垒机;
  • 客户镜像仓库(Harbor 等):若客户侧已有私有 Registry,推荐 docker pull + docker tag + docker push 先导入客户仓库,再在目标机 docker pull(本指南主要覆盖无 Registry 场景,但 §9 给出 Registry 替代路径)。

3. 完整镜像清单

3.1 核心(默认启动,无需 profile)

# 服务名 compose 行号 默认镜像 大小(参考)
1 preflight L162 busybox:1.36 ~2 MB
2 mysql L197 mysql:8.0 ~600 MB
3 redis L241 redis:7-alpine ~40 MB
4 minio L279 minio/minio:RELEASE.2025-04-22T22-12-26Z ~150 MB
5 minio-init L353 minio/mc:RELEASE.2025-04-16T18-13-26Z ~30 MB
6 wukongim L514 wukongim/wukongim:v2.2.4-20260313 ~80 MB
7 octo-server L621 mininglamposs/octo-server:latest ~300 MB
8 nginx L871 nginx:1.27-alpine ~45 MB
9 web(octo-web) L909 mininglamposs/octo-web:latest ~50 MB
10 admin(octo-admin) L953 mininglamposs/octo-admin:latest ~30 MB
11 market-preflight L985 mysql:8.0 与 #2 复用
12 marketplace L1038 mininglamposs/octo-marketplace:latest ~100 MB
13 search-producer-guard L1738 busybox:1.36 与 #1 复用
14 botfather-robot L2124 mysql:8.0 与 #2 复用(botfather 使用 mysql 客户端作一次性 init,复用同一镜像)

核心 14 个服务去重后镜像数:约 10 个,未压缩总大小约 1.4 GB。

3.2 Profile 可选模块镜像

各模块通过 `COMPOSE_PROFILES=` 启用,详见《内部模块Profile开启指南》。

3.2.1 智能摘要 `profiles: ["summary"]`
服务名 行号 默认镜像
summary-api L1082 mininglamposs/octo-smart-summary-api:latest
summary-worker L1138 mininglamposs/octo-smart-summary-worker:latest

依赖外部 LLM 网关(`LLM_API_URL` / `LLM_API_KEY`)。离线环境必须部署本地/内网 LLM 网关,否则 summary 功能不可用。

3.2.2 语音 `profiles: ["speech"]`
服务名 行号 默认镜像
octo-speech L1216 mininglamposs/octo-speech:latest
octo-speech-admin L1253 mininglamposs/octo-speech-admin:latest

语音模型/转写服务通常需访问通义千问等云端语音 API(`VOICE_QWEN_URL`/`VOICE_QWEN_KEY`),离线环境需提前评估是否可替换为内网 ASR 服务。

3.2.3 文档服务 `profiles: ["docs"]`
服务名 行号 默认镜像
docs-preflight L1306 busybox:1.36
octo-docs-backend L1357 mininglamposs/octo-docs-backend:0.8.0

⚠️ L1608 `search-ensure` 预检查的默认镜像 tag 为 `hub2.intra.mlamp.cn/octo/busybox:1.36`(search 模块启用时使用)。L1306 / L1738 / L1962 / L2180 / L2217 / L2366 这些 preflight 仍使用 `busybox:1.36`。离线部署时务必在有网机同时 pull `busybox:1.36`(Docker Hub)与 `hub2.intra.mlamp.cn/octo/busybox:1.36`,或在 `.env` 中将 `OCTO_PREFLIGHT_IMAGE` 统一覆盖为一个已存在的镜像。

3.2.4 消息搜索 `profiles: ["search"]`
服务名 行号 默认镜像 备注
search-kafka L1482 apache/kafka:3.8.0 Kafka broker
search-kafka-init L1533 apache/kafka:3.8.0 主题初始化(one-shot)
search-opensearch L1558 octo-search-opensearch-ik:2.17.0 本地构建镜像(见 §4.3)
search-ensure L1608 hub2.intra.mlamp.cn/octo/busybox:1.36 索引/别名初始化
es-indexer L1676 mininglamposs/octo-search-indexer:latest 实时索引消费
3.2.5 独立搜索生产者 `profiles: ["search-producer"]`
服务名 行号 默认镜像
search-producer L1782 mininglamposs/octo-search-indexer:latest

与 octo-server 内置 producer 二选一,不可同开。

3.2.6 搜索工具(一次性回填)`profiles: ["search-tools"]`
服务名 行号 默认镜像
search-cursor-seed L1841 mysql:8.0
search-backfill L1905 mininglamposs/octo-search-indexer:latest
3.2.7 集群/Agent 管理 `profiles: ["fleet"]` / `["fleet-db"]`
服务名 行号 默认镜像 profile
fleet-preflight L1962 busybox:1.36 fleet
fleet-postgres L2033 postgres:16-alpine fleet-db
octo-fleet L2055 mininglamposs/octo-fleet:latest fleet

不启用 `fleet-db` 时需设置 `FLEET_DATABASE_URL` 指向外部 PostgreSQL。

3.2.8 云盘 Drive `profiles: ["drive"]`
服务名 行号 默认镜像
drive-config L2180 busybox:1.36
drive-preflight L2217 mysql:8.0
drive-migrate L2275 migrate/migrate:v4.18.3
drive L2301 hub2.intra.mlamp.cn/octo/octo-drive:v0.5.0
3.2.9 文档前端(docs-html)`profiles: ["docs-html"]`
服务名 行号 默认镜像
docs-html-preflight L2366 busybox:1.36
docs-html-migrate L2392 hub2.intra.mlamp.cn/octo/octo-docs-html:v0.4.0
docs-html L2411 hub2.intra.mlamp.cn/octo/octo-docs-html:v0.4.0
3.2.10 文档索引 `profiles: ["doc-index"]`
服务名 行号 默认镜像
doc-index-kafka-init L2466 apache/kafka:3.8.0
doc-index-ensure L2491 hub2.intra.mlamp.cn/octo/busybox:1.36
doc-indexer L2551 hub2.intra.mlamp.cn/octo/octo-doc-indexer:v1.1.0
3.2.11 Drive 索引 `profiles: ["drive-index"]`
服务名 行号 默认镜像
tika L2609 hub2.intra.mlamp.cn/octo/tika:3.3.0.0
drive-index-kafka-init L2618 apache/kafka:3.8.0
drive-index-ensure L2643 hub2.intra.mlamp.cn/octo/busybox:1.36
drive-indexer L2685 hub2.intra.mlamp.cn/octo/octo-drive-indexer:v0.1.0

3.3 去重后全量镜像清单(默认 + 全部 profile)

下表为启用 `docs,docs-html,doc-index,drive,drive-index,search,summary,speech,fleet,fleet-db`

(即 `docker-compose-setup.sh` 默认 PROFILES 集合)时所需的去重镜像全集。

# 镜像 用途 来源
1 busybox:1.36 preflight / 一次性脚本 Docker Hub
2 hub2.intra.mlamp.cn/octo/busybox:1.36 search/doc-index/drive-index ensure 脚本 数言内部 Registry ⚠️
3 mysql:8.0 业务库 Docker Hub
4 redis:7-alpine 缓存/队列 Docker Hub
5 minio/minio:RELEASE.2025-04-22T22-12-26Z 对象存储 Docker Hub
6 minio/mc:RELEASE.2025-04-16T18-13-26Z MinIO 初始化客户端 Docker Hub
7 wukongim/wukongim:v2.2.4-20260313 IM 长连接 Docker Hub
8 nginx:1.27-alpine 反向代理 Docker Hub
9 apache/kafka:3.8.0 搜索/索引消息队列 Docker Hub
10 postgres:16-alpine Fleet 数据库(fleet-db profile) Docker Hub
11 migrate/migrate:v4.18.3 Drive 数据库迁移 Docker Hub
12 mininglamposs/octo-server:latest OCTO 服务端 Docker Hub / 官方
13 mininglamposs/octo-web:latest Web 前端 Docker Hub / 官方
14 mininglamposs/octo-admin:latest 管理后台 Docker Hub / 官方
15 mininglamposs/octo-marketplace:latest 技能/插件市场 Docker Hub / 官方
16 mininglamposs/octo-smart-summary-api:latest 智能摘要 API Docker Hub / 官方
17 mininglamposs/octo-smart-summary-worker:latest 智能摘要 Worker Docker Hub / 官方
18 mininglamposs/octo-speech:latest 语音服务 Docker Hub / 官方
19 mininglamposs/octo-speech-admin:latest 语音管理后台 Docker Hub / 官方
20 mininglamposs/octo-docs-backend:0.8.0 文档协同后端 Docker Hub / 官方
21 mininglamposs/octo-search-indexer:latest 搜索索引器/生产者/回填器 Docker Hub / 官方
22 mininglamposs/octo-fleet:latest Fleet/Agent 调度 Docker Hub / 官方
23 hub2.intra.mlamp.cn/octo/octo-drive:v0.5.0 云盘 数言内部 Registry ⚠️
24 hub2.intra.mlamp.cn/octo/octo-docs-html:v0.4.0 文档预览/HTML 数言内部 Registry ⚠️
25 hub2.intra.mlamp.cn/octo/octo-doc-indexer:v1.1.0 文档索引器 数言内部 Registry ⚠️
26 hub2.intra.mlamp.cn/octo/tika:3.3.0.0 Tika 文本抽取(drive-index) 数言内部 Registry ⚠️
27 hub2.intra.mlamp.cn/octo/octo-drive-indexer:v0.1.0 Drive 索引器 数言内部 Registry ⚠️
28 octo-search-opensearch-ik:2.17.0 OpenSearch 2.17 + IK 分词 本地构建 ⚠️(§4.3)

⚠️ 标识表示该镜像无法直接从 Docker Hub 获取:

- `hub2.intra.mlamp.cn/octo/*` 需要能访问数言内部 Registry;离线交付时应提前在有网机器上 pull 并 save。

- `octo-search-opensearch-ik:2.17.0` 不在任何公共 Registry,需在有网机器用 compose 仓库中的 `docker/opensearch/Dockerfile` 本地构建(`docker compose build search-opensearch`)。


4. 有网络机器:镜像拉取与打包

在有网跳板机/工作站上执行。建议先 `git clone` 完整 `octo-deployment` 仓库,确保

拿到与目标版本一致的 `docker/docker-compose.yaml`、`docker/opensearch/Dockerfile`、

`nginx/`、`configs/`、`scripts/` 等文件。

git clone 
cd octo-deployment/docker

4.1 生成或准备 .env

./docker-compose-setup.sh  \
  --registry hub2.intra.mlamp.cn/octo \
  --llm-url <内网LLM网关URL> \
  --llm-key 
  • 把 LLM_API_URL / VOICE_QWEN_URL 指向内网可达的 LLM/ASR 网关(否则 summary/speech 不可用);
  • 若完全没有内网 LLM 网关,可以先启用核心模块,不起 summary/speech;
  • 不需要 telemetry(OCTO 当前 compose 中未显式定义 DISABLE_TELEMETRY 变量,待确认;如有遥测上报需求,部署前与研发确认对应变量名。本指南后续步骤中保留"设置禁用遥测"为可选项)。

注意:在撰写本文时对 `docker-compose.yaml` 与 `docker-compose-setup.sh` 检索

`TELEMETRY`/`DISABLE_` 未发现显式的遥测开关变量。`DISABLE_SECURITY_PLUGIN`(OpenSearch)

与 `DISABLE_INSTALL_DEMO_CONFIG` 与遥测无关。DISABLE_TELEMETRY 具体变量名待产品/研发确认,

确认前勿随意添加。

4.2 拉取镜像(纯 pull 路径,适用于已有 Registry 可见的有网机)

4.2.1 核心镜像(必选)
docker pull busybox:1.36
docker pull mysql:8.0
docker pull redis:7-alpine
docker pull minio/minio:RELEASE.2025-04-22T22-12-26Z
docker pull minio/mc:RELEASE.2025-04-16T18-13-26Z
docker pull wukongim/wukongim:v2.2.4-20260313
docker pull mininglamposs/octo-server:latest
docker pull nginx:1.27-alpine
docker pull mininglamposs/octo-web:latest
docker pull mininglamposs/octo-admin:latest
docker pull mininglamposs/octo-marketplace:latest
4.2.2 可选模块镜像(按需)
# summary
docker pull mininglamposs/octo-smart-summary-api:latest
docker pull mininglamposs/octo-smart-summary-worker:latest

# speech
docker pull mininglamposs/octo-speech:latest
docker pull mininglamposs/octo-speech-admin:latest

# docs
docker pull mininglamposs/octo-docs-backend:0.8.0

# search
docker pull apache/kafka:3.8.0
docker pull mininglamposs/octo-search-indexer:latest

# fleet
docker pull postgres:16-alpine
docker pull mininglamposs/octo-fleet:latest

# drive
docker pull migrate/migrate:v4.18.3
docker pull hub2.intra.mlamp.cn/octo/octo-drive:v0.5.0

# docs-html
docker pull hub2.intra.mlamp.cn/octo/octo-docs-html:v0.4.0

# doc-index
docker pull hub2.intra.mlamp.cn/octo/octo-doc-indexer:v1.1.0

# drive-index
docker pull hub2.intra.mlamp.cn/octo/tika:3.3.0.0
docker pull hub2.intra.mlamp.cn/octo/octo-drive-indexer:v0.1.0

# 注意:search-ensure/doc-index-ensure/drive-index-ensure 默认使用此镜像
docker pull hub2.intra.mlamp.cn/octo/busybox:1.36

如果无法访问 `hub2.intra.mlamp.cn`,请联系 OCTO 交付同学获取上述镜像的 tar 包,或

通过 `docker tag` 将自己构建/导入的同名镜像覆盖。

4.3 本地构建 octo-search-opensearch-ik 镜像(search 模块必需)

cd octo-deployment/docker
docker compose build search-opensearch
# 或者直接:
docker build -t octo-search-opensearch-ik:2.17.0 \
  --build-arg OPENSEARCH_VERSION=2.17.0 \
  -f opensearch/Dockerfile opensearch/
docker images | grep octo-search-opensearch-ik
# 应输出:octo-search-opensearch-ik   2.17.0    ...

4.4 使用 docker save 打包镜像

方案 A:全量单包(适合介质空间充足、一次性部署)
# 建立打包目录
mkdir -p octo-offline-bundle/images
cd octo-offline-bundle/images

# 全量保存(把上面 §3.3 列表中的镜像全部打包进一个 tar)
docker save -o octo-images-all.tar \
  busybox:1.36 \
  hub2.intra.mlamp.cn/octo/busybox:1.36 \
  mysql:8.0 \
  redis:7-alpine \
  minio/minio:RELEASE.2025-04-22T22-12-26Z \
  minio/mc:RELEASE.2025-04-16T18-13-26Z \
  wukongim/wukongim:v2.2.4-20260313 \
  mininglamposs/octo-server:latest \
  nginx:1.27-alpine \
  mininglamposs/octo-web:latest \
  mininglamposs/octo-admin:latest \
  mininglamposs/octo-marketplace:latest \
  mininglamposs/octo-smart-summary-api:latest \
  mininglamposs/octo-smart-summary-worker:latest \
  mininglamposs/octo-speech:latest \
  mininglamposs/octo-speech-admin:latest \
  mininglamposs/octo-docs-backend:0.8.0 \
  apache/kafka:3.8.0 \
  mininglamposs/octo-search-indexer:latest \
  postgres:16-alpine \
  mininglamposs/octo-fleet:latest \
  migrate/migrate:v4.18.3 \
  hub2.intra.mlamp.cn/octo/octo-drive:v0.5.0 \
  hub2.intra.mlamp.cn/octo/octo-docs-html:v0.4.0 \
  hub2.intra.mlamp.cn/octo/octo-doc-indexer:v1.1.0 \
  hub2.intra.mlamp.cn/octo/tika:3.3.0.0 \
  hub2.intra.mlamp.cn/octo/octo-drive-indexer:v0.1.0 \
  octo-search-opensearch-ik:2.17.0

若只部署核心模块(不含 summary/speech/search/fleet/drive/docs 等),可只保留 §3.1

对应镜像,tar 包大约 1.5 GB 左右;全模块大约 10–15 GB(未压缩)。

方案 B:按模块分包(推荐,便于差异化部署与增量升级)
mkdir -p octo-offline-bundle/images
cd octo-offline-bundle/images

# 00-core:核心必选
docker save -o 00-core.tar \
  busybox:1.36 \
  hub2.intra.mlamp.cn/octo/busybox:1.36 \
  mysql:8.0 redis:7-alpine \
  minio/minio:RELEASE.2025-04-22T22-12-26Z minio/mc:RELEASE.2025-04-16T18-13-26Z \
  wukongim/wukongim:v2.2.4-20260313 \
  mininglamposs/octo-server:latest nginx:1.27-alpine \
  mininglamposs/octo-web:latest mininglamposs/octo-admin:latest \
  mininglamposs/octo-marketplace:latest

# 01-summary
docker save -o 01-summary.tar \
  mininglamposs/octo-smart-summary-api:latest \
  mininglamposs/octo-smart-summary-worker:latest

# 02-speech
docker save -o 02-speech.tar \
  mininglamposs/octo-speech:latest \
  mininglamposs/octo-speech-admin:latest

# 03-docs
docker save -o 03-docs.tar \
  mininglamposs/octo-docs-backend:0.8.0 \
  hub2.intra.mlamp.cn/octo/octo-docs-html:v0.4.0

# 04-search
docker save -o 04-search.tar \
  apache/kafka:3.8.0 \
  mininglamposs/octo-search-indexer:latest \
  octo-search-opensearch-ik:2.17.0

# 05-fleet
docker save -o 05-fleet.tar \
  postgres:16-alpine \
  mininglamposs/octo-fleet:latest

# 06-drive(含索引)
docker save -o 06-drive.tar \
  migrate/migrate:v4.18.3 \
  hub2.intra.mlamp.cn/octo/octo-drive:v0.5.0 \
  hub2.intra.mlamp.cn/octo/tika:3.3.0.0 \
  hub2.intra.mlamp.cn/octo/octo-drive-indexer:v0.1.0 \
  hub2.intra.mlamp.cn/octo/octo-doc-indexer:v1.1.0

4.5 校验文件

cd octo-offline-bundle/images
sha256sum *.tar > SHA256SUMS
cat SHA256SUMS

# 同时记录文件大小(人眼核对)
ls -lh *.tar
gzip -k *.tar        # 生成 .tar.gz,原 tar 保留;或用 pigz 多线程压缩

4.6 打包配置与脚本文件

cd octo-deployment
# 回到仓库根,打包 docker 目录(排除临时数据卷、已生成的日志等)
tar czf ../octo-offline-bundle/octo-docker-configs.tar.gz \
  --exclude='docker/.env' \
  --exclude='docker/certs/privkey.pem' \
  docker/
  • docker/.env 模板(已填好离线相关配置,见 §6.3);
  • 本指南打印版或 PDF 副本;
  • Docker / Docker Compose 二进制离线安装包(若目标机尚未安装,从 下载)。
octo-offline-bundle/
├── images/
│   ├── 00-core.tar
│   ├── 01-summary.tar
│   ├── ...
│   └── SHA256SUMS
├── octo-docker-configs.tar.gz
└── README-OFFLINE.txt        # 简短部署步骤便签(可选)

5. 传输到离线机器

5.1 U 盘 / 移动硬盘

  1. 将 `octo-offline-bundle/` 整个目录拷贝到介质;
  2. 如使用 FAT32,需注意单文件 4GB 限制——优先使用 ext4/NTFS/exFAT;
  3. 到目标机挂载后先校验 checksum:
   cd /path/to/octo-offline-bundle/images
   sha256sum -c SHA256SUMS

5.2 scp(经跳板/堡垒机)

# 在有网机执行
scp -r octo-offline-bundle/ user@jumphost:/path/to/dropzone/
# 再从 jumphost 到目标机
scp -r /path/to/dropzone/octo-offline-bundle/ user@octo-target:/opt/

6. 离线机器:导入镜像并启动

6.1 导入镜像

cd /opt/octo-offline-bundle/images

# 方案 A:单包
docker load -i octo-images-all.tar

# 方案 B:按模块(核心必装,其它按需)
docker load -i 00-core.tar
docker load -i 01-summary.tar    # 如启用 summary
docker load -i 04-search.tar     # 如启用 search
# ... 其它模块
Loaded image: busybox:1.36
Loaded image: mysql:8.0
...

6.2 确认镜像导入成功

docker images | sort
for img in \
  busybox:1.36 \
  hub2.intra.mlamp.cn/octo/busybox:1.36 \
  mysql:8.0 \
  redis:7-alpine \
  minio/minio:RELEASE.2025-04-22T22-12-26Z \
  minio/mc:RELEASE.2025-04-16T18-13-26Z \
  wukongim/wukongim:v2.2.4-20260313 \
  mininglamposs/octo-server:latest \
  nginx:1.27-alpine \
  mininglamposs/octo-web:latest \
  mininglamposs/octo-admin:latest \
  mininglamposs/octo-marketplace:latest \
  octo-search-opensearch-ik:2.17.0; do
  if docker image inspect "$img" >/dev/null 2>&1; then
    echo "[OK]    $img"
  else
    echo "[MISS]  $img"
  fi
done

6.3 解压配置并准备 .env

cd /opt
tar xzf /path/to/octo-offline-bundle/octo-docker-configs.tar.gz
cd octo-deployment/docker
# 方式1:如果离线机允许 openssl,可直接运行 setup(此时不依赖 Registry 拉取,仅生成本地证书与 env)
# 注意:setup 脚本内默认 --registry 指向 hub2.intra.mlamp.cn,可保留原值(镜像已 load 到本地 daemon,不再 pull)
./docker-compose-setup.sh  \
  --registry hub2.intra.mlamp.cn/octo \
  --llm-url http://<内网LLM网关地址>/v1 \
  --llm-key <内网LLM_KEY>

# 方式2:手工编辑 .env,从有网机复制一份模板,替换以下关键项

6.4 .env 离线关键配置

# --- 基础域名 / 端口 ---
OCTO_DOMAIN=<目标机IP或客户内网域名>
OCTO_HTTP_PORT=28080
OCTO_HTTPS_PORT=28443
TZ=Asia/Shanghai

# --- COMPOSE_PROFILES:根据实际启用的模块设置;核心最小可不写(仅核心服务)---
# 全模块默认(docker-compose-setup.sh 会自动填入):
COMPOSE_PROFILES=docs,docs-html,doc-index,drive,drive-index,search,summary,speech,fleet,fleet-db
# 最小核心:留空或不设置 COMPOSE_PROFILES 即可

# --- 镜像覆盖(若镜像名与 compose 默认一致且已 docker load,可省略;
#     若导入到本地 Harbor 等私有仓库,请修改以下变量指向私有仓库地址)---
# OCTO_SERVER_IMAGE=harbor.customer.local/octo/octo-server:latest
# OCTO_WEB_IMAGE=harbor.customer.local/octo/octo-web:latest
# ...(其它 OCTO_XXX_IMAGE 按需覆盖)

# --- LLM 网关(内网地址,不能使用公网 api.example.com)---
LLM_API_URL=http://<内网LLM网关>/v1
LLM_API_KEY=<内网LLM_KEY>
# 语音
VOICE_QWEN_URL=http://<内网语音网关>/
VOICE_QWEN_KEY=<语音KEY>

# --- 外网/遥测相关(待确认:当前 compose 未定义 DISABLE_TELEMETRY,以下为占位,待研发确认具体变量名后启用)---
# DISABLE_TELEMETRY=true
# OCTO_TELEMETRY_ENABLED=false

# --- OpenSearch 安全插件默认禁用(单机部署,保持默认)---
# OCTO_SEARCH_OPENSEARCH_DISABLE_SECURITY=true

# --- Drive / Search Kafka(默认关闭,待 search 升级脚本开启后再改)---
# DRIVE_KAFKA_DISABLED=true
# DRIVE_SEARCH_DISABLED=true
# OCTO_SEARCH_BACKEND=disabled    # search 模块未启用时必须保持 disabled

重要:`minio-init`、`preflight`、`market-preflight` 等一次性服务会检查

`MYSQL_ROOT_PASSWORD` / `MINIO_ROOT_PASSWORD` / `OCTO_MINIO_APP_PASSWORD` /

`OCTO_NOTIFY_INTERNAL_TOKEN` / `OCTO_WUKONGIM_MANAGER_TOKEN` 等是否仍是 `CHANGE_ME*`

占位符,必须确保这些值已通过 `docker-compose-setup.sh` 生成或手工设置为强随机值。

6.5 启动

cd /opt/octo-deployment/docker
docker compose up -d
docker compose up -d --wait --wait-timeout 240
docker compose up -d
# 不起 summary/speech/search/fleet/drive/docs 等
COMPOSE_PROFILES=summary,speech docker compose up -d

7. 常见坑与排障

7.1 架构不一致(arm64 / amd64)

  • 有网机器拉镜像时显式指定平台:
  •   docker pull --platform linux/amd64 mininglamposs/octo-server:latest
  • 或在有网机器使用 docker buildx 构建跨平台镜像;
  • 建议离线交付前在与目标机同架构机器上准备镜像。

7.2 镜像 digest 不匹配 / 镜像找不到

Error response from daemon: pull access denied for X, repository does not exist or may require 'docker login': denied: requested access to the resource is denied
manifest for mininglamposs/octo-server:latest not found
  1. 镜像没 `docker load` 成功;
  2. `.env` 中 `OCTO_XXX_IMAGE` 与 load 的镜像 tag 不一致;
  3. Compose 仍然尝试去 Registry 拉取(通常是因为 tag 不匹配)。
docker images | grep 
# 对比 tag 与 compose/.env 中的引用
docker compose config | grep image:

7.3 缺基础镜像 / 本地构建镜像忘记打包

  • octo-search-opensearch-ik:2.17.0 是本地构建,不会被自动 pull,必须在有网机
  • hub2.intra.mlamp.cn/octo/busybox:1.36 与 Docker Hub 的 busybox:1.36 **是两个

7.4 .env 中仍引用外网资源

变量 默认值 离线处理建议
LLM_API_URL https://api.example.com/v1 改为内网 LLM 网关;无 LLM 则不起 summary profile
LLM_API_KEY 空 / changeme 设置为内网 LLM 网关 key
VOICE_QWEN_URL / VOICE_QWEN_KEY 空 内网 ASR 地址/key;无则不起 speech
TS_EXTERNAL_BASEURL http://: 改为客户实际访问地址(含 https 端口)
TS_MINIO_DOWNLOADURL 同 baseURL 若使用 https,需把 scheme 改成 https
MINIO_SERVER_URL 同 baseURL 同上
SPEECH_SERVICE_URL http://octo-speech:8780 集群内部地址,一般无需修改
OCTO_SEARCH_OS_ADDRS http://search-opensearch:9200 集群内部地址,一般无需修改

7.5 证书与 https

  • 客户端(OpenClaw / octo-daemon / 浏览器)必须信任 certs/fullchain.pem;
  • 参考 docker/README.md 中"OpenClaw 信任 OCTO 自签名证书"章节;
  • 私钥 certs/privkey.pem 传输时必须加密/走安全渠道。

7.6 容器时区

7.7 Docker Compose 版本过旧


8. 验证离线部署成功

8.1 容器状态

cd /opt/octo-deployment/docker
docker compose ps

8.2 关键端口健康

# nginx 对外端口
curl -fsS http://127.0.0.1:28080/_nginx_up && echo "[OK] nginx up"
curl -kfsS https://127.0.0.1:28443/ -o /dev/null && echo "[OK] nginx https"

# octo-server 健康(通过 nginx 反代)
curl -fsS http://127.0.0.1:28080/api/v1/health
# 预期返回 JSON,包含 "status":"ok" 或类似健康字段

# 直接 ping octo-server
curl -fsS http://127.0.0.1:28081/v1/ping && echo "[OK] octo-server ping"

# marketplace
curl -fsS http://127.0.0.1:28080/marketplace/healthz && echo "[OK] marketplace"

8.3 Web 与 Admin

  • 浏览器访问 https://:28443/ 应能打开登录页;
  • 访问 https://:28443/admin/ 应能打开管理后台;
  • 首次登录使用 docker-compose-setup.sh 输出的 superAdmin 账号(或 OCTO_ADMIN_PWD)。

8.4 WebSocket 长连接

8.5 MinIO / MySQL / Redis 内部检查

# MySQL
docker compose exec -T mysql mysqladmin -uroot -p"$MYSQL_ROOT_PASSWORD" ping -h 127.0.0.1 --silent
# 预期:mysqld is alive

# Redis
docker compose exec -T redis redis-cli ping
# 预期:PONG

# MinIO
curl -fsS http://127.0.0.1:29000/minio/health/live && echo "[OK] minio"

8.6 日志快速巡检

docker compose logs --tail=50 octo-server | grep -iE "error|fatal|panic" || echo "no obvious errors"
docker compose logs --tail=50 nginx | grep -iE "error" || echo "nginx ok"

9. 离线环境升级流程

场景:已有离线部署运行中,发布了新版本(比如 octo-server 新版本、新增模块),

需要在不联网的情况下升级。

9.1 有网机器准备

  1. 拉取新版本镜像(所有需要升级的服务);
  2. 如果有 `octo-search-opensearch-ik` 新版本,重新 `docker compose build search-opensearch`;
  3. 把新旧版本镜像分别 save(或按服务单独 save),生成新的 tar 包与 SHA256SUMS;
  4. 获取新版本的 `docker/docker-compose.yaml`、`configs/`、`nginx/`、`scripts/` 等文件,
  5. 仔细阅读该版本的 CHANGELOG / Release Notes,确认是否有:
  • 数据库迁移脚本(一般在 scripts/ 或容器内自动执行,如 drive-migrate);
  • 新增必填环境变量;
  • profile 变化(新模块或模块合并/拆分);
  • 是否需要重建 volume、清空缓存。

9.2 离线机器升级步骤

⚠️ 升级前必须备份数据(MySQL / MinIO / OpenSearch / WuKongIM / Postgres 数据卷)。

cd /opt/octo-deployment/docker

# 1) 备份关键数据卷(示例,按需扩展)
mkdir -p /opt/backups/$(date +%Y%m%d-%H%M%S)
docker run --rm -v octo_mysql-data:/data -v /opt/backups/...:/backup busybox tar czf /backup/mysql-data.tar.gz -C /data .
docker run --rm -v octo_minio-data:/data -v /opt/backups/...:/backup busybox tar czf /backup/minio-data.tar.gz -C /data .
# wukongim、opensearch、fleet-postgres 等按需同样备份

# 2) 导入新镜像
docker load -i /path/to/new-images/*.tar

# 3) 替换 docker/ 目录下的配置(保留 .env 和 certs/)
tar xzf /path/to/new-octo-docker-configs.tar.gz -C /opt/octo-deployment/
# 然后用 diff 检查 .env 是否需要补充新变量
cp .env .env.bak
# 根据新的 compose/setup 提示,补充新出现的变量到 .env

# 4) 拉取新镜像(已离线 load,不会真的去 Registry 拉;compose 会识别本地镜像)
docker compose pull

# 5) 执行一次性数据库迁移(如果该版本有 scripts/ 下的迁移脚本或专门 migrate 服务)
# Docker Compose 通过 drive-migrate / docs-html-migrate 等 one-shot 服务自动跑迁移,
# up -d 时会执行;也可以手工单独触发:
docker compose up -d drive-migrate docs-html-migrate   # 按需

# 6) 滚动重启受影响服务
docker compose up -d
# 如只升级 octo-server:
docker compose up -d --force-recreate octo-server

9.3 升级后验证

  • 新增 API 端点是否可用;
  • 旧会话/消息是否可正常加载;
  • 上传/下载文件、发送消息、搜索(若启用)、文档协同(若启用)功能是否正常;
  • 日志中是否出现不断重启的容器(docker compose ps 观察 STATUS)。

9.4 回滚

# 1) 停止新版本服务
docker compose down

# 2) 从备份恢复数据卷(示例)
docker run --rm -v octo_mysql-data:/data -v /opt/backups/...:/backup busybox sh -c \
  "rm -rf /data/* && tar xzf /backup/mysql-data.tar.gz -C /data"

# 3) load 旧镜像(如果新镜像覆盖了旧 tag,需要重新 load 旧版本 tar)
docker load -i /path/to/old-images/*.tar

# 4) 还原旧版 docker/ 目录(包括旧 compose yaml)
# 5) docker compose up -d

10. 可选:通过客户内网私有 Registry 中转

  1. 在有网机器把所有镜像 `docker tag` 到客户 Registry 前缀,并 `docker push`;
  2. 在离线机 `.env` 中通过 `OCTO_XXX_IMAGE=harbor.customer.local/octo/:` 覆盖;
  3. 确保 docker daemon 已配置 `insecure-registries` 或已信任 Registry 证书;
  4. `docker compose pull` → `docker compose up -d`。

11. 待确认项

  1. 遥测开关变量名:`docker-compose.yaml` 中未发现显式 `DISABLE_TELEMETRY` 变量;如果
  2. ARM64 镜像支持情况:`mininglamposs/*` 与 `hub2.intra.mlamp.cn/octo/*` 镜像
  3. OpenSearch IK 镜像离线构建产物分发方式:当前需要客户/交付在有网机执行
  4. `latest` 标签稳定性:核心 OCTO 镜像(octo-server / octo-web / octo-admin /
  5. MySQL/Redis/MinIO 等第三方镜像的合规来源:政企客户可能要求使用其内部

附录 A:一键 pull 脚本(有网机)

#!/usr/bin/env bash
set -euo pipefail
IMAGES=(
  # core
  busybox:1.36
  hub2.intra.mlamp.cn/octo/busybox:1.36
  mysql:8.0
  redis:7-alpine
  minio/minio:RELEASE.2025-04-22T22-12-26Z
  minio/mc:RELEASE.2025-04-16T18-13-26Z
  wukongim/wukongim:v2.2.4-20260313
  mininglamposs/octo-server:latest
  nginx:1.27-alpine
  mininglamposs/octo-web:latest
  mininglamposs/octo-admin:latest
  mininglamposs/octo-marketplace:latest
  # summary
  mininglamposs/octo-smart-summary-api:latest
  mininglamposs/octo-smart-summary-worker:latest
  # speech
  mininglamposs/octo-speech:latest
  mininglamposs/octo-speech-admin:latest
  # docs
  mininglamposs/octo-docs-backend:0.8.0
  # search
  apache/kafka:3.8.0
  mininglamposs/octo-search-indexer:latest
  # fleet
  postgres:16-alpine
  mininglamposs/octo-fleet:latest
  # drive / docs-html / doc-index / drive-index
  migrate/migrate:v4.18.3
  hub2.intra.mlamp.cn/octo/octo-drive:v0.5.0
  hub2.intra.mlamp.cn/octo/octo-docs-html:v0.4.0
  hub2.intra.mlamp.cn/octo/octo-doc-indexer:v1.1.0
  hub2.intra.mlamp.cn/octo/tika:3.3.0.0
  hub2.intra.mlamp.cn/octo/octo-drive-indexer:v0.1.0
)
for img in "${IMAGES[@]}"; do
  echo ">>> pulling $img"
  docker pull "$img"
done
echo ">>> Building octo-search-opensearch-ik:2.17.0"
(cd "$(dirname "$0")/.." && docker compose build search-opensearch)
echo "All done."

附录 B:一键 load 脚本(离线机)

#!/usr/bin/env bash
set -euo pipefail
DIR="${1:-/opt/octo-offline-bundle/images}"
for f in "$DIR"/*.tar; do
  echo ">>> loading $f"
  docker load -i "$f"
done
echo "All images loaded. Verifying..."
docker images | grep -E "octo|busybox|mysql|redis|minio|wukongim|nginx|kafka|postgres|migrate|tika|opensearch"