- Обзор
- Настройка среды
- Подготовка сценариев Bash, используемых при создании образа
- start.sh
- Подготовка dockerfile для сборки образа (Linux)
- dockerfile
- Сборка образа Docker — Docker Desktop (Linux)
- Запуск образа Docker — Docker Desktop (Linux)
- Сборка образа Docker — Docker Compose (Linux)
- Запуск и масштабирование образа Docker — Docker Compose (Windows)
- Автор
- Marcel.L
Обзор
Весь код, используемый в этом руководстве, можно найти в моем проекте на GitHub: docker-github-runner-linux.
Добро пожаловать во вторую часть моего цикла статей: Самостоятельное размещение контейнеров GitHub Runner на Azure.
В первой части этой серии мы рассмотрели, как создать образ контейнера windows с помощью docker, а затем запустить наши саморазмещаемые GitHub runner в качестве контейнеров. В этой части мы сосредоточимся на создании образа Ubuntu на базе Linux.
В последующих частях мы рассмотрим, как использовать Azure для хранения и запуска наших контейнеров в облаке с помощью Azure Container Registry (ACR), Azure Container Instances (ACI) и Azure Container Apps (ACA) для запуска и масштабирования наших саморазмещающихся бегунов GitHub, вместо того чтобы использовать подход на базе ВМ с запуском docker внутри ВМ.
Настройка среды
Как было описано в первой части, перед созданием и запуском образов docker нам нужно сначала настроить несколько вещей. Для моей среды я буду использовать виртуальную машину Windows 11 под управлением WSL2. Вот дополнительная информация о запуске docker на Windows Server. На нашей виртуальной машине нам понадобятся следующие вещи:
-
Установите редактор кода, например VSCode
-
Установите и включите WSL2 (более подробную информацию см. в разделе: как включить WSL2):
Откройте PowerShell от имени администратора и запустите:
wsl --install
После установки WSL запустите:
Enable-WindowsOptionalFeature -Online -FeatureName $("Microsoft-Hyper-V", "Containers") -All
ПРИМЕЧАНИЕ: Вам потребуется перезагрузить систему после добавления соответствующих функций, указанных выше.
-
Загрузите и установите Docker Desktop для Windows (при этом автоматически будет установлен Docker-Compose)
-
После установки Docker Desktop For Windows необходимо переключиться на контейнеры Linux. Используйте элемент Docker в системном трее Windows:
ПРИМЕЧАНИЕ: Linux-контейнеры — это настройка по умолчанию, поэтому если вы пропустили первую часть этой серии, Docker Desktop For Windows уже будет настроен на использование Linux-контейнеров по умолчанию.
Подготовка сценариев Bash, используемых при создании образа
Теперь, когда Docker-Desktop, а также Docker-Compose установлены и настроены на использование Linux-контейнеров, мы можем приступить к созданию docker-образа для самостоятельного запуска на GitHub.
Откройте VSCode, вы можете клонировать репозиторий, найденный на моем проекте GitHub docker-github-runner-linux, который содержит все файлы, или просто выполнить следующие шаги. Мы подготовим скрипт, который будет необходим для создания образа docker.
Создайте папку root
под названием docker-github-runner-linux
, а затем еще одну папку под названием scripts
. Внутри папки scripts вы можете создать следующий скрипт:
start.sh
Этот скрипт будет использоваться как наш 'ENTRYPOINT'
скрипт и будет использоваться для загрузки нашего контейнера docker, когда мы запускаем контейнер из образа, который мы создаем. Основная цель этого скрипта — зарегистрировать новый экземпляр GitHub runner на репозитории, которую мы передаем в среду docker каждый раз, когда новый контейнер запускается или масштабируется из образа.
#!/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 $!
Подготовка dockerfile для сборки образа (Linux)
Теперь, когда наши скрипты готовы, мы можем приступить к самому интересному… Сборка образа linux docker. Перейдите в корневую папку и создайте файл с именем: dockerfile
:
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"]
Давайте рассмотрим подробнее и посмотрим, что на самом деле будет делать этот файл сборки docker, шаг за шагом:
# base image
FROM ubuntu:20.04
Инструкция '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}
Мы определяем входной аргумент с помощью 'ARG'
. Это нужно для того, чтобы мы могли указать команде docker build загрузить определенную версию агента GitHub runner в образ при сборке образа. Поскольку мы используем контейнер linux, '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
Первая команда 'RUN'
обновит базовые пакеты на образе Ubuntu 20.04 и добавит пользователя docker без права доступа.
Второй 'RUN'
установит пакеты и зависимости, такие как git, Azure-CLI, python вместе с jq, чтобы мы могли разобрать JSON для токена в нашем сценарии ENTRYPOINT.
ПРИМЕЧАНИЕ: Вы можете добавлять дополнительные пакеты по мере необходимости на этом этапе, но старайтесь не устанавливать слишком много пакетов во время сборки, чтобы сохранить образ как можно более компактным, компактным и пригодным для повторного использования. Вы всегда можете использовать GitHub Action позже в рабочем процессе при запуске контейнера и использовать действия для установки дополнительных инструментов.
Я покажу, как мы можем добавить дополнительное программное обеспечение и инструменты, например Terraform, позже при запуске нашего контейнера, используя действие GitHub Action.
# 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
Следующая инструкция 'RUN'
создаст новую папку actions-runner и загрузит и извлечет определенную версию двоичных файлов GitHub runner на основе аргумента сборки 'ARG'
, переданного в процесс сборки контейнера, который устанавливает переменную окружения: $RUNNER_VERSION, как описано ранее. Несколько дополнительных зависимостей также устанавливаются из извлеченных файлов 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"]
Последний раздел 'ADD'
добавит к образу 'ENTRYPOINT'
скрипт start.sh. Сценарий точки входа будет запускаться каждый раз при создании нового контейнера. Он действует как бутстраппер, который на основе определенных переменных окружения, которые мы передаем в команду Docker Run, таких как $GH_OWNER, $GH_REPOSITORY и $GH_TOKEN, зарегистрирует агент runner, самостоятельно размещенный в контейнере, в определенном репозитории в указанной нами организации GitHub.
Теперь, когда у нас готовы наши скрипты, а также наш dockerfile, мы можем собрать наш образ.
ПРИМЕЧАНИЕ: Мы можем собирать и запускать образы контейнеров linux с помощью docker-desktop или docker-compose, далее я покажу оба метода.
Сборка образа Docker — Docker Desktop (Linux)
В терминале VSCode или в сессии PowerShell перейдите в корневую папку, содержащую файл docker, и выполните следующую команду. Помните, что нам нужно передать аргумент build, чтобы указать 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 .
Процесс сборки может занять некоторое время:
После завершения процесса вы увидите новый образ в Docker Desktop для Windows в разделе images:
Запуск образа Docker — Docker Desktop (Linux)
Для запуска и инициализации нового контейнера GitHub runner linux из только что созданного образа выполните следующую команду. Мы должны передать некоторые переменные окружения с помощью опции '-e'
, чтобы указать PAT (Personal Access Token), организацию GitHub и репозиторий для регистрации runner.
#Run container from image:
docker run -e GH_TOKEN='myPatToken' -e GH_OWNER='orgName' -e GH_REPOSITORY='repoName' -d image-name
О том, как создать токен PAT на GitHub, см. в разделе Создание персонального маркера доступа. PAT-токены отображаются только один раз и являются конфиденциальными, поэтому позаботьтесь об их сохранности.
Для регистрации саморазмещаемого бегуна в токене PAT требуются следующие минимальные диапазоны разрешений: "repo"
, "read:org"
:
Совет: Я рекомендую использовать только токены PAT с коротким сроком действия и генерировать новые токены каждый раз, когда требуется регистрация новых бегунов-агентов.
После выполнения этой команды в настройках репозитория GitHub вы увидите новый саморазмещающийся GitHub runner. (Это наш контейнер docker):
Вы также сможете увидеть запущенный контейнер в Docker Desktop для Windows в разделе Containers:
Давайте протестируем наш новый контейнер docker с саморазмещаемым GitHub runner, создав рабочий процесс GitHub для запуска нескольких GitHub Actions с помощью установки Terraform на запущенный контейнер.
Вы можете использовать этот тестовый рабочий процесс из моего проекта на GitHub: docker-github-runner-linux.
Создайте новый рабочий процесс в репозитории GitHub, где вы развернули саморазмещаемый бегун, и запустите его:
name: Local runner test
on:
workflow_dispatch:
jobs:
testRunner:
runs-on: [self-hosted]
steps:
- uses: actions/checkout@v2
- name: Install Terraform
uses: hashicorp/setup-terraform@v2
- name: Display Terraform Version
run: terraform --version
- name: Display Azure-CLI Version
run: az --version
Обратите внимание, что рабочий процесс 'runs-on: [self-hosted]'
. Теперь мы можем использовать следующий шаг для установки Terraform:
steps:
- name: Install Terraform
uses: hashicorp/setup-terraform@v2
- name: Display Terraform Version
run: terraform --version
Чтобы добавить дополнительные docker runners (контейнеры), просто повторно выполните команду docker, которую мы запустили ранее (каждый запуск будет создавать дополнительный экземпляр runner/контейнер):
#Run container from image:
docker run -e GH_TOKEN='myPatToken' -e GH_OWNER='orgName' -e GH_REPOSITORY='repoName' -d image-name
Далее мы рассмотрим остановку/удаление запущенных экземпляров docker и очистку регистраций для всех саморазмещаемых бегунов, зарегистрированных в нашем репозитории GitHub.
Чтобы остановить и удалить все запущенные контейнеры, просто выполните команду :
docker stop $(docker ps -aq) && docker rm $(docker ps -aq)
Вы заметите, что все запущенные контейнеры под Docker Desktop для Windows больше не существуют, а также регистрация узлов docker в нашем репозитории GitHub также была очищена и удалена:
Причина, по которой наши регистрации бегунов на GitHub также удаляются, заключается в коде очистки в нашем сценарии 'ENTRYPOINT'
start.sh, который автоматически запускает очистку регистрации бегуна, когда докер-контейнер останавливается и уничтожается:
cleanup() {
echo "Removing runner..."
./config.sh remove --unattended --token ${REG_TOKEN}
}
trap 'cleanup; exit 130' INT
trap 'cleanup; exit 143' TERM
Далее мы рассмотрим, как можно собрать образ, а также запустить наш образ в масштабе с помощью docker-compose.
Сборка образа Docker — Docker Compose (Linux)
Как мы видели ранее, собрать наш образ с помощью команд docker довольно просто, но мы также можем использовать docker-compose с конфигурационным файлом, чтобы сделать все немного проще. Итак, перейдите в корневую папку, содержащую созданный нами ранее dockerfile, и создайте новый файл 'YAML'
под названием docker-compose.yml:
---
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}
В конфигурационном файле docker compose мы можем задать параметры для нашего образа докера, указав такие вещи, как имя образа, версию GitHub runner, а также переменные окружения.
Обратите внимание, что мы должны установить эти переменные окружения на нашем хосте, машине windows 11, чтобы docker compose смог интерпретировать значения, указанные в файле 'YAML'
внутри символов '${}'
. Это можно легко сделать, выполнив следующие команды PowerShell на хосте windows 11:
#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'
ПРИМЕЧАНИЕ: Вы также можете использовать файл окружения для передачи переменных окружения в процесс сборки docker compose, используя файл docker-compose.yml, как показано ниже:
---
version: '3.8'
services:
runner:
image: pwd9000-github-runner-lin:latest
build:
context: .
args:
RUNNER_VERSION: '2.292.0'
env_file:
- ./variables.env
Однако этот метод требует создания еще одного файла в корне нашей рабочей папки под названием ./variables.env и заполнения этого файла переменными окружения, как показано ниже:
GH_OWNER=orgName
GH_REPOSITORY=repoName
GH_TOKEN=myPatToken
ВАЖНО: Не используйте этот метод и не фиксируйте этот файл в системе управления исходным кодом, если вы используете конфиденциальные значения и храните код в удаленном репозитории системы управления исходным кодом. При необходимости добавьте этот файл окружения в файл '.gitignore'
, чтобы он не попадал в контроль исходного кода.
Какой бы метод вы ни решили использовать, вы можете запустить процесс сборки после создания этого файла docker-compose.yml, выполнив следующую команду PowerShell:
docker-compose build
После завершения процесса вы увидите новый образ в Docker Desktop для Windows в разделе images:
Запуск и масштабирование образа Docker — Docker Compose (Windows)
Что приятно в использовании docker-compose, так это то, что мы можем легко масштабировать количество бегунов, которые мы хотим использовать, просто выполнив следующую команду:
docker-compose up --scale runner=3 -d
Поскольку вся наша конфигурация и детали хранятся в переменных окружения и файле docker-compose 'YAML'
, нам не нужно выполнять длинные команды docker, как мы делали ранее, и мы просто масштабируем количество бегунов, указывая параметр '--scale'
.
ПРИМЕЧАНИЕ: Параметр '--scale runner=3 -d'
основан на параметре docker compose file, 'services:'
, который в нашем случае называется 'runner'
:
services:
runner:
Чтобы уменьшить масштаб до одного бегуна, мы можем просто повторно выполнить команду следующим образом:
docker-compose up --scale runner=1 -d
Чтобы остановить и удалить все запущенные контейнеры, просто выполните команду:
docker-compose stop
docker rm $(docker ps -aq)
Как было описано ранее, вы заметите, что все запущенные контейнеры в Docker Desktop for Windows больше не существуют, также как и регистрации в нашем репозитории GitHub были очищены:
В этой части серии мы рассказали о том, как можно создавать и запускать саморазмещаемые GitHub runners как linux-контейнеры с помощью docker-desktop и docker-compose. В следующей части этой серии блогов мы рассмотрим размещение/хранение образов контейнеров GitHub runner в удаленном реестре Azure с помощью Azure Container Registry (ACR).
Надеюсь, вам понравилась эта статья и вы узнали что-то новое. Примеры кода, использованные в этой статье, вы можете найти на моей странице GitHub. ❤️
Автор
Like, share, follow me on: 🐙 GitHub | 🐧 Twitter | 👾 LinkedIn

Marcel.L