GitHub Actions 为什么慢:别让每个作业从头重建环境
一个慢的 GitHub Actions 作业,大部分时间都花在第一个测试运行之前。安装 Node、下载依赖、构建 Docker 镜像:每次推送都是同样的几分钟,而团队里总有人在等那个绿色的勾。按分钟计费时,这几分钟你还得付钱。
Skipbox 是一个在作业之间保留机器的 GitHub Actions 运行器,一个作业安装的东西,下一个作业时仍在磁盘上。只改一行 runs-on: skipbox,作业就在你的专属机器上运行,每月固定 $39,分钟数不限。
每个作业都从空白虚拟机开始
GitHub 托管的运行器为每个作业准备一台新的虚拟机。上一个作业下载或构建的东西都不在上面,所以每个作业都在重建同样的状态:
| 步骤 | GitHub 托管的运行器 | Skipbox |
|---|---|---|
| 安装 Node、Python、Java | 下载工具链 | 从上一个作业的工具缓存中找到它 |
| 安装依赖 | 下载并解压缓存归档;未命中时,从包仓库完整下载 | 从磁盘读取包管理器的缓存 |
| 构建 Docker 镜像 | 没有任何层,每一步都重新构建 | 复用上一次构建的层 |
| 运行测试 | 私有仓库的 ubuntu-latest 为 2 个 CPU | 4 vCPU 起 |
前三行没有产出任何新东西,只是把机器恢复到昨天的状态。
GitHub 的缓存能缓解这个问题,却改变不了它。每个仓库只有 10 GB,7 天内没有作业读取的条目会被删除,新的功能分支也无法读取另一个功能分支的缓存。即使命中,每次运行仍要下载并解压一个归档。
等待让你付出什么
假设每个作业的准备工作要 3 分钟,你的团队每天运行 100 个作业。那就是每天 300 分钟的运行器时间花在把机器恢复原状上,每个拉取请求都要等它那一份。审查开始得更晚,合并落地得更晚,工程师在等待时转去做别的事。
按分钟计费时,这些分钟都会出现在账单上。以 4 vCPU 运行器,按每月分钟数:
| 每月分钟数(4 vCPU) | GitHub | Skipbox S | 每月节省 |
|---|---|---|---|
| 1万 | $102 | $39 | $63 |
| 2万 | $222 | $39 | $183 |
| 3万 | $342 | $39 | $303 |
GitHub 的金额是减去 GitHub Team 包含的用量后的账单。把你自己的分钟数填进首页的费用计算器,无需登录。
而运行次数只会增加:
- AI 编程智能体:智能体每次推送都会启动 CI。等待时间和账单都随推送增长,而不是随人数增长。
- 更多测试:一套端到端测试或一个矩阵,在它新增的每个作业里都要重复一遍准备工作。
- 预算:用 GitHub 预算封顶账单,作业会在月中不再启动,合并也随之停下。
自己提速是一个项目
继续用 GitHub 托管的运行器并让它变快,意味着要承担这样的工作:
- 用锁文件的哈希作为缓存键,并反复调整
restore-keys直到命中 - 加上 buildx,用
cache-to导出 Docker 的缓存,仍在同样的 10 GB 之内 - 拆分测试,而每个分片都要重复准备工作,计费分钟数反而上升
- 或者自己运行自托管运行器:准备机器、更新操作系统、在作业之间清理,宕机时还要修好它
这些都是在绕开一台什么都记不住的机器。Skipbox 保留机器,所以这些都不需要。
用 Skipbox 后有什么不同
准备好的环境留在磁盘上。你的作业在你账号专属的机器上运行,机器在作业之间一直保留。Docker 镜像、层和构建缓存;npm、pip、Gradle 等的包缓存;setup-node 等操作安装的工具。缓存空间至少是 GitHub 的 7 倍,没有 7 天后过期,也没有分支限制。
更大的机器,固定的价格。编译器和测试运行器按每个核心启动一个工作进程,所以核数越多,受 CPU 限制的步骤就越短。
| 套餐 | 机器 | 价格 |
|---|---|---|
| S | 4 vCPU · 16 GB | 每月 $39 |
| M | 8 vCPU · 16 GB | 每月 $79 |
| L | 16 vCPU · 32 GB | 每月 $149 |
每个套餐的分钟数都不限。Skipbox 的作业不消耗 GitHub 分钟数,所以 GitHub 预算从不会让它们停下。
无需照看机器。Skipbox 负责准备机器、更新操作系统和工具、在每个作业后清理、做健康检查,并重建检查失败的机器。
切换只需改一行
jobs:
build:
runs-on: skipbox # was ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: npm ci && npm test
- 使用 GitHub 登录 Skipbox。
- 安装 Skipbox GitHub 应用,并选择仓库。
- 修改
runs-on并推送。
第一个作业安装的东西,第二个作业时就在磁盘上。
安全
- 这台机器只属于你的账号,不会运行其他公司的作业。
- 每个作业结束后,运行器的凭据、进程和容器都会被清除。从 2026年11月13日起,你的检出目录及其构建输出(Cargo 的
target/)会留在你的专属机器上,供之后的作业使用;开启“每个作业用新虚拟机”后,每个作业都在一台新机器上运行。 - 没有写入权限的人提交的代码(例如来自复刻的拉取请求)在一台新的一次性机器上运行。
详情见作业如何隔离。
用你最慢的作业试试
试用免费,为期 7 天 或 3,000 作业分钟,以先到者为准,无需绑卡。把最慢的作业改为 runs-on: skipbox,连续运行两次,再把各步骤的耗时与 GitHub 上的并排对比。
常见问题
GitHub Actions 为什么这么慢?
GitHub 托管的运行器上,每个作业都在一台新的虚拟机上启动,上一次运行的东西一样都没有,所以在测试开始前,它要下载工具、重新安装依赖、重新构建 Docker 镜像。Skipbox 在你账号专属的机器上运行作业,并把这些状态保留在磁盘上,下一个作业从上一个作业结束的地方接着开始。
已经加了 actions/cache,工作流为什么还是慢?
即使缓存命中,每个作业仍要下载并解压一个归档,因为虚拟机每次都是新的。而且 GitHub 的缓存每个仓库只有 10 GB,7 天未使用的条目会被删除,也无法从同级分支读取。在 Skipbox 上,包缓存和 Docker 层已经在机器的磁盘上,无需管理缓存键。
怎样让 GitHub Actions 里的 Docker 构建更快?
把上一次构建的层交给这次构建。在 GitHub 托管的运行器上,这意味着用 buildx 导出缓存、每次运行再导入,而且同样受 10 GB 的限制。在 Skipbox 上,Docker 的镜像和构建缓存在作业之间留在机器上,所以 docker build 会自己复用这些层。
用 Skipbox 需要重写工作流吗?
不需要。Linux 作业只需把 runs-on 改为 skipbox。机器运行 Ubuntu 24.04,带有 Docker、Node.js 和 Python,你的步骤和操作原样运行。
能免费用我自己的慢作业试试吗?
能。试用为期 7 天 或 3,000 作业分钟,以先到者为准,无需绑卡。把最慢的作业改为 runs-on: skipbox,连续运行两次,再把各步骤的耗时与 GitHub 上的对比。
更新于 2026年11月11日