发布于 2026-01-06 0 阅读
0

创建一个基于 Docker 的自托管 GitHub 运行器 Linux 容器

创建一个基于 Docker 的自托管 GitHub 运行器 Linux 容器

概述

本教程中使用的所有代码都可以在我的 GitHub 项目中找到:docker-github-runner-linux

欢迎来到我的系列文章的第二部分:Azure 上的自托管 GitHub Runner 容器

在本系列的第一部分中,我们探讨了如何使用 Docker 创建Windows 容器镜像,然后将自托管的GitHub Runner作为容器运行。在这一部分中,我们将重点介绍如何构建基于 Linux 的 Ubuntu 镜像

在后续部分中,我们将探讨如何利用Azure容器注册表 (ACR)Azure 容器实例 (ACI)Azure 容器应用 (ACA)在云中存储和运行容器,以运行和扩展我们自托管的 GitHub 运行器,而不是使用基于 VM 的方法在 VM 内运行 Docker。

设置环境

如第一部分所述,在构建和运行 Docker 镜像之前,我们需要先进行一些设置。我的环境将使用运行WSL2 的Windows 11虚拟机。有关在Windows Server上运行 Docker 的更多信息,请参阅此处。我们的虚拟机需要以下组件:

以管理员身份打开 PowerShell 并运行:

wsl --install
Enter fullscreen mode Exit fullscreen mode

WSL 安装完成后,运行:

Enable-WindowsOptionalFeature -Online -FeatureName $("Microsoft-Hyper-V", "Containers") -All
Enter fullscreen mode Exit fullscreen mode

