首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >用 Docker 私有化部署 GitHub Actions Runner(Runner Fleet)

用 Docker 私有化部署 GitHub Actions Runner(Runner Fleet)

作者头像
soulteary
发布2026-03-04 16:27:26
发布2026-03-04 16:27:26
10
举报

最近把我折腾 GitHub self-hosted runner 的一些经验,整理成了一个开源小工具 Runner Fleet(千帆)。它的目标很简单,把 Runner 当作服务来管,而不是当作一堆目录来管。

我希望它能少点手工、少点踩坑,把 1~5 台机器上自托管 Runner 的部署、扩容、维护,收敛成一套可复用的流程。前期小规模好上手,后面要提高并发度、提升利用率、扩大吞吐,也不至于失控。

写在前面

在私有化环境里跑 GitHub Actions,自托管 Runner 往往不是难在跑起来,而是难在长期稳定地管起来。

一开始你可能只是手工执行几次 config.sh(GitHub Actions Runner 的配置脚本),把 Runner 挂到某个 repo 或 org 上。 但当你同时维护多个 Runner、多个标签、多个仓库,并且把它们跑在内网宿主机上之后,问题会很快集中爆发

  • • Token 分散在不同地方,过期、复用、权限范围都要反复确认
  • • 宿主机或容器重启后,Runner 不一定能自动恢复,workflow 卡在 queued 等待可用 runner
  • • Runner 看起来还在,但就是不接单,排错要同时翻目录、看进程、对照 GitHub 页面
  • • 多 Runner 共机后环境互相污染,一个任务改了环境,另一个任务跟着中招
  • • Docker 任务与非 Docker 任务边界混乱,不该碰 Docker 的 job 也能碰到,反过来该用 Docker 的又跑不起来
Runner Fleet - 开源 GitHub Runner 私有化部署方案
Runner Fleet - 开源 GitHub Runner 私有化部署方案

Runner Fleet - 开源 GitHub Runner 私有化部署方案

所以我写了一个开源项目 soulteary/runner-fleet[1] 如果你也在用 self-hosted runner 跑 CI/CD,欢迎来试试、提 issue 或 PR。如果确实帮你省了时间,也欢迎一键三连。

Runner Fleet 做的事情很明确:提供一个轻量的 Web 管理面,把 Runner 的安装、注册、启停、编辑、状态聚合,以及自愈巡检,收拢成一套可重复的工程流程。

同时它提供两种运行模式:既可以在宿主机上直接跑多个 Runner(非容器模式),最大化复用宿主机环境;也可以做到一 Runner 一容器(容器模式),在同一台机器上通过多个容器做环境隔离,方便你在私有化环境里按需选择。

构建一套可复用的使用范式

自托管 Runner 真正容易失控的根源不是规模,而是缺少一套稳定范式。

我更推荐把 Runner 的拆分逻辑从按仓库改成按职责,让每个 Runner 的环境边界足够清晰。这样出问题能快速定位,迁移扩容也更容易。

通常可以这样拆分

  • 通用(general)只负责拉代码、编译、单测、lint,尽量不依赖 Docker 或复杂的宿主环境
  • 容器(docker)专门跑容器构建与镜像发布,Docker 能力明确且可控
  • 重任务(heavy)重编译或大内存任务,独立出来避免拖慢整体队列

Runner Fleet 的设计天然适配这种范式:因为它把每一个 Runner 都当作配置项加生命周期对象,而不是你记得的某台机器上的某个目录。

这篇文章中,我们主要来聊聊“容器”场景的使用,其他的部分,有机会的时候再聊。

服务器环境准备

服务器配置参考《搭建 Ubuntu 24.04 基础开发环境指南[2]》,把 Ubuntu 更新到最新状态,安装 Docker Engine 与 Compose 插件,并让当前用户可以免 sudo 使用 Docker 即可:

代码语言:javascript
复制
sudo apt update && sudo apt upgrade -y

sudo apt install -y ca-certificates curl gnupg lsb-release

