csdn-enterpriseGitLab Runner docker pull 慢:并行流水线镜像拉取排查

1. 问题现象

团队并行提交多个 MR 后,GitLab Runner 队列开始变长。业务测试本身没有明显变慢,但 job 卡在环境准备阶段:

text 复制代码
Preparing environment
Using Docker executor with image node:20 ...
Pulling docker image node:20 ...
context deadline exceeded

这类问题不要一上来就改测试脚本。先确认到底是测试执行慢,还是 runner 在拉镜像时已经被拖住。

本文记录一套排查顺序:从 runner executor、基础镜像、service 镜像、pull policy、镜像源和本地缓存逐层检查。

2. 环境示例

text 复制代码
GitLab Runner: Docker executor
Runner 节点:Linux / Docker Engine
并发场景:多个分支同时跑单测和集成测试
常见镜像:node:20、python:3.12、postgres:16-alpine、redis:7、ghcr.io/.../test-runner

如果是 GitHub Actions 自建 runner,也可以参考同样的排查思路。核心都是:job 开始前要先把容器镜像拉到 runner 节点。

3. 先区分 pending、preparing 和 script

看 job 卡在哪一段:

阶段 现象 方向
pending 没有 runner 接任务 runner 数量、tag、并发数
preparing 已分配 runner,正在拉镜像 Docker、镜像源、DNS、缓存
script 脚本已经执行 测试耗时、依赖缓存、数据库初始化

如果日志里出现 Pulling docker image,说明至少有一部分时间花在镜像拉取。

4. 在 runner 节点手工验证

进入 runner 节点,不通过 CI,直接拉关键镜像:

bash 复制代码
docker pull node:20
docker pull python:3.12
docker pull postgres:16-alpine
docker pull redis:7-alpine

如果团队使用 GHCR、MCR、Quay:

bash 复制代码
docker pull ghcr.io/your-org/test-runner:latest
docker pull mcr.microsoft.com/playwright:v1.44.0-jammy
docker pull quay.io/skopeo/stable:latest

常见错误包括:

text 复制代码
context deadline exceeded
i/o timeout
connection reset by peer
TLS handshake timeout

这时问题优先看 runner 节点的网络、DNS、镜像源和代理配置。

5. 配置 Docker 镜像源

可以先用 1ms-helper 处理 Docker 场景:

bash 复制代码
curl -sSL https://static.1ms.run/1ms-helper/install.sh | bash
sudo 1ms-helper config:docker

Linux Docker 的基础配置可以参考:

json 复制代码
{
  "registry-mirrors": ["https://docker.1ms.run"],
  "dns": ["8.8.8.8", "114.114.114.114"]
}

然后重启 Docker:

bash 复制代码
systemctl daemon-reload
systemctl restart docker
systemctl status docker

再验证:

bash 复制代码
docker pull docker.1ms.run/library/node:20
docker pull docker.1ms.run/library/postgres:16-alpine
docker pull ghcr.1ms.run/your-org/test-runner:latest

说明:毫秒镜像在这里解决的是多源镜像入口和拉取稳定性这一层,不替代 runner 并发、测试拆分和依赖缓存。

6. 检查 GitLab Runner pull policy

GitLab Runner Docker executor 支持 pull_policy。如果每次 job 都强制拉镜像,runner 本地缓存就很难发挥作用。

示例:

toml 复制代码
[[runners]]
  executor = "docker"
  [runners.docker]
    image = "docker.1ms.run/library/node:20"
    pull_policy = ["if-not-present", "always"]

实际生产里不要简单照抄。建议按镜像类型区分:

镜像类型 建议
高频基础镜像 固定 tag,配合本地缓存
安全扫描镜像 固定版本,关键场景考虑 digest
数据库 service 镜像 固定小版本,减少重复拉取
团队自建镜像 使用内部版本号,不长期依赖 latest

7. 检查 .gitlab-ci.yml

一个常见配置:

yaml 复制代码
test:
  image: docker.1ms.run/library/node:20
  services:
    - name: docker.1ms.run/library/postgres:16-alpine
      alias: postgres
  script:
    - npm ci
    - npm test

如果每个 job 都启动独立数据库 service,且并发很多,镜像拉取、容器启动、数据库初始化都会叠加。需要结合缓存、测试拆分和服务复用一起看。

8. 固定关键镜像版本

近期 Docker 官方复盘过 Trivy 和 KICS 相关的供应链攻击事件。CI 里常见的扫描器、构建器、测试工具镜像,不建议长期用模糊的 latest。

至少做到:

  • 生产发布链路用明确 tag。
  • 关键扫描和构建镜像记录 digest。
  • 基础镜像升级走 MR,而不是静默变化。
  • runner 节点定期清理,但不要把高频镜像缓存清得太干净。

Docker 支持按 digest 拉取镜像,例如:

bash 复制代码
docker pull alpine@sha256:<digest>

Digest 不是为了让镜像拉得更快,而是为了让 CI 结果更可复现。

9. 排查清单

检查项 命令/位置
runner 是否接任务 GitLab job 状态、runner tag
是否卡在镜像 job 日志里的 Pulling docker image
Docker 是否正常 systemctl status docker
DNS 是否异常 1ms-helper check:dns
基础镜像能否拉取 docker pull node:20
多源镜像能否拉取 docker pull ghcr.io/...
pull policy 是否合适 config.toml
service 镜像是否过多 .gitlab-ci.yml

总结

CI 并行构建变慢时,不要只看测试脚本。runner 的镜像拉取阶段经常是隐藏瓶颈。

我的处理顺序是:

  1. 看 job 卡在 pending、preparing 还是 script。
  2. 在 runner 节点手工拉基础镜像和 service 镜像。
  3. 配置 Docker 镜像源并验证多源镜像入口。
  4. 检查 pull_policy 和本地缓存。
  5. 固定关键工具镜像版本,必要时记录 digest。

这样才能把"测试慢"和"runner 拉镜像慢"分开处理。

相关推荐
镜子AI7 小时前
镜子AI 技术复盘:三条自动化链路上的“停止条件“设计
运维·人工智能·自动化
tianyuanwo7 小时前
NetBox 数据库详解:当“关系型数据库”被装进一个网络运维的领域模型里
运维·数据库·netbox
螺蛳粉 螺蛳粉8 小时前
第 05 篇:etcd 深入:Raft 共识、watch 机制与快照备份恢复实战(底座认知 05)
docker·云原生·容器·kubernetes·etcd·分布式存储·kube-apiserver
知已难寻9 小时前
03 · OpenStack的计算管理 Nova
运维·服务器·开发语言·云原生·云计算·openstack·开源软件
huainingning10 小时前
Windows syslog日志服务器搭建与模拟器对接
运维·服务器·智能路由器
say_fall10 小时前
【Linux系统编程】Ext 文件系统:磁盘与存储、文件与目录、现代计算机究竟如何寻找文件
linux·运维·服务器·数据库·c++
wacsii11 小时前
【Linux进程(一)】Linux 进程初探:操作系统如何管理进程?fork() 为什么返回两次?
linux·运维·服务器
相思难忘成疾11 小时前
从零搭建 Kubernetes 1.30 集群:kubeadm 部署一主多从实战(RHEL 9.3 + Docker + flannel)
linux·运维·kubernetes
PellyKoo11 小时前
【docker】cifs卷改smb密码后容器起不来的解决方法
运维·docker·容器
时早玖沐11 小时前
放弃 QQ 官方机器人:用 SnowLuma + AstrBot 自建 QQ 机器人
docker·开源·agent