恒美微站
首页
关于我们
建站服务
主题模板
案例展示
资讯中心
联系我们
信创环境无外网离线部署实践:Docker镜像导出与Harbor私有仓库搭建
首页
资讯中心
/
信创环境无外网离线部署实践:Docker镜像导出与Harbor私有仓库搭建
信创环境无外网离线部署实践:Docker镜像导出与Harbor私有仓库搭建
发布时间:2026/10/7 22:20:43
先在脑子里把整个链路过一次CubeStudio 这种企业级 AI 平台要私有化部署到完全无外网的信创环境核心就是“把外网的所有依赖提前打包再通过隔离介质送进去”。镜像导出、Harbor 离线仓库、内网编排启动每一步都不难但每一步都有坑。这篇文章我会把自己实际操作中的完整流程、配置、排错都放进来给同样在做信创离线部署的朋友做个参考。1. 先把整套部署思路理清楚1.1 完全无外网环境的典型部署链路很多人在接到“内网私有化部署”需求时第一反应是“不就是 docker pull 吗放到内网跑一下”。等你真正站到一台没有任何外网连接的服务器前就会发现连docker pull nginx都执行不了更别提拉一套 CubeStudio 的镜像了。所以必须把部署拆成三个物理阶段来准备外网同步机这台机器可以访问外网负责从镜像仓库拉取 CubeStudio 所有服务镜像、Harbor 离线安装包、Docker 与 Compose 组件包统一打成离线介质包。隔离介质通常是一块移动硬盘或 U 盘也可以是企业内部允许的数据摆渡系统。介质上存放同步机整理好的所有 tar 包、rpm 包、安装脚本。内网资源区包括一台 Harbor 镜像仓库服务器和多台 CubeStudio 业务节点。所有业务节点都从 Harbor 拉镜像这样后续扩容、升级、节点重建都不需要重新插 U 盘。这个链路看似多绕了一步实际上是最稳的。尤其信创环境里机器可能是鲲鹏、飞腾、海光、兆芯等多种 CPU 架构操作系统可能是麒麟、统信 UOS如果只靠一台机器离线 load后续其他节点没法复用一套镜像那才是灾难。1.2 为什么离线部署一定要上 Harbor有人会问内网机器不多的话直接把镜像 tar 包拷到每一台机器、执行docker load不就行了吗短期看确实可以但问题出在“私有化交付”这件事上镜像没有统一版本管理CubeStudio 前后端、中间件、算法引擎加起来十几个镜像散落在各节点上没法确认哪台跑的是哪个版本。升级与回滚困难想升级某个服务版本你得重新打包 tar再逐台 load、逐台重启出了问题还没法快速回退。多节点拉取不可控一旦后续要加一台计算节点做 GPU 推理新节点必须从头对接离线介质。Harbor 的价值就是把这些镜像集中到内网一个标准仓库里所有节点通过192.168.x.x/cubestudio/xxx:tag这种地址拉取。它本身也提供镜像复制、回收策略、安全扫描这些能力很多信创项目验收时也会把“是否具备统一镜像仓库”作为一项指标。所以我这边最终定的架构是隔离网内一台 Harbor 多台应用节点应用节点上通过 Docker Compose 编排 CubeStudio所有镜像统一从 Harbor 获取。2. 外网侧准备把所有能搬的东西提前打成包2.1 先理清 CubeStudio 有哪些镜像这一步最容易被忽略但恰恰是最关键的。我一般拿到交付包后第一件事是去读 CubeStudio 官方提供的 compose 文件或离线清单把镜像逐个列出来保存成一个images.txt。以生产环境为例通常包含以下几类前端网关负责 Web 入口、权限校验、反向路由一般是一个 nginx 类镜像。后端服务负责任务编排、用户管理、模型仓库逻辑这是核心 API 服务。数据库PostgreSQL保存元数据和任务状态。对象存储MinIO存放数据集、模型权重、日志文件。缓存队列Redis用于会话和异步任务。算子引擎部分场景需要 Notebook 或训练执行器可能还需要独立镜像。我列一下常见的清单格式cubestudio/frontend:2.1.0 cubestudio/backend:2.1.0 cubestudio/notebook:2.1.0 cubestudio/postgres:15.2 cubestudio/minio:RELEASE.2024-08-03T04-33-05Z cubestudio/redis:7.2-alpine这个文件必须和最终内网部署用的docker-compose.yml对齐千万别漏。漏一个镜像内网里就得多跑一次摆渡。2.2 镜像导出命令与多架构踩坑记录清单整理好以后在同步机上执行批量拉取和导出。我直接给脚本按顺序操作mkdir -p /opt/offline/images cd /opt/offline # 逐个拉取 while read -r img; do docker pull $img done images.txt # 逐个导出为独立 tar方便按需搬运 while read -r img; do name$(echo $img | tr /: _) docker save -o images/${name}.tar $img done images.txt # 统一打一个大包方便一次性拷走 tar -czf cubestudio-images.tar.gz images/如果单个 tar 太大可以考虑分卷压缩split -b 4G -d cubestudio-images.tar.gz cubestudio-images.tar.gz.为什么我建议导出成独立 tar 而不是一个大包因为信创内网经常存在“先部署基础环境、后部署业务应用”的节奏。先送基础镜像后送业务镜像独立 tar 更方便。当然如果摆渡介质空间够直接一个大包也行。这里必须提一个容易翻车的地方CPU 架构匹配。同步机如果是 x86 机器而内网信创服务器是鲲鹏或者飞腾这类 ARM64 芯片直接导出的镜像 load 进去大概率报exec format error因为镜像里的程序二进制是 x86 指令集。处理办法有两个在同步机上用docker pull --platform linux/arm64拉取对应架构镜像再导出更稳妥的方式是找一台与内网目标环境相同 CPU 架构的同步机或者先确认镜像仓库是否提供多架构 manifest再拉取对应平台镜像。建议在镜像 tar 包命名中明确标记架构比如加上x86_64或aarch64后缀否则内网同事看到一堆 tar 根本分不清哪个能用。2.3 配套安装包清单Docker、Compose、Harbor很多离线部署失败不是败在业务镜像而是败在内网机器连 Docker 都没装好或者 Harbor 离线安装包里的 Docker Compose 插件版本不兼容。所以同步机上要准备一整套“环境安装包”。我整理的标准清单是这样的/opt/offline/ ├── images/ │ ├── cubestudio_frontend_2.1.0.tar │ ├── cubestudio_backend_2.1.0.tar │ └── ... ├── docker/ │ ├── docker-ce-24.0.7.rpm │ ├── docker-ce-cli-24.0.7.rpm │ ├── containerd.io-1.6.28.rpm │ ├── docker-compose-plugin-2.24.0.rpm │ └── docker-buildx-plugin-0.14.0.rpm ├── harbor/ │ └── harbor-offline-installer-v2.11.1.tgz ├── gpu/ │ ├── nvidia-container-toolkit-*.rpm │ └── libnvidia-container-*.rpm └── images.txt这里有几个点要提前确认第一Docker rpm 包必须按内网操作系统的发行版来准备。麒麟 V10 和统信 UOS 大都基于 RHEL8/CentOS8 内核一般可以用 el8 系列的 rpm 包但最好还是拿一台同版本的机器先验证。第二Harbor 离线安装包自带了 Harbor 所有组件镜像不需要额外拉镜像。但 Harbor 2.x 的离线安装脚本依赖 Docker Compose v2 插件如果内网机器没有会直接报docker compose command not found。第三如果 CubeStudio 需要 GPU 推理还要准备 NVIDIA Container Toolkit 的离线 rpm或者对应信创算力卡的容器运行时组件。这些提前准备好能省掉后面至少一天的时间。3. 内网 Harbor 离线搭建实战3.1 先把 Docker 和 Compose 插件补齐内网服务器第一次通电后通常只有一个干净的操作系统。我先手动挂载介质把 docker 安装包解压出来mkdir -p /mnt/usb mount /dev/sdb1 /mnt/usb cd /mnt/usb/docker rpm -Uvh *.rpm systemctl enable --now docker docker version如果是 Debian/Ubuntu 内核的信创系统rpm 包就不能用了需要提前准备 deb 包用dpkg -i安装。这就是为什么我强调“按内网系统准备安装包”。接着确认 Docker Compose 插件是否生效docker compose version如果报命令找不到就把同步机上准备好的 compose 插件手动拷贝到对应目录mkdir -p /usr/local/lib/docker/cli-plugins cp /mnt/usb/docker/docker-compose /usr/local/lib/docker/cli-plugins/ docker-compose chmod x /usr/local/lib/docker/cli-plugins/docker-compose docker compose version这一步看似基础但很多 Harbor 安装失败就是因为它。Harbor 的install.sh会调用 docker compose没有这个插件脚本跑到一半就停住了。3.2 Harbor 离线安装与 HTTPS 证书配置安装完基础环境后开始装 Harbor。我用的是 Harbor 离线安装包里面包含了 Harbor 自身的全部镜像所以不需要内网访问外网。mkdir -p /data/harbor tar xzf /mnt/usb/harbor/harbor-offline-installer-v2.11.1.tgz -C /data/harbor cd /data/harbor cp harbor.yml.tmpl harbor.yml编辑harbor.yml核心配置如下hostname: 192.168.209.133 http: port: 80 https: port: 443 certificate: /data/cert/harbor.crt private_key: /data/cert/harbor.key harbor_admin_password: YourStrongPassword data_volume: /data/harbor/data生产环境我建议直接启用 HTTPS。离线环境没有正规 CA可以自建一套内部 CA 和证书mkdir -p /data/cert openssl genrsa -out /data/cert/harbor.key 2048 openssl req -new -x509 \ -key /data/cert/harbor.key \ -out /data/cert/harbor.crt \ -days 3650 \ -subj /CN192.168.209.133自签名证书在浏览器里会有告警但内网私有化部署无所谓。真正要注意的是后面 Docker 节点信任证书那一步我放在 3.3 讲。然后执行安装./install.sh --with-trivy加上--with-trivy是为了启用镜像漏洞扫描很多信创安全验收会要求这个能力。安装结束后检查容器状态docker ps | grep harbor看到 harbor-core、harbor-portal、harbor-registry 等容器都在Up状态基本就成功了。再用 curl 验证 APIcurl -k https://192.168.209.133/v2/返回一个空的{}或者版本信息都算正常。3.3 让内网所有业务节点信任 HarborHarbor 起来只是第一步真正会卡人的是 Docker 客户端推送镜像时的信任问题。默认情况下Docker 只信任 HTTPS 且证书受系统信任的仓库。内网自签名证书默认不被信任所以要在每个业务节点的 Docker 配置里做两件事mkdir -p /etc/docker/certs.d/192.168.209.133 cp /data/cert/harbor.crt /etc/docker/certs.d/192.168.209.133/ca.crt这是最规范的证书信任方式。我实际操作中还会同时配置insecure-registries因为有些脚本拉镜像时不一定走 443 端口{ insecure-registries: [192.168.209.133] }修改后重启 Dockersystemctl restart docker注意重启 Docker 会中断当前节点上所有运行中的容器所以这个操作一定要放在业务低峰期或者先把已有容器 stop 再操作。这里也顺手说明一个后面常见的问题来源很多“harbor 推送失败”的第一行日志是get https://192.168.209.133/v2/: dial tcp 192.168.209.133:xxx: connect: connection refused十有八九就是 Harbor 服务没起来或者节点没有信任这个地址。后面我会专门列排查表。4. 镜像导入与推送4.1 把离线导出的镜像包导进内网Harbor 装好后接下来就是把 CubeStudio 的镜像从 tar 包里 load 进来再推送到 Harbor。首先在内网机器的介质目录找到镜像包docker load -i images/cubestudio_frontend_2.1.0.tar docker load -i images/cubestudio_backend_2.1.0.tardocker load会把镜像的层和元数据导入本地然后可以在本地镜像列表看到它们docker images | grep cubestudio这里会遇到一个典型问题导出的镜像保存了原始仓库名和 tag比如cubestudio/backend:2.1.0但这个地址在内网里不存在必须重新打上 Harbor 的仓库地址否则内网节点没法从这个地址拉取。4.2 批量重打标签并推送到 Harbor手动一条条 retag 太慢了项目交付时我一般写一个批量脚本registry192.168.209.133 projectcubestudio while read -r img; do tag${img##*:} repo${img%%:*} docker tag $img $registry/$project/$repo:$tag docker push $registry/$project/$repo:$tag done /opt/offline/images.txt执行完后到 Harbor 的 Web 界面里应该能看到cubestudio项目下面所有镜像和 tag。再随便挑一个拉取测试docker pull 192.168.209.133/cubestudio/backend:2.1.0如果拉取成功并显示Digest信息说明内网 Harbor 本身已经正常工作了。我要特别提醒一下推送到 Harbor 的 tag 一定要和后续 docker-compose.yml 里的镜像地址完全一致包括仓库 IP、项目名、镜像名、版本号。线上我见过太多人因为漏写了项目名cubestudio导致 CubeStudio 启动时一直从默认 Docker Hub 拉镜像最后报manifest unknown。4.3 常见推送失败问题排查红框里最经典的一条报错harbor 推送失败 get https://192.168.209.133/v2/: dial tcp 192.168.209.133:xxx: connect: connection refused基本可以按下面这个顺序排查先看 Harbor 容器状态docker ps | grep harbor如果 harbor-core、harbor-registry 没起来先看日志。再看端口监听ss -tlnp | grep 443如果 443 没有监听说明 Harbor 的 nginx 没起来。然后看业务节点是否信任curl -k https://192.168.209.133/v2/如果在业务节点上都不通那就是网络权限或防火墙问题。最后看 daemon.jsoncat /etc/docker/daemon.json确认insecure-registries或证书信任配置没有拼错改完记得重启 docker。这个排查顺序我基本固定下来了每次遇到类似问题都能快速定位而不是盲改一堆配置。5. CubeStudio 服务编排与启动5.1 docker-compose 编排文件解析CubeStudio 一般提供官方 compose 编排文件但既然我们离线部署镜像地址要从原始的 Docker Hub 改成内网 Harbor 地址。下面给一个精简版示例实际以交付版本为准version: 3.8 services: postgres: image: 192.168.209.133/cubestudio/postgres:15.2 restart: always environment: POSTGRES_DB: cubestudio POSTGRES_USER: cubestudio POSTGRES_PASSWORD: ChangeMe volumes: - /data/cubestudio/postgres:/var/lib/postgresql/data redis: image: 192.168.209.133/cubestudio/redis:7.2-alpine restart: always minio: image: 192.168.209.133/cubestudio/minio:RELEASE.2024-xx restart: always command: server /data --console-address :9001 volumes: - /data/cubestudio/minio:/data backend: image: 192.168.209.133/cubestudio/backend:2.1.0 restart: always depends_on: - postgres - redis - minio environment: DB_HOST: postgres DB_PORT: 5432 REDIS_HOST: redis MINIO_ENDPOINT: http://minio:9000 LICENSE_FILE: /etc/cubestudio/license.lic volumes: - /data/cubestudio/models:/data/models - /data/cubestudio/datasets:/data/datasets - /opt/cubestudio/license.lic:/etc/cubestudio/license.lic:ro frontend: image: 192.168.209.133/cubestudio/frontend:2.1.0 restart: always depends_on: - backend ports: - 8080:80熟悉 Docker Compose 的人可能注意到了这里把 license 文件也挂载进去了。企业私有化部署经常需要离线授权license 文件要么放在数据盘要么以只读方式挂进容器这个必须提前规划。5.2 数据目录规划与启动顺序内网机器的数据落到哪里一开始就要想好。我习惯把所有有状态数据统一放在/data/cubestudio/下目录结构这样分/data/cubestudio/ ├── postgres/ # 元数据库 ├── minio/ # 对象存储数据 ├── models/ # 模型权重 ├── datasets/ # 数据集 └── logs/ # 业务日志启动服务不要一股脑docker compose up -d建议分步启动先启动依赖组件再启动业务服务docker compose up -d postgres docker compose up -d redis minio docker compose up -d backend docker compose up -d frontend依赖服务起来后可以用一个简单的循环等 backend 健康检查通过until curl -sf http://localhost:8080/api/health; do sleep 2 echo waiting for backend... done健康检查通过后再访问前端页面看是否能正常登录。5.3 信创环境里的 AI 算力适配CubeStudio 如果承担大模型微调或推理任务内网节点一般要挂 GPU 或国产加速卡。以 NVIDIA GPU 为例离线环境需要提前准备rpm -ivh libnvidia-container*.rpm rpm -ivh nvidia-container-toolkit*.rpm nvidia-ctk runtime configure --runtimedocker systemctl restart docker重启后检查docker info | grep -i runtime能看到nvidia运行时说明配置成功。这时候在 compose 文件里给训练/推理服务加上资源限制trainer: image: 192.168.209.133/cubestudio/trainer:2.1.0 runtime: nvidia deploy: resources: reservations: devices: - driver: nvidia count: 1 capabilities: [gpu]国产加速卡方面比如 DCU、昇腾这类通常不支持标准的nvidiaruntime更多是通过设备映射/dev/davinci0、/dev/hisi_hdc等方式挂进容器还要设置对应的LD_LIBRARY_PATH。这些适配强烈建议在投标前或项目初期就拿真机验证不要在部署当天才试。6. 常见问题速查与排错实录6.1 Harbor 与镜像推送问题现象可能原因处理方式get https://192.168.209.133/v2/: dial tcp ... connection refusedHarbor 容器没启动docker ps检查看docker logs harbor-core同样的报错但 Harbor 在运行业务节点没有信任仓库地址配置insecure-registries或证书信任重启 dockerx509: certificate signed by unknown authorityCA 证书未放到节点复制harbor.crt到/etc/docker/certs.d/192.168.209.133/ca.crtunauthorized: authentication required推送时没登录先docker login 192.168.209.133manifest unknowntag 不存在或名称不一致对比 compose 文件与 Harbor 中的镜像 tagHarbor 版本升级时也要小心。老版本升级到新版本官方有upgrade.sh但升级前一定先备份harbor.yml和data_volume指向的数据目录最好在测试环境先跑一遍数据库迁移再动生产。6.2 信创系统与容器运行时问题现象可能原因处理方式exec format error镜像架构与 CPU 不匹配重新在目标架构同步机导出镜像docker compose command not foundCompose 插件未安装手动拷贝插件到/usr/local/lib/docker/cli-plugins系统自带 podman 与 docker 冲突端口或 socket 占用停用 podman socket重新指定 docker socketWindows Server 2022 上离线起 WSL 容器失败WSL 发行版没有离线包使用wsl --install --from-file 离线包仅适合开发验证生产建议 Linux 信创环境补充一点信创机器的内核版本往往比公版 CentOS 低Docker 版本不要追新建议选 20.10 或 24.0 这种经过大量国产系统验证的稳定版本。我在麒麟 V10 上见过 Docker 25 和系统内核网络栈的兼容性问题后来降到 24.0 就正常了。6.3 CubeStudio 业务层常见问题现象可能原因处理方式前端页面可以打开但登录请求 502backend 容器没起来看docker logs backend往往和数据库连接有关上传数据集失败MinIO 对象存储无法访问检查 compose 里MINIO_ENDPOINT是否用服务名而不是 localhost模型训练任务卡死GPU 运行时未生效docker exec进容器跑nvidia-smi确认设备可见磁盘写满镜像和模型权重占用过大提前规划大容量数据盘Harbor 设置镜像回收策略实际项目里数据库连接失败和 MinIO 地址配置错误是出现频率最高的两个问题。内网里容器之间通信一定要用 compose 中的服务名千万别改成 IP否则服务重启后 IP 一旦变化整套服务就断了。整个流程走下来我的体会是离线部署真正考验的不是操作能力而是“提前规划”的能力。哪些镜像需要、哪些 rpm 需要、哪些架构需要在同步机阶段全部想清楚内网就是按部就班。如果等到内网里发现缺包再安排介质摆渡一次至少折腾半天。按照上面这套“镜像导出 Harbor 编排启动”的组合基本能把离线部署从“玄学”变成“流水线”。