curl -fsSL https://mirrors.tuna.tsinghua.edu.cn/docker-ce/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg

sudochmod a+r /etc/apt/keyrings/docker.gpg

echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://mirrors.tuna.tsinghua.edu.cn/docker-ce/linux/ubuntu/ \
  $(lsb_release -cs) stable" | sudotee /etc/apt/sources.list.d/docker.list > /dev/null

sudo apt update && sudo apt install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin

sudo gpasswd -a ${USER} docker

安装完毕,通常服务器会提示“需要重启”:

代码语言:javascript
复制
*** System restart required ***

输入 sudo reboot,完成服务器重启,一个能够运行 GitHub Action Runner 的服务器环境就准备好啦。

Runner Fleet 全容器环境部署

容器模式不是为了“看起来更云原生”,而是为了解决真实的三个痛点:

  1. 1. Runner 之间环境互相污染
  2. 2. 同机多 Runner 升级回滚时容易踩到彼此目录
  3. 3. 你需要更硬的边界来承载程序内容不完全可信的 job

我们从 GitHub Release 页面[3],找到最新的版本,使用 docker pull 对镜像进行下载:

代码语言:javascript
复制
docker pull ghcr.io/soulteary/runner-fleet:v1.1.0
docker pull ghcr.io/soulteary/runner-fleet:v1.1.0-runner

创建独立的 Docker 容器网络:

代码语言:javascript
复制
docker network create runner-net

创建两个目录:

代码语言:javascript
复制
mkdir -p config && chown 1001:1001 config
mkdir -p runners && chown 1001:1001 runners

然后,创建容器使用的 .env 基础配置:

代码语言:javascript
复制
# 此处账号/密码换成自己需要的,仅为示例
BASIC_AUTH_USER=soulteary
BASIC_AUTH_PASSWORD=soulteary

# 使用镜像
MANAGER_IMAGE=ghcr.io/soulteary/runner-fleet:v1.1.0
RUNNER_IMAGE=ghcr.io/soulteary/runner-fleet:v1.1.0-runner   

# 固定配置
CONTAINER_MODE=true
CONTAINER_NETWORK=runner-net
JOB_DOCKER_BACKEND=host-socket
RUNNERS_BASE_PATH=/app/runners
SERVER_PORT=8080
SERVER_ADDR=0.0.0.0

接下来,我们分别执行下面的命令,先将 Docker GID 添加到刚刚的 .env 文件中:

代码语言:javascript
复制
DOCKER_GID=$(getent group docker 2>/dev/null | cut -d: -f3)
[ -n "$DOCKER_GID" ] && echo "DOCKER_GID=$DOCKER_GID" >> .env

然后,将 runner 在宿主机中的真实路径也传递到 .env 中:

代码语言:javascript
复制
VOLUME_HOST_PATH=$(realpath runners 2>/dev/null || (cd runners 2>/dev/null && pwd -P))
echo "VOLUME_HOST_PATH=$VOLUME_HOST_PATH" >> .env

最后,编写 docker-compose.yml

