背景と目的
https://qiita.com/mnrst/items/e48d6c5b54385de5447a
以前こちらの記事を書きました。今回はセルフホステッド Linux エージェントを Docker で起動して、その Docker の中で Docker ビルドが出来る環境を用意して試してみました。
前提条件
コマンドの実施環境は、Mac + Azure CLI です。
bash
$ sw_vers
ProductName: macOS
ProductVersion: 12.1
BuildVersion: 21C52
$ az version
{
"azure-cli": "2.32.0",
"azure-cli-core": "2.32.0",
"azure-cli-telemetry": "1.0.6",
"extensions": {}
}
Azure DevOps 組織にプロジェクトを作成
bash
# リソースのリージョンを設定します
region=japaneast
# Azure DevOps 組織名を設定します(サインアップした組織名です)
prefix=mnrdevopsagent
# Azure CLI に拡張機能を追加します
az extension add \
--name azure-devops
# 拡張機能に Azure DevOps 組織をデフォルト設定します
az devops configure \
--defaults organization=https://dev.azure.com/${prefix}/
# Azure DevOps のプロジェクトを作成します
az devops project create \
--name ${prefix}
# 作成したプロジェクトに簡単な Dockerfile を登録します
mkdir ${prefix} && cd ${prefix}
echo "FROM nginx" > Dockerfile
git init
git add Dockerfile
git commit -m "first commit"
git remote add origin https://${prefix}@dev.azure.com/${prefix}/${prefix}/_git/${prefix}
git push -u origin --all
プロジェクトに Azure Pipeline を作成
こちらを参考にパイプラインを作成します。
bash
# azure-pipelines.yml を作成
cat <<EOF > azure-pipelines.yml
trigger:
- master
pool:
vmImage: ubuntu-latest
variables:
imageName: ${prefix}
steps:
- task: Docker@2
displayName: Build an image
inputs:
repository: \$(imageName)
command: build
Dockerfile: Dockerfile
EOF
# azure-pipelines.yml を Git リポジトリに登録します
git add azure-pipelines.yml
git commit -m update
git push
# パイプラインを作成します
az pipelines create \
--name ${prefix}-pipeline \
--yml-path azure-pipelines.yml
# パイプラインの実行状況を確認します
az pipelines runs list \
--output table
# 最初のパイプラインの詳細を確認します
az pipelines runs show \
--id 1 \
--output table
# ブラウザーでビルド結果ページを開きます
az pipelines runs show \
--id 1 \
--open
セルフホステッド検証用の Linux VM を作成
bash
# リソースグループを作成します
az group create \
--name ${prefix}-rg \
--location $region
# SSH キーペアをファイル名を指定して作成します
ssh-keygen -m PEM -t rsa -b 4096 \
-f ${prefix}
# VM を作成します
az vm create \
--resource-group ${prefix}-rg \
--name ${prefix}-vm \
--os-disk-name ${prefix}-vmOSDisk \
--image UbuntuLTS \
--admin-username azureuser \
--ssh-key-value ${prefix}.pub \
--size Standard_A2_v2 \
--nsg-rule NONE \
--public-ip-address-dns-name ${prefix} \
--storage-sku Standard_LRS
# NSG に自分の IP アドレスから SSH 接続出来るようにします
az network nsg rule create \
--resource-group ${prefix}-rg \
--name Allow-SSH \
--nsg-name ${prefix}-vmNSG \
--priority 100 \
--source-address-prefixes $(curl -s inet-ip.info) \
--destination-port-ranges 22 \
--access Allow \
--protocol Tcp
# SSH 秘密キーを使用して SSH 接続します
ssh -i ${prefix} azureuser@${prefix}.$region.cloudapp.azure.com
VM 内で Docker 環境を準備
bash
sudo apt-get install ca-certificates curl gnupg lsb-release
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu \
$(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt-get update
sudo apt-get -y install docker-ce docker-ce-cli containerd.io
sudo usermod -a -G docker $USER
newgrp docker
docker run -it --rm nginx curl inet-ip.info
セルフホステッド Linux エージェントを Docker で起動
bash
# Azure DevOps の組織 URL を設定(${prefix} 部分は手動で置き換えてください)
azpurl=https://dev.azure.com/${prefix}
azptoke=arwttgjnbnbssyn3gtdqau6a6g6sgx52pufczx4nmxrfvw2tmj5a
# セルフホステッドエージェント用の PAT を設定します
azptoke=yourpathere
# セルフホステッド Linux エージェント用の Dockerfile を作成します
cat << "EOF" > Dockerfile
FROM ubuntu:18.04
# To make it easier for build and release pipelines to run apt-get,
# configure apt to not require confirmation (assume the -y argument by default)
ENV DEBIAN_FRONTEND=noninteractive
RUN echo "APT::Get::Assume-Yes \"true\";" > /etc/apt/apt.conf.d/90assumeyes
RUN apt-get update && apt-get install -y --no-install-recommends \
ca-certificates \
curl \
jq \
git \
iputils-ping \
libcurl4 \
libicu60 \
libunwind8 \
netcat \
libssl1.0 \
&& rm -rf /var/lib/apt/lists/*
RUN curl -LsS https://aka.ms/InstallAzureCLIDeb | bash \
&& rm -rf /var/lib/apt/lists/*
ENV DOCKER_CHANNEL stable
ENV DOCKER_VERSION 18.06.1-ce
RUN set -ex \
&& curl -fL "https://download.docker.com/linux/static/${DOCKER_CHANNEL}/`uname -m`/docker-${DOCKER_VERSION}.tgz" -o docker.tgz \
&& tar --extract --file docker.tgz --strip-components 1 --directory /usr/local/bin \
&& rm docker.tgz \
&& docker -v
ARG TARGETARCH=amd64
ARG AGENT_VERSION=2.194.0
WORKDIR /azp
RUN if [ "$TARGETARCH" = "amd64" ]; then \
AZP_AGENTPACKAGE_URL=https://vstsagentpackage.azureedge.net/agent/${AGENT_VERSION}/vsts-agent-linux-x64-${AGENT_VERSION}.tar.gz; \
else \
AZP_AGENTPACKAGE_URL=https://vstsagentpackage.azureedge.net/agent/${AGENT_VERSION}/vsts-agent-linux-${TARGETARCH}-${AGENT_VERSION}.tar.gz; \
fi; \
curl -LsS "$AZP_AGENTPACKAGE_URL" | tar -xz
COPY ./start.sh .
RUN chmod +x start.sh
ENTRYPOINT [ "./start.sh" ]
EOF
# Dockerfile の一番最後で呼ばれるシェルスクリプトを作成します
cat << "EOF" > start.sh
#!/bin/bash
set -e
if [ -z "$AZP_URL" ]; then
echo 1>&2 "error: missing AZP_URL environment variable"
exit 1
fi
if [ -z "$AZP_TOKEN_FILE" ]; then
if [ -z "$AZP_TOKEN" ]; then
echo 1>&2 "error: missing AZP_TOKEN environment variable"
exit 1
fi
AZP_TOKEN_FILE=/azp/.token
echo -n $AZP_TOKEN > "$AZP_TOKEN_FILE"
fi
unset AZP_TOKEN
if [ -n "$AZP_WORK" ]; then
mkdir -p "$AZP_WORK"
fi
export AGENT_ALLOW_RUNASROOT="1"
cleanup() {
if [ -e config.sh ]; then
print_header "Cleanup. Removing Azure Pipelines agent..."
# If the agent has some running jobs, the configuration removal process will fail.
# So, give it some time to finish the job.
while true; do
./config.sh remove --unattended --auth PAT --token $(cat "$AZP_TOKEN_FILE") && break
echo "Retrying in 30 seconds..."
sleep 30
done
fi
}
print_header() {
lightcyan='\033[1;36m'
nocolor='\033[0m'
echo -e "${lightcyan}$1${nocolor}"
}
# Let the agent ignore the token env variables
export VSO_AGENT_IGNORE=AZP_TOKEN,AZP_TOKEN_FILE
source ./env.sh
print_header "1. Configuring Azure Pipelines agent..."
./config.sh --unattended \
--agent "${AZP_AGENT_NAME:-$(hostname)}" \
--url "$AZP_URL" \
--auth PAT \
--token $(cat "$AZP_TOKEN_FILE") \
--pool "${AZP_POOL:-Default}" \
--work "${AZP_WORK:-_work}" \
--replace \
--acceptTeeEula & wait $!
print_header "2. Running Azure Pipelines agent..."
trap 'cleanup; exit 0' EXIT
trap 'cleanup; exit 130' INT
trap 'cleanup; exit 143' TERM
# To be aware of TERM and INT signals call run.sh
# Running it with the --once flag at the end will shut down the agent after the build is executed
./run.sh "$@" &
wait $!
EOF
# コンテナイメージを作成します
docker build -t devopsagent:latest .
# セルフホステッドエージェントを起動します
docker run -d \
-e AZP_URL=$azpurl \
-e AZP_TOKEN=$azptoke \
-e AZP_AGENT_NAME=$(hostname)-devopsagent \
--name $(hostname)-devopsagent \
-v /var/run/docker.sock:/var/run/docker.sock \
devopsagent:latest
# エージェントのログを確認します
docker logs -f $(hostname)-devopsagent
作成したセルフホステッドエージェントでパイプラインを実行
bash
# VM からログアウトします
exit
# azure-pipelines.yml を更新
cat <<EOF > azure-pipelines.yml
trigger:
- master
pool: default
variables:
imageName: ${prefix}
steps:
- task: Docker@2
displayName: Build an image
inputs:
repository: \$(imageName)
command: build
Dockerfile: Dockerfile
EOF
# azure-pipelines.yml を Git リポジトリに登録します
git add azure-pipelines.yml
git commit -m update
git push
# パイプラインの実行状況を確認します
az pipelines runs list \
--output table
# 最初のパイプラインの詳細を確認します
az pipelines runs show \
--id 2 \
--output table
# ブラウザーでビルド結果ページを開きます
az pipelines runs show \
--id 2 \
--open
参考
bash
# リソースグループを削除します
az group delete \
--name ${prefix}-rg
# Azure DevOps のプロジェクトを削除します
az devops project delete \
--id $(az devops project show \
--project ${prefix} \
--query id \
--output tsv)
# Azure CLI に追加した拡張機能を削除します
az extension remove \
--name azure-devops
https://docs.microsoft.com/ja-jp/azure/devops/pipelines/agents/docker?view=azure-devops