从零搭建机器人技术文档中心:GitLab + Antora + CI/CD + Nginx 实战教程
- 1. 最终目标、角色与参数
- 2. 阶段一:准备 Windows、WSL 与 Ubuntu Server
- 3. 阶段二:安装 Docker 并处理镜像网络
- 4. 阶段三:用 Compose 部署 GitLab CE
- 5. 阶段四:在 WSL 建立最小 Antora 样例
- 6. 阶段五:练习图片、正文结构与跨页引用
- 7. 阶段六:增加 FANUC 与 ABB 多版本
- 8. 阶段七:在 GitLab 创建 Group 与内容仓库
- 9. 阶段八:让 Antora 读取私有 GitLab 仓库
- 10. 阶段九:独立网站总控仓库 robot-docs-site
- 11. 阶段十:启动并注册 GitLab Runner
- 12. 阶段十一:修复 helper image 与首次镜像下载
- 13. 阶段十二:第一个 CI Job
- 14. 阶段十三:配置 CI 变量与 Antora 构建 Artifact
- 15. 阶段十四:部署 Nginx 并验证目录挂载
- 16. 阶段十五:让 CI 自动部署到 Nginx
- 17. 阶段十六:内容仓库更新触发 Site Pipeline
- 18. 阶段十七:将触发配置覆盖 ABB 1.0 和 FANUC
- 19. 阶段十八:统一共享 CI 模板
- 20. 可选扩展:无版本门户首页
- 21. 把本教程加入当前服务并验证功能
- 22. 典型故障与逐层排查
- 23. 最终目录与日常工作流
- 24. 配套资源与参考
本教程整理自“文档网站搭建建议”对话的完整实验记录。目标是搭建一套自己可控的局域网文档中心:用 GitLab 保存 AsciiDoc,用 Runner 执行 Antora 构建,用 Nginx 提供网页;ABB 与 FANUC 分别维护内容仓库,各版本内容更新后自动触发网站发布。
| 原实验先在 WSL 本地学习 Antora,之后才搭建 Ubuntu Server。为方便从零复现,本文将服务器环境准备放在前面,保留原实验的项目命名、地址和关键故障。命令经过整理,并非逐条聊天记录。门户首页在原对话中仅提出方案,本文放在可选扩展中;搜索、定制 UI、域名和 HTTPS 不属于已完成实验。 |
1. 最终目标、角色与参数
1.1. 系统各部分做什么
| 部分 | 职责 |
|---|---|
Ubuntu Server |
提供长期运行的服务器环境、网络与持久化目录。 |
Docker / Compose |
用镜像运行 GitLab、Runner、Nginx;Compose 用配置文件描述启动方式。 |
GitLab CE |
保存 Git 仓库、管理用户权限、创建 Pipeline、保存 Artifact。 |
GitLab Runner |
领取并执行 CI Job;Docker executor 为 Job 创建临时容器。 |
Antora |
读取指定仓库和分支,将 |
Nginx |
持续监听端口,将生成好的 HTML、CSS、JS、图片返回给浏览器。 |
多项目触发 |
内容仓库的 Pipeline 触发 Site 仓库的 Pipeline。 |
共享 CI 模板 |
把触发规则放在 Site 仓库维护,由各内容仓库引用。 |
WSL / 编辑电脑 Ubuntu Server
修改 AsciiDoc 192.168.179.129
│ git push │
└─────────────────────────────→ GitLab :8181
robot-docs/
├─ robot-docs-abb v1.0 / v1.1
├─ robot-docs-fanuc v1.0
└─ robot-docs-site main
↑ 内容仓库触发
│
Runner
│ npm ci + Antora
build/site
│ Artifact → deploy-docs
/srv/robot-docs-site
│ 只读挂载
Nginx :8080
│
浏览器
CI(持续集成)负责自动验证和构建;本实验的 CD(持续部署)把成功构建的网页自动复制到网站目录。Pipeline 是一次流水线,Stage 是阶段,Job 是实际执行命令的任务。
1.2. 实验参数表
| 参数 | 本文示例 | 使用前核对 |
|---|---|---|
服务器地址 |
192.168.179.129 |
替换为你的虚拟机实际 IP;尽量设置 DHCP 地址保留。 |
服务器用户 |
vision3d |
替换为安装 Ubuntu 时创建的用户。 |
GitLab Web |
GitLab、Runner、Job 容器和 WSL 都必须能访问。 |
|
Ubuntu SSH |
22 |
用于登录服务器。 |
GitLab SSH |
2222 |
映射到 GitLab 容器的 22,区别于服务器登录端口。 |
文档网站 |
由 Nginx 提供。 |
|
Group |
robot-docs |
包含 Site、ABB、FANUC 三个项目。 |
工作目录 |
/robot_docs_demo、/robot_docs_site |
位于 WSL;不等于服务器的 |
Runner 配置 |
/srv/gitlab-runner/config/config.toml |
位于 Ubuntu Server。 |
网站发布目录 |
/srv/robot-docs-site |
位于 Ubuntu Server,Nginx 只读、CI 可写。 |
历史镜像代理 |
docker.1ms.run |
原实验实际使用的第三方代理;现在是否可用需自己验证。 |
本文中 Bash 命令在 Ubuntu/WSL 执行。带 \ 的多行命令是一条命令,反斜杠必须是该行最后一个字符;改成一行时去掉反斜杠即可。命令中的示例邮箱、版本和 Token 占位符需替换,不要把提示符 $ 一起复制。
历史日志记录了 Node 22、Antora 3.2.0、Runner 19.3.3 等版本,这些是当时环境的信息,不代表本教程已在这些版本的新环境中重新部署。新建环境应固定实际可用版本,Runner 与 helper 必须匹配。GitLab 的 strategy: mirror 要求 GitLab 18.2 或以上。
|
2. 阶段一:准备 Windows、WSL 与 Ubuntu Server
2.1. 创建虚拟机
-
准备 Windows 主机、可正常启动虚拟机的 VMware Workstation,以及 Ubuntu Server 24.04 LTS 安装 ISO。
-
创建独立实验虚拟机,选择 Linux / Ubuntu 64 位,网络使用 NAT。可从 4 vCPU、8 GB 内存、100 GB 虚拟磁盘开始;这是实验起点,内存和磁盘应按实际负载调整。
-
启动安装程序,选择标准 Ubuntu Server,设置用户名与密码。
-
网络优先使用 DHCP;安装过程中显示的临时地址不一定是安装完成后的实际地址。
-
存储选择仅用于这台实验机的虚拟磁盘,可使用 LVM。确认格式化对象确实是新虚拟磁盘再继续。
-
Ubuntu Pro 可选择暂时跳过;勾选安装 OpenSSH Server,实验初期允许密码登录。
-
Featured Server Snaps 不必选择;完成安装后卸载 ISO 并重启。
原实验 100 GB 虚拟磁盘使用 LVM,根分区约 49 GB,其余空间留在卷组中。虚拟磁盘大小和根分区可用空间是两回事,Docker 镜像、GitLab 数据和 Artifact 主要消耗根分区空间。
hostname -I
ip -br addr
ip route
df -h /
sudo vgs
sudo lvs
sudo systemctl status ssh --no-pager
在 Windows PowerShell 或 WSL 登录服务器:
ssh vision3d@192.168.179.129
在 Ubuntu Server 更新系统与安装常用工具:
sudo apt update
sudo apt upgrade -y
sudo apt install -y curl ca-certificates git tree unzip
curl -I https://ubuntu.com
验收:Windows 能 SSH 登录;服务器有默认路由,软件源可访问;确认实际 IP 后,后续所有配置使用同一地址。
2.2. WSL 负责编辑和本地实验
Windows PowerShell 中可查看 WSL:
wsl --list --verbose
如果尚未安装,在有相应权限的 PowerShell 中执行 wsl --install -d Ubuntu,按系统提示完成重启和初始化。已有 WSL Ubuntu 可直接使用。以后文中的 WSL 表示编辑与本地构建环境,Ubuntu Server 表示运行 GitLab/Runner/Nginx 的虚拟机。
2.3. VMware 启动故障
原实验曾在 Windows 10 升级到 Windows 11 后出现:
无法打开内核设备 "\\.\VMCIDev\VMX"
模块 "DevicePowerOn" 启动失败
如果旧虚拟机也无法启动,应先检查 VMware 主机驱动、服务与 Windows 版本兼容性。关闭虚拟机、备份虚拟机文件,使用具有管理员权限的安装程序修复或更新 VMware,重启 Windows 后再次测试。出现 “You must have administrative privileges…” 时,说明当前修复程序没有提升权限。这个错误发生在 Ubuntu 启动前,不应通过修改 Docker 或 GitLab 配置处理。
3. 阶段二:安装 Docker 并处理镜像网络
3.1. 安装 Docker Engine 与 Compose
原实验访问 download.docker.com 出现连接重置,因此改用 Ubuntu 软件仓库。以下是一条完整的 Ubuntu Server 实验安装路线:
sudo apt update
sudo apt install -y docker.io docker-compose-v2
sudo systemctl enable --now docker
sudo systemctl status docker --no-pager
sudo docker --version
sudo docker compose version
sudo usermod -aG docker "$USER"
exit
重新 SSH 登录,使用户组生效,然后执行:
docker ps
docker run --rm hello-world
docker.io 是 Ubuntu 打包的 Engine;docker-compose-v2 提供 docker compose 子命令。另一条路线是使用 Docker 官方 APT 源安装 docker-ce 与 docker-compose-plugin,不要混装两条路线。软件包不存在时检查 Ubuntu 版本、软件源和 universe 仓库配置。官方路线参见 Docker Ubuntu 安装说明。
| 加入 docker 用户组等同于授予强大的主机管理权限。本文使用独立实验机,避免把不受信任用户加入该组。 |
3.2. 区分 DNS、HTTPS 与 Docker 自身问题
getent ahostsv4 registry-1.docker.io
resolvectl status
curl -4 -I --connect-timeout 10 https://registry-1.docker.io/v2/
curl -I --connect-timeout 10 https://registry.gitlab.com/v2/
sudo journalctl -u docker -n 80 --no-pager
Registry 返回 HTTP 401 Unauthorized 通常说明已经连通,只是尚未认证;连接超时、重置和无法解析是另一类故障。一次 DNS 查询不能单独证明根因,应结合解析、TCP/HTTPS 和 Docker 日志。原实验先发现 NAT DNS 可疑,切换 DNS 后 Docker Hub 的 HTTPS 仍失败,说明只换 DNS 没有解决全部问题。
临时修改 DNS(网卡名须取自 ip -br addr):
sudo resolvectl dns ens33 223.5.5.5 119.29.29.29
sudo resolvectl flush-caches
resolvectl status ens33
该设置可能在重启或网络重配后失效。需要持久化时先查看 /etc/netplan/,在原有网卡配置中修改 nameservers,避免覆盖原路由和地址;远程操作优先 sudo netplan try。不要将第三方公共 DNS 强行用于依赖公司内部域名的网络。
3.3. 镜像代理与离线导入
原实验成功使用了显式镜像代理路径:
docker pull docker.1ms.run/library/hello-world:latest
docker run --rm docker.1ms.run/library/hello-world:latest
同样的路径用于 library/node:22、library/nginx:alpine、gitlab/gitlab-ce 与 gitlab/gitlab-runner-helper。代理路径会直接出现在镜像名称里,与 Docker daemon 的 registry-mirrors 配置不同。Docker Hub 代理不会自动解决 registry.gitlab.com 的访问问题。
如果该历史代理不可用,可使用自己信任且可访问的镜像仓库、正确配置 Docker daemon 的网络代理,或者离线导入。以下在 能联网且架构匹配的电脑 执行:
docker pull node:22
docker save -o node22.tar node:22
scp node22.tar vision3d@192.168.179.129:~/
然后在 Ubuntu Server:
docker load -i ~/node22.tar
docker image inspect node:22
如果导入镜像名是 node:22,CI 中也应使用 node:22,或先 docker tag 为 CI 配置使用的完整镜像名。预拉取与离线导入必须针对 Job 实际使用的 Docker daemon。
验收:Docker/Compose 能报告版本,至少一个测试镜像能成功运行。不要把拉取失败误认为 Docker 安装失败。
4. 阶段三:用 Compose 部署 GitLab CE
4.1. 准备持久化目录
在 Ubuntu Server:
sudo mkdir -p /srv/gitlab/{config,logs,data}
mkdir -p ~/gitlab-docker
cd ~/gitlab-docker
nano compose.yaml
compose.yaml(保留原实验启动方式):
services:
gitlab:
image: docker.1ms.run/gitlab/gitlab-ce:latest
container_name: gitlab
restart: always
hostname: gitlab-server
environment:
GITLAB_OMNIBUS_CONFIG: |
external_url 'http://192.168.179.129:8181'
gitlab_rails['gitlab_shell_ssh_port'] = 2222
ports:
- "8181:8181"
- "2222:22"
volumes:
- "/srv/gitlab/config:/etc/gitlab"
- "/srv/gitlab/logs:/var/log/gitlab"
- "/srv/gitlab/data:/var/opt/gitlab"
shm_size: "256m"
external_url 决定 GitLab 对外链接以及这里内部 Nginx 的监听端口,因此本例使用 8181:8181。2222:22 只用于 GitLab 的 Git SSH。三个卷分别保存配置、日志和数据,使容器重建不等于仓库消失。持久化不替代备份。
latest 是原实验使用方式;建立长期运行环境前,应将其改成已验证的具体版本标签并记录镜像摘要,升级按 GitLab 支持的升级路径执行。不能通过随意拉取新 latest 跳过版本升级要求。
4.2. 启动、等待初始化并登录
docker compose config
docker compose up -d
docker ps
docker logs --tail 100 -f gitlab
第一次下载与初始化可能较慢。查看日志时按 Ctrl+C 仅退出日志跟随,不会停止后台容器。网页短暂 502 或 health: starting 时继续检查容器初始化,不要反复删容器重建。
docker exec gitlab gitlab-ctl status
curl -I http://192.168.179.129:8181/users/sign_in
docker exec -it gitlab grep 'Password:' /etc/gitlab/initial_root_password
浏览器访问 http://192.168.179.129:8181,使用 root 和初始密码登录,随后修改密码。初始密码只用于第一次登录,不要放入文档、仓库或截图。资料初始化页面可跳过。
验收:GitLab 登录成功,可进入项目创建页面;8181 是 GitLab 页面,8080 暂时还没有正式文档服务。
5. 阶段四:在 WSL 建立最小 Antora 样例
5.1. 准备 Node 与站点依赖
在 WSL 使用已有 Node 22 环境。若没有 nvm,可从其官方 Git 仓库安装一个明确版本(下面使用 v0.40.3),再安装 Node 22:
sudo apt update
sudo apt install -y git curl ca-certificates
git clone --branch v0.40.3 --depth 1 https://github.com/nvm-sh/nvm.git "$HOME/.nvm"
export NVM_DIR="$HOME/.nvm"
. "$NVM_DIR/nvm.sh"
nvm install 22
nvm use 22
nvm alias default 22
如果 ~/.nvm 已存在,不要覆盖,加载其 nvm.sh 即可。在 ~/.bashrc 中添加以下两行,使新终端也能加载:
export NVM_DIR="$HOME/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && . "$NVM_DIR/nvm.sh"
nvm 是独立开源项目;GitHub 或 Node 下载受限时,先解决网络,或从 Node 官方下载页 取得对应 Linux 架构的 Node 22 并按其说明安装。不要把 Windows Node 误当作 WSL Linux Node。先检查:
node --version
npm --version
mkdir -p ~/robot_docs_demo
cd ~/robot_docs_demo
npm init -y
npm install --save-dev --save-exact @antora/cli@3.2.0 @antora/site-generator@3.2.0
npx antora --version
3.2.0 是原对话安装输出记录的版本。若所用 npm 源不能提供该版本,先 npm view @antora/cli versions --json 与 npm view @antora/site-generator versions --json,选择二者共同支持的版本,再将两个版本同步替换。不要只替换 CLI。--save-exact 与 package-lock.json 让依赖可重现;CI 后续使用 npm ci 严格按 lock 文件安装。
5.2. 建立 ABB 内容组件
mkdir -p abb/modules/ROOT/{pages,images}
创建 abb/antora.yml:
name: abb
title: ABB机器人
version: '1.0'
nav:
- modules/ROOT/nav.adoc
创建 abb/modules/ROOT/pages/index.adoc:
= ABB 机器人文档
欢迎使用 ABB 集成实验文档。
== 文档入口
* xref:network.adoc[网络配置]
* xref:faq.adoc[常见问题]
创建 abb/modules/ROOT/pages/network.adoc:
= 网络配置
== 准备工作
NOTE: 以下是文档站点演示内容,机器人参数须依据现场实际配置。
== 操作步骤
. 核对电脑与控制器的地址。
. 检查网络连通性。
. 保存配置并记录变更。
WARNING: 修改现场设备地址前应确认停机与操作授权。
创建 abb/modules/ROOT/pages/faq.adoc:
= 常见问题
== 页面无法访问
先区分网页服务是否运行,以及页面文件是否生成。
创建 abb/modules/ROOT/nav.adoc:
* xref:index.adoc[ABB简介]
* xref:network.adoc[网络配置]
* xref:faq.adoc[常见问题]
name 是组件标识,title 是显示名称,version 是文档版本;ROOT 是默认模块,pages 放页面,images 放图片,nav.adoc 决定左侧导航。右侧页内目录由正文标题生成。
5.3. 将内容纳入 Git
cd ~/robot_docs_demo/abb
git init -b v1.0
git config user.name "Your Name"
git config user.email "you@example.com"
git add antora.yml modules
git commit -m "Add ABB 1.0 documentation"
cd ~/robot_docs_demo
本地内容源也需要 Git 仓库和至少一次提交;Antora 通过 Git 识别版本。这里仅初始化 abb,不要把包含其他子仓库、node_modules 与构建结果的整个 Demo 目录当成内容仓库。
5.4. 配置本地 playbook
创建 ~/robot_docs_demo/antora-playbook.yml:
site:
title: 机器人技术文档中心
start_page: abb::index.adoc
content:
sources:
- url: ./abb
branches: [v1.0]
ui:
bundle:
url: https://gitlab.com/antora/antora-ui-default/-/jobs/artifacts/master/raw/build/ui-bundle.zip?job=bundle-stable
snapshot: true
output:
dir: ./build/site
site、content、ui、output 是平级配置。ui.bundle.url 必须是字符串。UI 下载受限时,在可联网环境取得默认 UI bundle,放到 ui/ui-bundle.zip,将 URL 改为 ./ui/ui-bundle.zip,并把文件纳入 Site 仓库以供 CI 使用。
npx antora --clean antora-playbook.yml
find build/site -name index.html
python3 -m http.server 8080 --directory build/site
打开 Windows 浏览器 http://localhost:8080/abb/1.0/index.html。该服务运行于 WSL,不能假定 VM 的 192.168.179.129:8080 也可访问。终端关闭或按 Ctrl+C 后,临时服务会停止。
验收:能看到 ABB 首页、左侧导航、代码和提示框;日志出现 Site generation complete!。如果只显示目录列表,检查是否错误地从 ~/robot_docs_demo 而非 build/site 提供服务。
6. 阶段五:练习图片、正文结构与跨页引用
将图片复制到 abb/modules/ROOT/images/,页面中使用:
image::network-example.png[网络配置示例,width=900]
== 网络检查
=== 地址核对
NOTE: 图片资源和页面一起纳入 Git,才能在 CI 中构建。
参见 xref:faq.adoc[常见问题]。
image:: 是块图片;不要用文件系统相对路径 ../images/ 代替 Antora 资源引用。本教程自身的图片位于 images/tutorial/,可直接验证图片资源解析:
截图直接复制自原对话资源,保持原样;其内容是当时状态,不能代替新环境的验收。本文代码块中的 AsciiDoc 图片示例属于示例文本,不会被当成实际资源加载。
7. 阶段六:增加 FANUC 与 ABB 多版本
7.1. 创建 FANUC 组件
在 WSL:
cd ~/robot_docs_demo
mkdir -p fanuc/modules/ROOT/{pages,images}
fanuc/antora.yml:
name: fanuc
title: FANUC机器人
version: '1.0'
nav:
- modules/ROOT/nav.adoc
fanuc/modules/ROOT/pages/index.adoc:
= FANUC 机器人文档
本组件用于演示 FANUC R-30iB 文档的独立管理。
== 入门
内容按控制器和程序版本逐步完善。
fanuc/modules/ROOT/nav.adoc:
* xref:index.adoc[FANUC简介]
cd ~/robot_docs_demo/fanuc
git init -b v1.0
git config user.name "Your Name"
git config user.email "you@example.com"
git add antora.yml modules
git commit -m "Add FANUC 1.0 documentation"
7.2. 创建 ABB 1.1 分支
cd ~/robot_docs_demo/abb
git switch -c v1.1
nano antora.yml
将 version 改为 '1.1',编辑该版本页面,再提交:
git add antora.yml modules
git commit -m "Add ABB documentation version 1.1"
git show v1.0:antora.yml
git show v1.1:antora.yml
两个分支分别必须声明 1.0、1.1;仅创建分支但不修改 version,可能导致组件版本重复。分支名 v1.1 和文档版本 '1.1' 不必相同;网站路径由组件版本决定,本文预期 /abb/1.1/,不带 v。
将 playbook 的 content 部分改为:
content:
sources:
- url: ./abb
branches: [v1.0, v1.1]
- url: ./fanuc
branches: [v1.0]
cd ~/robot_docs_demo
npx antora --clean antora-playbook.yml
find build/site -maxdepth 3 -name index.html
验收:组件选择器中有 ABB 1.0、ABB 1.1、FANUC 1.0,版本切换后 URL 与正文对应。改版本名后使用 --clean 清理 构建输出,避免旧 /abb/v1.0/ 路径残留。
8. 阶段七:在 GitLab 创建 Group 与内容仓库
8.1. 创建空项目
浏览器进入 GitLab:
-
创建 Group
robot-docs。 -
在该 Group 下创建 Private 空项目
robot-docs-abb。 -
同样创建
robot-docs-fanuc。 -
暂不初始化 README,避免与已有本地仓库产生独立历史。
-
检查 Project name 和 Project slug 都与目标名称一致;只修改显示名不一定同步修改 slug。
8.2. 配置 GitLab SSH 密钥并推送
在 WSL 创建专用于本实验的密钥,已有合适密钥可复用:
ssh-keygen -t ed25519 -f ~/.ssh/id_ed25519_robot_docs -C "robot-docs-lab"
cat ~/.ssh/id_ed25519_robot_docs.pub
把 .pub 公钥添加到 GitLab 用户的 SSH Keys。私钥不要上传。可在 ~/.ssh/config 追加:
Host robot-docs-gitlab
HostName 192.168.179.129
User git
Port 2222
IdentityFile ~/.ssh/id_ed25519_robot_docs
IdentitiesOnly yes
ssh -T robot-docs-gitlab
cd ~/robot_docs_demo/abb
git remote add origin robot-docs-gitlab:robot-docs/robot-docs-abb.git
git push -u origin v1.0
git push -u origin v1.1
cd ~/robot_docs_demo/fanuc
git remote add origin robot-docs-gitlab:robot-docs/robot-docs-fanuc.git
git push -u origin v1.0
若已有 origin,先 git remote -v 核对,再使用 git remote set-url origin …。首推后检查 GitLab 默认分支、分支保护状态与用户权限;它们可能影响后续变量和 CI。
SSH 的标准完整 URL 形式是 ssh://git@192.168.179.129:2222/robot-docs/robot-docs-abb.git。此时 2222 是端口;不要在不带 ssh:// 的普通 SCP 形式中把它误写成目录。
验收:GitLab 中能浏览 ABB 两个版本分支及 FANUC 的 v1.0;WSL push 成功。
9. 阶段八:让 Antora 读取私有 GitLab 仓库
9.1. 项目 Deploy Token 与 Group Deploy Token
先理解三类凭据:
| 凭据 | 用途 |
|---|---|
用户 SSH Key |
编辑者 clone / push 内容仓库。 |
Deploy Token |
Antora 只读获取私有仓库;项目级覆盖一个项目,Group 级覆盖该组的项目。 |
Runner authentication token |
Runner 向 GitLab 认证,通常是 |
原实验先为 ABB 使用项目 Deploy Token,加入 FANUC 后改为 Group Deploy Token。在 Group 的 Settings → Repository → Deploy tokens 创建只带 read_repository 权限的 Token,记录实际用户名和 Token。只有需要读取镜像仓库时才增加对应 registry 权限。
删除或撤销旧项目 Token 前,应先验证 Group Token 能读取所有目标仓库。Group Token 的读取范围更广,应限制使用者与有效期。
9.2. 修改远程内容源
将 playbook 中 content 替换为:
content:
sources:
- url: http://192.168.179.129:8181/robot-docs/robot-docs-abb.git
branches: [v1.0, v1.1]
- url: http://192.168.179.129:8181/robot-docs/robot-docs-fanuc.git
branches: [v1.0]
Token 不应写入 URL 并提交。原实验通过 GIT_CREDENTIALS 提供认证,下面用交互输入避免真实 Token 留在命令历史中:
cd ~/robot_docs_demo
read -r -p 'Deploy token username: ' ANTORA_GIT_USERNAME
read -r -s -p 'Deploy token: ' ANTORA_GIT_TOKEN
printf '\n'
GIT_CREDENTIALS="http://${ANTORA_GIT_USERNAME}:${ANTORA_GIT_TOKEN}@192.168.179.129:8181" \
npx antora --fetch --clean antora-playbook.yml
unset ANTORA_GIT_USERNAME ANTORA_GIT_TOKEN
用户名和 Token 如包含 URL 保留字符,应先按 URL userinfo 规则编码。默认 GitLab 生成的 Deploy Token 通常适用于该形式。若改用凭据文件,限制权限并放在仓库外,通过 GIT_CREDENTIALS_PATH 指定,避免提交到 Git。
Antora 自己负责仓库获取,不要假定命令行 Git 已登录就等于 Antora 已认证。参见 Antora 私有仓库认证。
验收:本地构建能生成 ABB 与 FANUC。若有疑问,可临时改名本地 ABB 目录,验证仍从远端构建,之后恢复目录。--fetch 刷新远端内容,--clean 清理输出,两者作用不同。
10. 阶段九:独立网站总控仓库 robot-docs-site
在 GitLab Group 中创建 Private *空*项目 robot-docs-site,检查 slug 正确。
在 WSL:
mkdir -p ~/robot_docs_site
cd ~/robot_docs_site
cp ~/robot_docs_demo/antora-playbook.yml .
cp ~/robot_docs_demo/package.json .
cp ~/robot_docs_demo/package-lock.json .
如果使用本地 UI bundle,也复制 ui/。创建 .gitignore:
node_modules/
build/
.cache/
*.log
.env
.git-credentials
此时总控仓库只保存构建配置与依赖锁定,不复制 ABB/FANUC 子仓库。node_modules/ 能从 lock 文件还原,build/ 是生成结果,二者不进入 Git。
npm ci
git init -b main
git config user.name "Your Name"
git config user.email "you@example.com"
git add .gitignore antora-playbook.yml package.json package-lock.json
git commit -m "Initial Antora site configuration"
git remote add origin robot-docs-gitlab:robot-docs/robot-docs-site.git
git push -u origin main
验收:GitLab 总控仓库只有站点配置、package 文件等,没有 node_modules 和 build。内容仓库和总控仓库各自拥有独立 Git 历史。
11. 阶段十:启动并注册 GitLab Runner
11.1. 在 GitLab 创建 Runner
进入 Site 项目的 Settings → CI/CD → Runners,创建 Project Runner(界面名称随版本可能变化):
-
Description:
antora-docker-runner。 -
Tags:
antora,docker,用逗号分隔,不能写成一个antora docker标签。 -
原实验勾选 Run untagged jobs;本文最终 CI 也显式写两个 tags。
-
实验初期不暂停;若启用 Protected,任务分支必须满足保护条件。
记录创建后显示的 glrt-… authentication token。新注册流程是在 GitLab 创建 Runner 后使用该 Token,不应把旧 registration token 和 --registration-token 流程混用。
11.2. 在 Ubuntu Server 启动 Runner 容器
sudo mkdir -p /srv/gitlab-runner/config
docker run -d \
--name gitlab-runner \
--restart always \
-v /srv/gitlab-runner/config:/etc/gitlab-runner \
-v /var/run/docker.sock:/var/run/docker.sock \
docker.1ms.run/gitlab/gitlab-runner:latest
docker exec -it gitlab-runner gitlab-runner register
交互输入:
| 提示 | 填写 |
|---|---|
GitLab instance URL |
|
Token(若询问) |
GitLab 刚创建的 authentication token |
Runner name |
antora-docker-runner |
Executor |
docker |
Default Docker image |
docker.1ms.run/library/node:22 |
按照实际版本提示填写;也可使用 GitLab 创建页给出的 register --url … --token … 命令,但不要把实际 Token 保存到脚本、聊天或教程里。
docker exec gitlab-runner gitlab-runner --version
docker exec gitlab-runner gitlab-runner verify
docker logs --tail 80 gitlab-runner
docker.sock 让 Runner 能通过宿主机 Docker 创建 Job 容器,不是 Docker-in-Docker。本实验不要求 Job 挂载这个 socket,也不要求 privileged = true。Runner 本身拥有强大的主机权限,应只用于可信项目。
config.toml 中保存实际认证 Token,不要把完整配置输出到公开日志。参见 Runner 注册文档。
验收:GitLab 显示 Online / Idle;Idle 表示在线等待任务。Project Runner 分配给 Site 即可,内容仓库仅使用 trigger job 时不需要执行脚本的 Runner。
12. 阶段十一:修复 helper image 与首次镜像下载
12.1. helper image 为什么必须能下载
Docker executor 启动业务镜像之前,使用 helper image 完成源码获取、缓存和 Artifact 上传下载。原实验 Runner 已在线,但 Job 卡在:
Using helper image:
registry.gitlab.com/gitlab-org/gitlab-runner/gitlab-runner-helper:x86_64-v19.3.3
Pulling docker image registry.gitlab.com/...
这是 GitLab Registry 拉取问题,不是 Node、Antora 或 CI script 的问题。
在 Ubuntu Server 查版本与架构,并预拉取 *匹配*的 helper:
docker exec gitlab-runner gitlab-runner --version
uname -m
docker pull docker.1ms.run/gitlab/gitlab-runner-helper:x86_64-v19.3.3
docker pull docker.1ms.run/library/node:22
x86_64-v19.3.3 是原实验值。若 Runner 为其他版本或 ARM,按实际 helper 标签替换,不要复制这个标签搭配不同版本 Runner。
12.2. 修改 config.toml
sudo nano /srv/gitlab-runner/config/config.toml
在现有 Runner 的 [runners.docker] 段内修改或添加,保留已生成的 URL、Token 等字段,不重复创建第二个段:
[runners.docker]
image = "docker.1ms.run/library/node:22"
helper_image = "docker.1ms.run/gitlab/gitlab-runner-helper:x86_64-v19.3.3"
pull_policy = "if-not-present"
privileged = false
volumes = ["/cache"]
docker restart gitlab-runner
if-not-present 优先使用本地存在的镜像,不会自动更新浮动标签。它适合此独立实验机的网络情况,长期运行应采用明确版本/摘要及可控更新流程。升级 Runner 时同步更新 helper;很多 Runner 配置能自动重载,此处重启是便于实验确认。
参见 Runner 高级配置。
验收:Job 日志显示已使用配置的 helper,之后开始拉取 Node。如果卡点转移到 Node 的下载,说明 helper 这一层已经通过。首次 Node 下载曾耗时较长,应观察日志和拉取进度,不能仅凭时间长判定挂死。
13. 阶段十二:第一个 CI Job
在 WSL 的 Site 仓库 创建 .gitlab-ci.yml:
stages: [test]
test-ci:
stage: test
image: docker.1ms.run/library/node:22
tags: [antora, docker]
script:
- echo "GitLab CI Runner is working."
- node --version
- npm --version
cd ~/robot_docs_site
git add .gitlab-ci.yml
git commit -m "Add initial GitLab CI test"
git push
进入 Build → Pipelines,打开这次提交的 Pipeline,再打开 test-ci 看日志。正常顺序是 Runner 领取任务、准备 Docker executor、helper、Node 镜像、获取代码、执行 script。
验收:日志打印 Node/npm 版本,出现 Job succeeded,Pipeline Passed。历史失败 Pipeline 不必删除;以本次提交为准。
14. 阶段十三:配置 CI 变量与 Antora 构建 Artifact
14.1. 保存只读认证变量
Site 项目 Settings → CI/CD → Variables:
| Key | 值 | 设置 |
|---|---|---|
ANTORA_GIT_USERNAME |
Group Deploy Token 实际用户名 |
可 Visible;关闭 Expand variable reference。 |
ANTORA_GIT_TOKEN |
Group Deploy Token |
Masked,支持时 Hidden;关闭 Expand variable reference。 |
实验中的分支若未保护,Protected 变量不会提供给相应任务。应使变量与分支保护策略一致:初期可按原实验不勾 Protected,稳定后保护 main 与需要发布的分支,再启用对应保护。不要为了解决缺变量,把 Token 写进 playbook。
14.2. 构建 Job
将测试配置替换成:
stages: [build]
build-docs:
stage: build
image: docker.1ms.run/library/node:22
tags: [antora, docker]
script:
- test -n "$ANTORA_GIT_USERNAME"
- test -n "$ANTORA_GIT_TOKEN"
- npm ci
- GIT_CREDENTIALS="http://${ANTORA_GIT_USERNAME}:${ANTORA_GIT_TOKEN}@192.168.179.129:8181" npx antora --fetch --clean antora-playbook.yml
- test -f build/site/index.html
- ls -la build/site
artifacts:
name: "robot-docs-site-$CI_COMMIT_SHORT_SHA"
paths:
- build/site/
expire_in: 7 days
提交后观察构建日志:
git add .gitlab-ci.yml
git commit -m "Build Antora site in GitLab CI"
git push
14.3. Artifact、仓库与网站的区别
仓库存的是 .adoc 和配置;Artifact 是 Job 执行结束前上传给 GitLab 的 build/site/ 成品包。Job 容器是临时的,没有 Artifact,构建结果会随着临时环境清理而失去。
在 build-docs 的 Job 页面,右侧 Job artifacts 下可以 Browse / Download;这些按钮不在项目仓库首页。Browse 便于核对生成文件,Download 下载成品包,Keep 可保留该次产物。expire_in 是过期配置,具体保留还受 GitLab “保留最近成功产物”等设置影响。
Artifact 不等于已经发布的网站,也不是 cache:Artifact 用于交付本次结果,cache 通常用于复用依赖、减少下载。
验收:构建成功,Artifact 中有 ABB 1.0、ABB 1.1、FANUC 1.0 和入口 index.html;此时还不能仅凭构建成功就认定 VM 的 8080 网站已更新。
15. 阶段十四:部署 Nginx 并验证目录挂载
在 Ubuntu Server:
sudo mkdir -p /srv/robot-docs-site
printf '<h1>Hello Robot Documentation!</h1>\n' | sudo tee /srv/robot-docs-site/index.html
docker pull docker.1ms.run/library/nginx:alpine
docker run -d \
--name robot-docs-nginx \
--restart always \
-p 8080:80 \
-v /srv/robot-docs-site:/usr/share/nginx/html:ro \
docker.1ms.run/library/nginx:alpine
docker ps
curl -I http://127.0.0.1:8080/
浏览器访问 http://192.168.179.129:8080,应看到测试标题。
8080:80 表示主机 8080 转发到容器 80;卷把主机目录作为 Nginx 的网页根目录;:ro 表示 Nginx 只能读取这个挂载。CI 或宿主机仍可写入同一目录。
Nginx 只处理请求并读取文件,不解析 AsciiDoc、不替代 Antora,也不执行 CI。更新静态网页通常不需要重启;修改 Nginx 配置才需要测试并 reload。GitLab 容器内部也有 Nginx,但它与这里的 robot-docs-nginx 是两个独立用途。
验收:VM 上长期运行 gitlab、gitlab-runner、robot-docs-nginx;Windows 能看到 VM 8080 测试页,关闭 WSL 预览服务不影响它。
16. 阶段十五:让 CI 自动部署到 Nginx
16.1. 让 Job 可写发布目录
在 Ubuntu Server 修改 Runner 的 config.toml 中原有 volumes:
volumes = [
"/cache",
"/srv/robot-docs-site:/srv/robot-docs-site"
]
docker restart gitlab-runner
该设置决定 Job 容器 的挂载,而不是只给 Runner 管理容器增加卷。目录映射最终是:
宿主机 /srv/robot-docs-site
├─ Nginx /usr/share/nginx/html(只读)
└─ Job /srv/robot-docs-site(可写)
本实验应将有发布目录权限的 Runner 限制给可信 Site 项目;否则使用这个 Runner 的其他 Job 也能改网站目录。
16.2. 完整 Site CI 配置
将 Site 的 .gitlab-ci.yml 改为以下完整版本。沿用原实验的直接复制部署,并增加入口检查与部署互斥:
stages:
- build
- deploy
default:
image: docker.1ms.run/library/node:22
tags: [antora, docker]
build-docs:
stage: build
script:
- test -n "$ANTORA_GIT_USERNAME"
- test -n "$ANTORA_GIT_TOKEN"
- npm ci
- GIT_CREDENTIALS="http://${ANTORA_GIT_USERNAME}:${ANTORA_GIT_TOKEN}@192.168.179.129:8181" npx antora --fetch --clean antora-playbook.yml
- test -f build/site/index.html
artifacts:
name: "robot-docs-site-$CI_COMMIT_SHORT_SHA"
paths:
- build/site/
expire_in: 7 days
deploy-docs:
stage: deploy
resource_group: robot-docs-production
needs:
- job: build-docs
artifacts: true
script:
- test -f build/site/index.html
- test -d /srv/robot-docs-site
- mountpoint -q /srv/robot-docs-site
- test -w /srv/robot-docs-site
- find /srv/robot-docs-site -mindepth 1 -maxdepth 1 -exec rm -rf -- {} +
- cp -a build/site/. /srv/robot-docs-site/
- test -f /srv/robot-docs-site/index.html
rules:
- if: '$CI_COMMIT_BRANCH == "main"'
environment:
name: production
url: http://192.168.179.129:8080
needs: artifacts: true 将 build-docs 的产物下载到部署 Job,两个 Job 不共享临时工作目录。rules 限制只有 main 部署;environment 登记部署环境,不会自动启动服务器。resource_group 防止本项目的部署 Job 同时复制目录,但不会自动保证所有排队 Pipeline 按内容新旧顺序发布。
清理命令会删除指定发布目录中的旧网站,必须确认固定路径是专用发布目录。mountpoint 检查用于阻止未正确挂载时向 Job 内部普通目录误部署。该方式不是原子发布:复制期间可能短暂缺文件,复制失败也可能留下不完整网站。构建失败时部署不会运行,旧网站保留;不能把这一性质扩展为“所有部署失败都能保留旧网站”。正式环境可进一步采用 release 目录、原子切换和回滚方案。
|
cp -a build/site/. 包含隐藏文件,避免 build/site/* 漏复制。Node 镜像默认以 root 运行时通常能写入;若自定义非 root 用户,需按实际 UID/GID 配置目录权限,不建议以 chmod 777 掩盖问题。
提交与验证:
cd ~/robot_docs_site
git add .gitlab-ci.yml
git commit -m "Deploy Antora site to Nginx"
git push
验收:Build 和 Deploy Passed;VM 8080 的测试标题变成真正 Antora 页面;/abb/1.1/network.html 和 /fanuc/1.0/index.html 可访问。无需重启 Nginx。
17. 阶段十六:内容仓库更新触发 Site Pipeline
17.1. 在 ABB v1.1 添加触发 Job
在 WSL:
cd ~/robot_docs_demo/abb
git switch v1.1
nano .gitlab-ci.yml
先用独立配置理解触发机制:
stages: [trigger]
trigger-site-build:
stage: trigger
trigger:
project: robot-docs/robot-docs-site
branch: main
strategy: mirror
rules:
- if: '$CI_COMMIT_BRANCH =~ /^v[0-9]+\.[0-9]+$/'
trigger 是 GitLab 调度的多项目触发任务,不是运行 curl 的脚本 Job,因此不需要 Docker 镜像或 Runner tags。它以触发 Pipeline 用户的权限创建下游 Pipeline;该用户必须有权限在 Site 的 main 上运行 Pipeline。Deploy Token 只解决 Antora 仓库读取,不能替代这个用户权限。
strategy: mirror 让上游任务等待下游并镜像成功/失败状态,要求 GitLab 18.2+;较旧实例可按其版本使用 depend,语义并不完全相同,需参考对应版本文档。本规则只匹配 v1.0、v1.1 等分支,不匹配 main、v1.0.1 或 Tag。
git add .gitlab-ci.yml
git commit -m "Trigger site pipeline from ABB version branch"
nano modules/ROOT/pages/network.adoc
在 network.adoc 增加:
== 自动发布测试
本段内容通过 GitLab CI/CD 自动构建并部署。
git add modules/ROOT/pages/network.adoc
git commit -m "Verify ABB automatic publication"
git push
验收:ABB Pipeline 的 trigger job 指向 Site 下游 Pipeline,Site Build/Deploy 成功,刷新 Nginx 页面可见新段落。检查 Site playbook 确实包含被更新的分支,否则触发成功也不会收录该分支。
18. 阶段十七:将触发配置覆盖 ABB 1.0 和 FANUC
18.1. ABB 分支间同步与 cherry-pick
先确定待同步提交只包含目标 CI 配置,避免把 ABB 1.1 的正文和 version 一并带到 1.0:
cd ~/robot_docs_demo/abb
git status
git log --oneline -- .gitlab-ci.yml
git show --stat <待同步提交SHA>
git switch v1.0
git cherry-pick <待同步提交SHA>
尖括号处替换为实际提交 SHA;不要原样执行占位符。
原实验出现 modify/delete 冲突:
CONFLICT (modify/delete): .gitlab-ci.yml deleted in HEAD
and modified in 94b84e6
当前 v1.0 没有文件,但引入提交修改了文件,Git 无法替你决定保留还是删除。目标是给 v1.0 增加 CI,因此检查工作区已有文件并选择保留:
git status
cat .gitlab-ci.yml
git add .gitlab-ci.yml
git cherry-pick --continue
git push
如目标确实是删除该文件,使用 git rm .gitlab-ci.yml 后 continue;如果选错提交或想撤销本次操作,使用 git cherry-pick --abort。普通内容冲突需要手工编辑,删除 <<<<<<<、=======、>>>>>>> 标记后再 add/continue。不要在未解决冲突时继续创建其他提交。
只同步单文件时也可在确认没有未保存修改后,使用 git restore --source=v1.1 — .gitlab-ci.yml,再创建一个明确的新提交;这样不必引入混合提交。
18.2. FANUC 加入触发
FANUC 的 v1.0 增加同样的触发配置,提交后在其首页增加自动发布验证段落并 push。
cd ~/robot_docs_demo/fanuc
git switch v1.0
nano .gitlab-ci.yml
git add .gitlab-ci.yml
git commit -m "Trigger documentation site from FANUC"
git push
验收:ABB v1.0、ABB v1.1、FANUC v1.0 各自更新能触发 Site。发布三个版本依赖 playbook 明确列出三个来源,不是给任何分支 push 都会自动加入站点。
19. 阶段十八:统一共享 CI 模板
19.1. Site 创建共享模板
在 WSL 的 Site 仓库:
cd ~/robot_docs_site
mkdir -p ci
nano ci/trigger-site.yml
ci/trigger-site.yml:
stages:
- trigger
trigger-site-build:
stage: trigger
trigger:
project: robot-docs/robot-docs-site
branch: main
strategy: mirror
rules:
- if: '$CI_COMMIT_BRANCH =~ /^v[0-9]+\.[0-9]+$/'
git add ci/trigger-site.yml
git commit -m "Add shared documentation trigger CI template"
git push
Site 自己的根 .gitlab-ci.yml 仍是 Build/Deploy 配置,不引用这个触发模板,避免触发自身形成循环。
19.2. 内容仓库仅保留 include
将 ABB 的 v1.0、v1.1 和 FANUC v1.0 中 .gitlab-ci.yml 改为:
include:
- project: robot-docs/robot-docs-site
ref: main
file: /ci/trigger-site.yml
逐个分支提交 push。各内容仓库无需再复制 trigger 的完整逻辑。
include:project 在创建 Pipeline 时从指定项目读取 YAML,用户必须能访问私有模板项目。ref: main 会使用当时 main 的模板;模板修改不会主动重跑所有内容 Pipeline,下一次内容更新才使用新模板。长期稳定使用可固定模板 Tag 或 SHA,升级时有计划地更新引用。
本模板声明 stages: [trigger] 适用于原实验的纯文档内容仓库;若以后加入其他 build/test job,需统一规划 stages,不能忽略 include 合并后阶段覆盖的问题。可在 GitLab CI Editor 的 Validate / 合并配置视图检查实际展开结果。
验收:三个版本分支都使用 include,内容修改仍能触发 Site Build/Deploy;Site Pipeline 不反向触发内容仓库。共享模板成功是原对话已经完成的实验终点。
20. 可选扩展:无版本门户首页
原对话提出了实验 19 首页方案,但没有完成后的验收截图。以下可选操作与已完成的自动发布链路分开。
Site 仓库新增 antora.yml:
name: home
title: 机器人技术文档中心
version: ~
nav:
- modules/ROOT/nav.adoc
新增 modules/ROOT/pages/index.adoc:
= 机器人技术文档中心
== 选择机器人品牌
* xref:abb::index.adoc[ABB 机器人文档]
* xref:fanuc::index.adoc[FANUC 机器人文档]
新增 modules/ROOT/nav.adoc:
* xref:index.adoc[文档中心首页]
* xref:gitlab-antora-ci-nginx-guide.adoc[从零搭建机器人技术文档中心]
playbook 改为 start_page: home::index.adoc,content.sources 增加:
- url: .
branches: HEAD
此本地来源读取当前 Site checkout(仓库必须已有提交),适用于本地与 CI;也可按原对话使用 Site 的远端 Git URL 和 main。保留 ABB/FANUC 两个来源。version: ~ 是无版本组件,页面路径不包含版本段;跨组件 xref 由 Antora 解析实际 URL。
先本地构建验收,再提交 push。首页方案、全文搜索、产品导航、UI 定制与 HTTPS 可逐项扩展,不能假定它们已经由当前模板自动实现。
21. 把本教程加入当前服务并验证功能
21.1. 最短接入方法:加入已存在内容组件
不必先完成 home 组件,可把本包放到 已被 playbook 读取的 ABB v1.1 中:
-
在内容仓库切到 v1.1,并确认工作区无未提交冲突。
-
复制包内
modules/ROOT/pages/gitlab-antora-ci-nginx-guide.adoc到同名目录。 -
复制包内
modules/ROOT/images/tutorial/整个目录到同名目录。 -
在现有
modules/ROOT/nav.adoc末尾增加下面这一行,不要覆盖原导航。
* xref:gitlab-antora-ci-nginx-guide.adoc[从零搭建机器人技术文档中心]
-
提交页面、图片和导航,push 后观察内容 Pipeline → Site Pipeline → Nginx。
git add modules/ROOT/pages/gitlab-antora-ci-nginx-guide.adoc modules/ROOT/images/tutorial modules/ROOT/nav.adoc
git commit -m "Add GitLab Antora CI Nginx tutorial"
git push
包内 README 和 examples 是接入说明及配置参考,不要求复制到页面目录。不要为了导入本文覆盖自己的 .gitlab-ci.yml、playbook 或 antora.yml。
21.2. 验收表
| 检查 | 预期 |
|---|---|
上游 Pipeline |
include 成功解析,trigger job 创建 Site 下游 Pipeline。 |
Site build-docs |
npm ci、Antora 成功,日志无本文图片缺失错误。 |
Artifact |
包含教程 HTML 及 |
Site deploy-docs |
下载同一 build-docs 产物并完成部署。 |
浏览器 |
左侧出现教程入口,正文、表格、代码块、提示框和图片正常。 |
直接访问 |
ABB v1.1 接入时路径为 |
版本隔离 |
仅上传到 v1.1 时,v1.0 不会凭空拥有该页;需要另行同步。 |
服务持续性 |
关闭 WSL 临时预览后,VM 的 Nginx 网站仍可访问。 |
22. 典型故障与逐层排查
22.1. Docker 源或镜像仓库连接失败
curl: (35) Connection reset by peer 后又出现 chmod: cannot access docker.asc,先处理密钥下载失败;后面的文件不存在是连锁错误。不要继续配置一个引用不存在密钥的 APT 源。切换 Ubuntu 仓库安装路线前检查 /etc/apt/sources.list.d/,禁用自己刚添加且无效的 Docker 源,不要误删系统 Ubuntu 源。
Docker Hub 拉取失败:先检查 DNS、HTTPS,再检查 daemon 日志。ping 成功不代表 HTTPS Registry 可达。shell 的代理环境变量也不自动等于 Docker daemon 已使用代理;必要时按 Docker 服务的代理配置方式设置并验证。
GitLab Registry 拉取失败:观察是否是 helper image;Docker Hub 镜像代理可用不代表 GitLab Registry 可达。使用匹配 Runner 版本和架构的 helper 镜像,确认本地镜像名与配置完全一致。
22.2. Runner 注册失败或任务 Pending
docker ps --filter name=gitlab-runner
docker logs --tail 100 gitlab-runner
docker exec gitlab-runner gitlab-runner verify
curl -I http://192.168.179.129:8181/users/sign_in
403 或 Token 验证失败:确认使用新 authentication token、Runner 未删除、地址指向正确实例。不要重复创建多个 Runner 掩盖问题。
Pending:检查 Runner Online、是否分配给项目、是否暂停、Job tags 是否都匹配、是否允许 untagged,以及 Protected Runner 是否允许当前分支。antora docker 单标签与 antora,docker 两标签不同。
Job 已运行但长期卡在 Preparing:查看 helper 或业务镜像拉取日志;这不是 Pending。Runner 的 verify 仅证明认证通信,不证明整个 Docker executor 能完成 Job。
22.3. 私有仓库认证、变量与多项目权限
HTTP Basic: Access denied:检查 Deploy Token 用户名、过期状态、read_repository、Group 范围和 URL。CI 中变量为空:检查变量拼写、Environment scope、Protected 与分支保护条件。避免打开 set -x 或打印 GIT_CREDENTIALS。
downstream pipeline cannot be created:确认 project 路径、main 存在,触发用户有权限,目标分支保护允许,且 Site 的 workflow/rules 没有排除 CI_PIPELINE_SOURCE == "pipeline"。跨项目 include 失败还要核对模板 file/ref 和读取权限。API Job Token allowlist 与用户权限是不同机制;本实验的原生 trigger 不需要先添加一个 curl API Token。
网站内容未更新:确认内容 commit 已 push 到 playbook 列出的分支;Site Job 使用 --fetch;检查 Site Pipeline 是否真的 deploy;最后才处理浏览器缓存。不要只看上游绿色就推断最终 HTML 一定包含目标内容。
22.4. YAML、组件与版本错误
site.content.sources not declared:content 错误缩进到了 site 下;它应是顶层键。ui.bundle.url must be String:检查 bundle/url 的层级和 URL 是否变成映射。
重复组件版本:检查每个分支 antora.yml 的 name/version 组合。分支名带 v 不代表输出 URL 一定带 v。原 /abb/v1.0/ 残留属于旧输出时,用 --clean;若部署时仅追加复制未删除旧文件,发布目录也可能残留。
22.5. Artifact 不存在或无法传递
No files to upload:检查 output.dir 是否为 build/site、Job 工作目录、Antora 是否成功,artifacts.paths 必须相对项目工作目录。不要把 output 改为 public 后还继续上传 build/site。
部署 Job 找不到 build/site:检查 needs 的 job 名和 artifacts: true,确认产物未过期。不同 Job 的临时目录独立存在,cache 不替代 Artifact 交付。
仓库首页没有 build/site 是预期行为,去 build-docs Job 的 Job artifacts 查看。Artifact 被删除不等于 Nginx 中已部署文件也自动删除;两者是不同存储。
22.6. Nginx 拒绝连接、403、404 与权限
在 Ubuntu Server:
docker ps --filter name=robot-docs-nginx
docker port robot-docs-nginx
docker logs --tail 80 robot-docs-nginx
docker exec robot-docs-nginx nginx -t
docker exec robot-docs-nginx ls -la /usr/share/nginx/html
ls -la /srv/robot-docs-site
curl -I http://127.0.0.1:8080/
sudo ss -lntp
sudo ufw status
ERR_CONNECTION_REFUSED:检查容器与端口映射是否存在,网址是否指向正确机器;Windows localhost、WSL localhost 与 VM IP 不应混淆。如果 VM 本机可访问而 Windows 不可访问,检查 VMware 网络、地址变化与防火墙。若有 UFW,按可信局域网范围开放 8080/8181/2222,并保留管理 SSH 的规则。
403:检查网页入口文件、目录遍历权限与文件读取权限;不要仅确认目录存在。404:检查请求版本路径、实际 HTML 文件、部署是否成功。临时 Python 服务显示目录列表时,通常是提供服务的根目录错误。
Deploy Passed 但网站仍旧:先确认 Job 挂载和 Nginx 挂载指向同一个主机路径,检查服务器上文件时间与内容;最后使用强制刷新排除客户端缓存。写入失败时应核对 UID/GID、挂载的 rw/ro 和磁盘空间。
22.7. 磁盘空间与重启
df -h
docker system df
sudo du -sh /srv/gitlab/data /srv/gitlab/logs /var/lib/docker
根分区不足会导致镜像解压、GitLab 数据写入、Artifact 上传与部署失败。先判断数据类型和保留策略,再清理;不要执行带 volumes 的全局 prune 删除持久化数据。LVM 有空闲空间并不代表根文件系统已经扩容,扩容前核对实际逻辑卷名并备份。
服务器重启后检查三个容器是否恢复、IP 是否变化。若 IP 变化,external_url、Runner URL、playbook、凭据匹配地址和 environment URL 都需要一致调整。
23. 最终目录与日常工作流
WSL
~/robot_docs_demo/
├── abb/ 独立 Git 内容仓库
│ ├── antora.yml
│ ├── .gitlab-ci.yml include 共享模板
│ └── modules/ROOT/
│ ├── nav.adoc
│ ├── pages/
│ └── images/
└── fanuc/ 独立 Git 内容仓库
~/robot_docs_site/ 独立 Git 网站总控仓库
├── .gitignore
├── .gitlab-ci.yml build + deploy
├── antora-playbook.yml
├── package.json
├── package-lock.json
├── ci/trigger-site.yml
├── node_modules/ 不提交
└── build/site/ 不提交,保存 Artifact
Ubuntu Server
/srv/gitlab/{config,logs,data}
/srv/gitlab-runner/config/config.toml
/srv/robot-docs-site/ Nginx 读取的发布目录
日常内容更新:切换正确版本分支 → 编辑 .adoc 与图片 → 检查差异 → commit/push → 观察上游/下游 Pipeline → 浏览器验收。增加新品牌时,创建新组件和内容仓库,配置版本与 include,并在 Site playbook 增加来源;仅复制 CI 模板不会自动把新品牌收录进网站。
修改站点依赖时同时更新 package.json 与 package-lock.json;修改共享模板时先验证展开配置;跨分支同步时确保不误改组件版本。失败构建先查看首个错误,不要被后续缺文件日志带偏。