代码语言:javascript
复制
services:
  runner-manager:
    # 默认使用稳定版 v1.0.0;开发/尝鲜可设 .env:MANAGER_IMAGE=ghcr.io/soulteary/runner-fleet:main
    image:${MANAGER_IMAGE:-ghcr.io/soulteary/runner-fleet:v1.0.0}
    container_name:runner-manager
    # 使用 job_docker_backend: dind 时请先启动 DinD:docker compose --profile dind up -d
    # 容器模式下必须用宿主机 socket,否则 Manager 无法创建 Runner 容器;默认 unix,勿改为 tcp://runner-dind:2375
    # 全容器时可通过 .env 传入以下变量覆盖 config/config.yaml,无需改 config 文件:CONTAINER_MODE、VOLUME_HOST_PATH、JOB_DOCKER_BACKEND、CONTAINER_NETWORK、RUNNER_IMAGE、RUNNERS_BASE_PATH 等
    environment:
      DOCKER_HOST:${DOCKER_HOST:-unix:///var/run/docker.sock}
      BASIC_AUTH_USER:${BASIC_AUTH_USER:-}
      BASIC_AUTH_PASSWORD:${BASIC_AUTH_PASSWORD:-}
      # 以下可选:覆盖 config/config.yaml,全容器时无需改 config 文件(见 .env.example)
      CONTAINER_MODE:${CONTAINER_MODE:-}
      VOLUME_HOST_PATH:${VOLUME_HOST_PATH:-}
      JOB_DOCKER_BACKEND:${JOB_DOCKER_BACKEND:-}
      CONTAINER_NETWORK:${CONTAINER_NETWORK:-}
      RUNNER_IMAGE:${RUNNER_IMAGE:-}
      RUNNERS_BASE_PATH:${RUNNERS_BASE_PATH:-}
    ports:
      -"${MANAGER_PORT:-8080}:8080"
    # 仅挂载 config 目录(勿挂载 config/config.yaml 单文件,否则宿主机无该文件时 Docker 会创建空文件导致启动失败)
    volumes:
      -./config:/app/config
      -./runners:/app/runners
      -/var/run/docker.sock:/var/run/docker.sock
    # 容器模式需 Manager 访问宿主机 Docker:加入宿主机 docker 组(GID 用 getent group docker 查看,常见为 999)
    group_add:
      -"${DOCKER_GID:-999}"
    networks:
      -runner-net
    restart:unless-stopped
    healthcheck:
      test: ["CMD", "curl", "-fsS", "http://127.0.0.1:8080/health"]
      interval:30s
      timeout:5s
      start_period:15s
      retries:3

# runner-net 设为 external,避免 compose down 时删除网络导致已注册的 Runner 容器
#(由 Manager 动态创建、未在 compose 中定义)无法启动。首次使用请执行:docker network create runner-net
networks:
runner-net:
    external: true

当所有配置都就绪后,执行 docker compose up -d,软件部署就完成了。默认情况下,我们打开 http://IP或域名:8080,输入上面配置中定义的账号和密码:

Runner Fleet - Basic Auth 登录
Runner Fleet - Basic Auth 登录

Runner Fleet - Basic Auth 登录

回车之后,就能够打开 Runner 配置界面,开始使用啦。

Runner Fleet - WebUI 界面
Runner Fleet - WebUI 界面

Runner Fleet - WebUI 界面

跑通第一个私有化的 GitHub Action

在 GitHub 项目中获取 Runner Token

GitHub - Action Runner 配置页面
GitHub - Action Runner 配置页面

GitHub - Action Runner 配置页面

当 Fleet 部署好之后,我们访问 GitHub 上任意项目的配置页面,打开 Action 菜单的 Runner 配置页面。

GitHub - 复制配置 token 指令
GitHub - 复制配置 token 指令

GitHub - 复制配置 token 指令

点击 “New self-hosted runner”,来到不同操作系统的 Runner 配置页面。我们在官方提供的 macOS / Linux 架构配置示例中,找到带有 token 的配置命令,单机该命令,命令会自动粘贴到剪贴板。

初始化 Fleet Runner

Fleet - 粘贴带有 Token 的命令到解析器
Fleet - 粘贴带有 Token 的命令到解析器

Fleet - 粘贴带有 Token 的命令到解析器

我们将命令粘贴到 fleet 的解析器中,点击“解析并填充”按钮。

Fleet - 一键解析
Fleet - 一键解析

Fleet - 一键解析

配置中的内容,就会都自动装填到创建 Runner 表单中,我们可以在创建之前,调整或修改各种细节(比如命名):

Fleet - 自动添加 Runner
Fleet - 自动添加 Runner

Fleet - 自动添加 Runner

如果你觉得上面的内容都就绪了,点击“添加 Runner” 按钮,程序将自动初始化 Runner。

Fleet - 刷新页面的 Runner 列表
Fleet - 刷新页面的 Runner 列表

Fleet - 刷新页面的 Runner 列表

添加完毕,我们在 Fleet Runner 列表中就能够看到刚刚添加的内容啦。

GitHub - Runner 列表实例就绪
GitHub - Runner 列表实例就绪

GitHub - Runner 列表实例就绪

与此同时,GitHub Runner 页面的 Runner 实例也就就绪啦。

修改 GitHub CI 配置,启用 Runner

到现在为止,我们已经将所有 GitHub Action CI/CD 的环境和服务都配置就绪啦。真正使用上私有化的 Runner 只差一步,就是修改 .github/workflows 中的 CI 文件,让他们使用自部署的 Runner,而非 GitHub 上的共享 Runner。

我们随便找一个之前已经启用了 GitHub Action 的项目,打开它任意的 workflows 配置文件:

代码语言:javascript
复制
jobs:
  # Code formatting check
fmt:
    name:CodeFormattingCheck
    runs-on:ubuntu-latest
    steps:
      -name:Checkoutcode
        uses: actions/checkout@v6

上面配置文件中,有一句配置是: runs-on: ubuntu-latest,我们将它修改为 runs-on: self-hosted

GitHub - 使用自托管 Runner 运行任务
GitHub - 使用自托管 Runner 运行任务

GitHub - 使用自托管 Runner 运行任务

再次运行 CI 任务的时候,就会调用我们的私有化服务来执行任务啦,是不是很简单?

最后

Fleet 里还有一些其他的玩法,包括裸金属使用、Dind 模式使用,这些在后续有机会的时候,我会陆续分享出来。

在设计工具的时候,我希望我们能够通过写明确的、简单的配置来规避掉大量奇奇怪怪的错误,也希望 UI 操作都能够直接落盘,让排错的证据可追踪。当然,因为环境的复杂性,报错的信息也应该即时反馈在界面该有的地方。

或许,这才是工程化工具该有的样子。

--EOF


我们有一个小小的折腾群,里面聚集了一些喜欢折腾、彼此坦诚相待的小伙伴。

我们在里面会一起聊聊软硬件、HomeLab、编程上、生活里以及职场中的一些问题,偶尔也在群里不定期的分享一些技术资料。

关于交友的标准,请参考下面的文章:

致新朋友:为生活投票,不断寻找更好的朋友[4]

当然,通过下面这篇文章添加好友时,请备注实名和公司或学校、注明来源和目的,珍惜彼此的时间 :D

关于折腾群入群的那些事[5]


如果你觉得内容还算实用,欢迎点赞分享给你的朋友,在此谢过。

如果你想更快的看到后续内容的更新,请戳 “点赞”、“分享”、“在看” ,这些免费的鼓励将会影响后续有关内容的更新速度。


本文使用「署名 4.0 国际 (CC BY 4.0)」许可协议,欢迎转载、或重新修改使用,但需要注明来源。 署名 4.0 国际 (CC BY 4.0)

引用链接

[1] soulteary/runner-fleet: https://github.com/soulteary/runner-fleet [2] 搭建 Ubuntu 24.04 基础开发环境指南: https://soulteary.com/2025/01/17/guide-to-setting-up-ubuntu-24-04-basic-development-environment.html [3] GitHub Release 页面: https://github.com/soulteary/runner-fleet/releases [4] 致新朋友:为生活投票,不断寻找更好的朋友: https://zhuanlan.zhihu.com/p/557928933 [5] 关于折腾群入群的那些事: https://zhuanlan.zhihu.com/p/56159997

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2026-02-18,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 折腾技术 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 写在前面
    • 构建一套可复用的使用范式
    • 服务器环境准备
  • Runner Fleet 全容器环境部署
  • 跑通第一个私有化的 GitHub Action
    • 在 GitHub 项目中获取 Runner Token
    • 初始化 Fleet Runner
    • 修改 GitHub CI 配置,启用 Runner
  • 最后
    • 引用链接
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档