注意:添加上述相关功能后,您需要重启系统。

  • 下载并安装适用于 Windows 的 Docker Desktop(这将自动安装Docker-Compose

  • 安装好适用于 Windows 的 Docker Desktop后,您需要切换到 Linux 容器。使用 Windows 系统托盘中的 Docker 图标:

image.png

注意: Linux 容器是默认设置,因此如果您跳过了本系列的第一部分,Docker Desktop For Windows默认将设置为使用Linux 容器。

准备用于镜像创建的 Bash 脚本

现在我们已经安装并设置了Docker-DesktopDocker-Compose来使用Linux 容器,我们可以开始构建我们自己的 GitHub 运行器 docker 镜像了。

打开 VSCode,您可以克隆我的 GitHub 项目docker-github-runner-linux中的仓库(其中包含所有文件),或者直接按照以下步骤操作。我们将准备一个脚本,该脚本将在创建 Docker 镜像时用到。

创建一个root名为 `scripts` 的文件夹docker-github-runner-linux,然后在 `scripts` 文件夹中创建一个名为 `.scripts` 的子文件夹scripts。在`scripts`文件夹中,您可以创建以下脚本:

image.png

开始脚本

我们将使用此脚本作为引导'ENTRYPOINT'脚本,在从我们创建的镜像启动/运行容器时,用于引导我们的 Docker 容器。此脚本的主要目的是在每次从镜像启动或扩展新容器时,在我们传递给 Docker 环境的仓库上注册一个新的自托管 GitHub Runner 实例。

#!/bin/bash

GH_OWNER=$GH_OWNER
GH_REPOSITORY=$GH_REPOSITORY
GH_TOKEN=$GH_TOKEN

RUNNER_SUFFIX=$(cat /dev/urandom | tr -dc 'a-z0-9' | fold -w 5 | head -n 1)
RUNNER_NAME="dockerNode-${RUNNER_SUFFIX}"

REG_TOKEN=$(curl -sX POST -H "Accept: application/vnd.github.v3+json" -H "Authorization: token ${GH_TOKEN}" https://api.github.com/repos/${GH_OWNER}/${GH_REPOSITORY}/actions/runners/registration-token | jq .token --raw-output)

cd /home/docker/actions-runner

./config.sh --unattended --url https://github.com/${GH_OWNER}/${GH_REPOSITORY} --token ${REG_TOKEN} --name ${RUNNER_NAME}

cleanup() {
    echo "Removing runner..."
    ./config.sh remove --unattended --token ${REG_TOKEN}
}

trap 'cleanup; exit 130' INT
trap 'cleanup; exit 143' TERM

./run.sh & wait $!
Enter fullscreen mode Exit fullscreen mode

准备用于构建镜像的 Dockerfile(Linux)

现在脚本已经准备就绪,我们可以开始有趣的部分了……构建Linux Docker 镜像。返回根文件夹并创建一个名为 `docker-compose.yml` 的文件dockerfile

image.png

Dockerfile

此 Dockerfile 包含构建容器镜像的指令。

# base image
FROM ubuntu:20.04

#input GitHub runner version argument
ARG RUNNER_VERSION
ENV DEBIAN_FRONTEND=noninteractive

LABEL Author="Marcel L"
LABEL Email="pwd9000@hotmail.co.uk"
LABEL GitHub="https://github.com/Pwd9000-ML"
LABEL BaseImage="ubuntu:20.04"
LABEL RunnerVersion=${RUNNER_VERSION}

# update the base packages + add a non-sudo user
RUN apt-get update -y && apt-get upgrade -y && useradd -m docker

# install the packages and dependencies along with jq so we can parse JSON (add additional packages as necessary)
RUN apt-get install -y --no-install-recommends \
    curl nodejs wget unzip vim git azure-cli jq build-essential libssl-dev libffi-dev python3 python3-venv python3-dev python3-pip

# cd into the user directory, download and unzip the github actions runner
RUN cd /home/docker && mkdir actions-runner && cd actions-runner \
    && curl -O -L https://github.com/actions/runner/releases/download/v${RUNNER_VERSION}/actions-runner-linux-x64-${RUNNER_VERSION}.tar.gz \
    && tar xzf ./actions-runner-linux-x64-${RUNNER_VERSION}.tar.gz

# install some additional dependencies
RUN chown -R docker ~docker && /home/docker/actions-runner/bin/installdependencies.sh

# add over the start.sh script
ADD scripts/start.sh start.sh

# make the script executable
RUN chmod +x start.sh

# set the user to "docker" so all subsequent commands are run as the docker user
USER docker

# set the entrypoint to the start.sh script
ENTRYPOINT ["./start.sh"]
Enter fullscreen mode Exit fullscreen mode

让我们仔细看看这个 Docker 构建文件究竟会执行哪些操作,一步一步来:

# base image
FROM ubuntu:20.04
Enter fullscreen mode Exit fullscreen mode

'FROM'指令将指示我们的 Docker 构建程序获取并使用 Ubuntu 20.04 操作系统基础镜像。接下来,我们将向该基础镜像添加其他配置。

#input GitHub runner version argument
ARG RUNNER_VERSION
ENV DEBIAN_FRONTEND=noninteractive

LABEL Author="Marcel L"
LABEL Email="pwd9000@hotmail.co.uk"
LABEL GitHub="https://github.com/Pwd9000-ML"
LABEL BaseImage="ubuntu:20.04"
LABEL RunnerVersion=${RUNNER_VERSION}
Enter fullscreen mode Exit fullscreen mode

我们使用 `docker build` 定义一个输入参数'ARG'。这样我们就可以指示 `docker build` 命令在构建镜像时将特定版本的GitHub Runner Agent 加载到镜像中。由于我们使用的是Linux 容器, `docker build`'ARG'将创建一个系统变量`$RUNNER_VERSION`,容器内的 Bash 可以访问该变量。

我们还设置了一个名为DEBIAN_FRONTEND的环境变量,使其与系统交互,这样我们以后就可以在无人值守模式下运行命令。'ENV'

此外,我们还可以使用元数据'LABEL'为图像添加标签,以便提供更多关于图像的信息。您可以根据需要更改这些值。

注意: 'LABEL RunnerVersion=${RUNNER_VERSION}'此标签会根据我们稍后将传递给 docker 构建命令的构建参数动态更新。

# update the base packages + add a non-sudo user
RUN apt-get update -y && apt-get upgrade -y && useradd -m docker

# install the packages and dependencies along with jq so we can parse JSON (add additional packages as necessary)
RUN apt-get install -y --no-install-recommends \
    curl nodejs wget unzip vim git azure-cli jq build-essential libssl-dev libffi-dev python3 python3-venv python3-dev python3-pip
Enter fullscreen mode Exit fullscreen mode

第一条指令将更新 Ubuntu 20.04 镜像上的基础软件包,并添加一个名为docker'RUN'的非 sudo 用户

第二个步骤将安装gitAzure-CLIpythonjq'RUN'等软件包和依赖项,以便我们可以在ENTRYPOINT脚本中解析 JSON 以获取令牌

注意:您可以在此阶段根据需要添加其他软件包,但请尽量不要在构建时安装过多软件包,以保持镜像尽可能精简、紧凑且易于重用。您始终可以在运行容器的工作流中使用GitHub Action,并通过 Action 安装更多工具。

稍后在运行容器时,我将演示如何使用 GitHub Action 添加更多软件和工具,例如Terraform 。

# cd into the user directory, download and unzip the github actions runner
RUN cd /home/docker && mkdir actions-runner && cd actions-runner \
    && curl -O -L https://github.com/actions/runner/releases/download/v${RUNNER_VERSION}/actions-runner-linux-x64-${RUNNER_VERSION}.tar.gz \
    && tar xzf ./actions-runner-linux-x64-${RUNNER_VERSION}.tar.gz

# install some additional dependencies
RUN chown -R docker ~docker && /home/docker/actions-runner/bin/installdependencies.sh
Enter fullscreen mode Exit fullscreen mode

下一'RUN'条指令将创建一个名为actions-runner 的新文件夹,并根据'ARG'传递给容器构建过程的构建参数值(该参数值会设置环境变量$RUNNER_VERSION,如前所述)下载并提取特定版本的 GitHub Runner 二进制文件。此外,还会从提取的 GitHub Runner 文件中安装一些其他依赖项。

# add over the start.sh script
ADD scripts/start.sh start.sh

# make the script executable
RUN chmod +x start.sh

# set the user to "docker" so all subsequent commands are run as the docker user
USER docker

# set the entrypoint to the start.sh script
ENTRYPOINT ["./start.sh"]
Enter fullscreen mode Exit fullscreen mode

最后一部分会将名为start.sh 的'ADD'脚本添加到镜像中。该入口脚本会在每次创建新容器时运行。它充当引导程序,根据我们传递给Docker Run命令的特定环境变量(例如$GH_OWNER$GH_REPOSITORY$GH_TOKEN),将容器的自托管运行器代理注册到我们指定的GitHub 组织中的特定仓库'ENTRYPOINT'

现在我们的脚本和 Dockerfile 都已准备就绪,我们可以构建镜像了。

注意:我们可以使用docker-desktopdocker-compose构建和运行 linux 容器镜像,接下来我将展示这两种方法。

构建 Docker 镜像 - Docker Desktop(Linux)

在 VSCode 终端或 PowerShell 会话中,导航到包含 Dockerfile 的根文件夹并运行以下命令。请记住,我们需要传递一个构建参数,以告知 Docker 在创建镜像时要使用的 GitHub Runner 代理版本。GitHub Runner 版本

#Build container: docker build [OPTIONS] PATH
docker build --build-arg RUNNER_VERSION=2.292.0 --tag docker-github-runner-lin .
Enter fullscreen mode Exit fullscreen mode

建造过程可能需要一些时间才能完成:

image.png

流程完成后,您将在Docker Desktop for Windows 的images 目录下看到新镜像

image.png

运行 Docker 镜像 - Docker Desktop(Linux)

要从我们刚刚创建的镜像运行并配置一个新的自托管 GitHub Runner Linux 容器,请运行以下命令。我们需要使用选项传入一些环境变量,以'-e'指定PAT(个人访问令牌)GitHub 组织和要注册 Runner 的仓库

#Run container from image:
docker run -e GH_TOKEN='myPatToken' -e GH_OWNER='orgName' -e GH_REPOSITORY='repoName' -d image-name
Enter fullscreen mode Exit fullscreen mode

请参阅“创建个人访问令牌”了解如何创建 GitHub PAT 令牌。PAT 令牌仅显示一次,且非常敏感,请务必妥善保管。

注册自托管运行器所需的 PAT 令牌的最低权限范围为:"repo""read:org"

image.png

提示:我建议只使用有效期较短的 PAT 令牌,并在需要注册新的代理程序时生成新的令牌。

运行此命令后,在 GitHub 仓库设置中,您将看到一个新的自托管 GitHub 运行器。(这就是我们的 Docker 容器):

image.png

您还可以在 Windows 版 Docker Desktop 的“容器”下看到正在运行容器

image.png

让我们通过在运行的容器上安装Terraform来创建一个GitHub 工作流,从而运行一些GitHub Actions,以此来测试我们新的自托管 docker 容器 GitHub runner 。

您可以使用我的 GitHub 项目中的此测试工作流程: docker-github-runner-linux

在部署了自托管运行器的 GitHub 仓库下创建一个新的工作流:

name: Local runner test

on:
  workflow_dispatch:

jobs:
  testRunner:
    runs-on: [self-hosted]
    steps:
      - uses: actions/checkout@v3.6.0
      - name: Install Terraform
        uses: hashicorp/setup-terraform@v2
      - name: Display Terraform Version
        run: terraform --version
      - name: Display Azure-CLI Version
        run: az --version
Enter fullscreen mode Exit fullscreen mode

请注意工作流程'runs-on: [self-hosted]'。现在我们可以使用以下步骤安装Terraform

steps:
- name: Install Terraform
    uses: hashicorp/setup-terraform@v2
- name: Display Terraform Version
    run: terraform --version
Enter fullscreen mode Exit fullscreen mode

image.png

要添加额外的 Docker 运行器(容器),我们只需重新运行之前运行的 Docker 命令(每次运行都会创建一个额外的运行器实例/容器):

#Run container from image:
docker run -e GH_TOKEN='myPatToken' -e GH_OWNER='orgName' -e GH_REPOSITORY='repoName' -d image-name
Enter fullscreen mode Exit fullscreen mode

image.png

接下来,我们将研究如何停止/销毁正在运行的 Docker 实例,并清理所有已注册到我们 GitHub 存储库的自托管运行器的注册信息。

要停止并移除所有正在运行的容器,只需运行:

docker stop $(docker ps -aq) && docker rm $(docker ps -aq)
Enter fullscreen mode Exit fullscreen mode

您会注意到,所有在Windows 版 Docker Desktop下运行的容器都已消失,同时,我们 GitHub 仓库的 Docker 节点注册信息也已被清理和删除:

image.png

'ENTRYPOINT'GitHub runner 注册信息被移除的原因是,我们的脚本start.sh中包含清理代码,该代码会在 docker 容器停止并销毁时自动触发 runner 注册信息的清理:

cleanup() {
    echo "Removing runner..."
    ./config.sh remove --unattended --token ${REG_TOKEN}
}

trap 'cleanup; exit 130' INT
trap 'cleanup; exit 143' TERM
Enter fullscreen mode Exit fullscreen mode

接下来我们将了解如何构建镜像,以及如何使用docker-compose大规模运行镜像。

构建 Docker 镜像 - Docker Compose(Linux)

正如我们之前看到的,使用 Docker 命令构建镜像非常容易,但我们也可以使用带有配置文件的docker-compose来简化操作。接下来,再次导航到包含我们之前创建的Dockerfile 的根文件夹,并创建一个名为docker-compose.yml的新'YAML'文件

---
version: '3.8'

services:
  runner:
    image: pwd9000-github-runner-lin:latest
    build:
      context: .
      args:
        RUNNER_VERSION: '2.292.0'
    environment:
      GH_TOKEN: ${GH_TOKEN}
      GH_OWNER: ${GH_OWNER}
      GH_REPOSITORY: ${GH_REPOSITORY}
Enter fullscreen mode Exit fullscreen mode

在 docker compose 配置文件中,我们可以通过指定镜像名称、GitHub runner 版本以及环境变量等内容来设置 docker 镜像的参数。

请注意,我们需要在主机(Windows 11 系统)上设置这些环境变量,以便Docker Compose能够解析'YAML'文件中'${}'符号指定的值。这可以通过在 Windows 11 主机上运行以下 PowerShell 命令轻松完成:

#set system environment with $env: (or use .env file to pass GH_TOKEN, GH_OWNER, GH_REPOSITORY)
$env:GH_OWNER='Org/Owner'
$env:GH_REPOSITORY='Repository'
$env:GH_TOKEN='myPatToken'
Enter fullscreen mode Exit fullscreen mode

注意:您也可以使用环境变量文件,通过类似这样的docker-compose.yml文件将环境变量传递给 docker compose 构建过程:

---
version: '3.8'

services:
  runner:
    image: pwd9000-github-runner-lin:latest
    build:
      context: .
      args:
        RUNNER_VERSION: '2.292.0'
    env_file:
      - ./variables.env
Enter fullscreen mode Exit fullscreen mode

然而,这种方法需要我们在工作文件夹的根目录下创建一个名为./variables.env的文件,并像这样用我们的环境变量填充该文件:

GH_OWNER=orgName
GH_REPOSITORY=repoName
GH_TOKEN=myPatToken
Enter fullscreen mode Exit fullscreen mode

重要提示:如果您使用敏感值并将代码存储在远程源代码控制仓库中,请勿使用此方法,也不要将此文件提交到源代码控制系统。'.gitignore'如有需要,请将此环境文件添加到您的文件中,以防止其被推送到源代码控制系统。

无论你决定使用哪种方法,创建好docker-compose.yml文件后,都可以运行以下 PowerShell 命令来启动构建过程:

docker-compose build
Enter fullscreen mode Exit fullscreen mode

image.png

流程完成后,您将在Docker Desktop for Windows 的images 目录下看到新镜像

image.png

运行和扩展 Docker 镜像 - Docker Compose(Windows)

使用docker-compose的好处在于,我们可以通过运行以下命令轻松扩展要使用的运行器数量:

docker-compose up --scale runner=3 -d
Enter fullscreen mode Exit fullscreen mode

由于我们所有的配置和细节都保存在环境变量docker-compose 'YAML'文件中,我们不必像以前那样运行冗长的 docker 命令,只需指定'--scale'参数即可扩展所需的运行器数量。

image.png

注意:'--scale runner=3 -d'参数基于 docker compose 文件中的'services:'设置,在本例中名为'runner'

services:
  runner:
Enter fullscreen mode Exit fullscreen mode

要将规模缩小到单个运行器,我们可以简单地重新运行该命令,如下所示:

docker-compose up --scale runner=1 -d
Enter fullscreen mode Exit fullscreen mode

要停止并移除所有正在运行的容器,只需运行:

docker-compose stop
docker rm $(docker ps -aq)
Enter fullscreen mode Exit fullscreen mode

如前所述,您会注意到所有在Windows 版 Docker Desktop下运行的容器都已不存在,并且我们 GitHub 存储库的注册信息也已被清除:

image.png

在本系列文章的这一部分,我们介绍了如何使用docker-desktopdocker-compose构建和运行自托管的GitHub Runner,并将其作为Linux 容器运行。在本系列博客的下一部分中,我们将探讨如何使用Azure 容器注册表 (ACR)在 Azure 的远程注册表中托管/存储GitHub Runner容器镜像。

希望您喜欢这篇文章,并且有所收获。您可以在我的GitHub页面上找到本文中使用的代码示例。❤️

作者

请点赞、分享并关注我的社交媒体账号:🐙 GitHub | 🐧 X | 👾 LinkedIn

文章来源:https://dev.to/pwd9000/create-a-docker-based-self-hosted-github-runner-linux-container-48dh