LoginSignup
0
1

More than 1 year has passed since last update.

Azure DevOps のセルフホステッド Linux エージェントを Docker で起動してその中で Docker ビルドしてみた

Posted at

背景と目的

以前こちらの記事を書きました。今回はセルフホステッド 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

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1