Dev Container Build and Run とは?
Azure DevOpsの拡張機能として提供されており、
Azure PipelinesでDev Containersのコンテナをビルド、Azure Container Registryにイメージをpushするタスクが利用できます。
Dev Containersはクライアント環境でビルドされたそれぞれのコンテナ イメージを利用するシナリオが多いですが、
ビルドをAzure上で実行させ利用者(開発者)はビルドされたイメージをpullするだけになり、より固定的な環境として開発チーム内で共通化する事ができます。
Dev Containersは開発環境をコンテナ上で構築する事により、セットアップ手順の省力化やチーム内での共通化、他のプロジェクトに影響のない環境の独立化など、様々なメリットのあるVisual Stucio Code 開発環境のソリューションの1つです。
ここではDev Containersについての詳しい説明は割愛します。
前提
説明では、Azure DevOps(Repos、Pipelines)、Azure Container Registryを利用しているものとします。
プロジェクト
リポジトリ
DevOps 拡張機能
以下機能が提供されます。
- PipelineでのDevcontainersCiタスクの実行
- Pipeline エディタ上でのDevcontainersCiタスクの追加
ライセンス
MIT
Azure DevOpsへの拡張機能のインストール
Dev Containers 作成
-
Azure Reposに新しいリポジトリを作成し、
.devcontainers/devcontainer.jsonを作成、リポジトリにpush
(Debian 環境を作る例).devcontainer/devcontainer.json// For format details, see https://aka.ms/devcontainer.json. For config options, see the // README at: https://github.com/devcontainers/templates/tree/main/src/debian { "name": "Debian", // Or use a Dockerfile or Docker Compose file. More info: https://containers.dev/guide/dockerfile "image": "mcr.microsoft.com/devcontainers/base:bullseye" // Features to add to the dev container. More info: https://containers.dev/features. // "features": {}, // Use 'forwardPorts' to make a list of ports inside the container available locally. // "forwardPorts": [], // Configure tool-specific properties. // "customizations": {}, // Uncomment to connect as root instead. More info: https://aka.ms/dev-containers-non-root. // "remoteUser": "root" }チュートリアル: Developing inside a Container using Visual Studio Code Remote Development
パイプライン 作成
パイプラインがContainer Registryにpushするためのトークンを作成
新しいパイプラインを作成
-
azure-pipelines.ymlファイルが作成されるので、scriptにdocker loginのコマンドと環境変数ACR_TOKENの設定を記述する。
docker loginの-uパラメータ(ユーザー名)にはContainer Registryに作成したトークンの名前、-pパラメータ(パスワード)に変数ACR_TOKENを指定azure-pipelines.yml# Starter pipeline # Start with a minimal pipeline that you can customize to build and deploy your code. # Add steps that build, run tests, deploy, and more: # https://aka.ms/yaml trigger: - main pool: vmImage: ubuntu-latest steps: - script: | docker login -u build-container -p $ACR_TOKEN yourregistry.azurecr.io displayName: 'Log in to Container Registry' env: ACR_TOKEN: $(ACR_TOKEN)
Devcontainers CI Taskの追加
-
設定内容は下記の"設定値"に反映されるため、記述式がわかる場合にはこの対話形式を利用する必要はありません。
項目 設定値 入力値 入力例 Image name (including registry) imageName イメージの名前(レジストリ含む) yourregistry.azurecr.io/example-dev-containerOne or more comma-separated image tags (defaults to latest) imageTag pushされるイメージに設定されるタグ 1.0,latestPlatforms for which the image should be built.
If omitted, defaults to the platform of the Azure DevOps Agent.
Multiple platforms should be comma separated.platform Multiplatform Dev Container Builds linux/amd64,linux/arm64Specify the command to run after building the dev container image runCmd コンテナー イメージのビルド後に実行するコマンド make ci-buildSpecify a child folder (containing a .devcontainer) instead of using the repository root subFolder .devcontainerフォルダーを含むフォルダーへのリポジトリ ルートからの相対パスfolderBSpecify environment variables to pass to the docker run command env 実行時に開発コンテナに渡す環境変数 ACR_TOKEN: $(ACR_TOKEN)Control when images are pushed to the registry push filterに設定すると、sourceBranchFilterForPush、buildReasonsForPush、及びpushOnFailedBuildの条件が満たされた場合にイメージがpushされる。imageNameが設定されている場合は既定でfilterNever push( never)
Push if buildReasonsForPush, sourceBranchFilterForPush, and pushOnFailedBuild conditions are met(filter)
Always push(always)☑Control whether to push the image on failed builds (if push==filter) pushOnFailedBuild ビルド失敗時にpushを実行するかどうか Set the Build Reasons that should trigger a push of the dev container image (if push=filter).
Defaults to Manual, IndividualCI, BatchedCI.
(see https://docs.microsoft.com/en-us/azure/devops/pipelines/build/variables?view=azure-devops&viewFallbackFrom=vsts&tabs=yaml)buildReasonsForPush レジストリにpushできる Build.Reason 値を指定 ManualInidividualCISet the source branches (e.g. refs/heads/main) that are allowed to trigger a push of the dev container image (if push=filter).
Leave empty to allow all.sourceBranchFilterForPush レジストリにpushされるブランチの指定
(※main等ではなく、refs等からコミット ハッシュの書き込まれている箇所を指定する必要があります)refs/heads/main☑For non-root Dev Containers (i.e. where remoteUseris specified), the action attempts to make the container user UID and GID match those of the host user. Set this to true to skip this step (defaults to false)skipContainerUserIdUpdate ルート以外の Dev Container( remoteUserが指定されている)場合、コンテナー ユーザーのユーザーIDとグループIDをホスト ユーザーのものと一致させるSpecify additional images to use for build caching cacheFrom ビルド キャッシュに使用する追加のイメージを指定 ☑Builds the image with --no-cache(takes precedence overcacheFrom)noCache ビルドに --no-cacheオプションを指定 -
YAMLファイルに
DevcontainersCiのタスクが追加される。azure-pipelines.yml# Starter pipeline # Start with a minimal pipeline that you can customize to build and deploy your code. # Add steps that build, run tests, deploy, and more: # https://aka.ms/yaml trigger: - main pool: vmImage: ubuntu-latest steps: - script: | docker login -u build-container -p $ACR_TOKEN yourregistry.azurecr.io displayName: 'Log in to Container Registry' env: ACR_TOKEN: $(ACR_TOKEN) - task: DevcontainersCi@0 inputs: imageName: 'yourregistry.azurecr.io/debian' push: 'filter' sourceBranchFilterForPush: 'refs/heads/main' displayName: 'Run a DevcontainersCi' -
Name に変数名を指定、Keep this value secret にチェックを入れ、Value にContainer Registryに作成したトークンのパスワードを入力し、OKをクリック

パイプライン 実行
バージョン タグについて
パイプライン タスク内でカウンタが利用できます。
以下のように設定すれば、latestのタグを最新のイメージに更新、ver_major.ver_minorの値でタグが設定される。
ver_majorは 1、ver_minorはver_majorが変化するまで0からインクリメントされ、
ver_majorが 2 等に変化するとver_minorは 0 にリセットされる。
variables:
ver_major: 1
ver_minor: $[counter(variables['ver_major'], 0)]
- task: DevcontainersCi@0
inputs:
# ...
imageTag: '$(ver_major).$(ver_minor),latest'
# ...
参考
Pipelineで利用する変数、式について
Visual Studio Codeでの利用
WSL+Ubuntu の場合
-
Dev ContainerはContainer Registryのイメージを利用するように変更します。
.devcontainer/devcontainer.json{ "name": "Debian", "image": "yourregistry.azurecr.io/debian/releases:latest" } -
Azure CLIを利用し、Azureにログイン
az acr | Microsoft Learn$ az acr login --name (Container Registry名) -
Visual Studio Codeを起動
$ cd (リポジトリ クローン先ディレクトリ) $ code .
応用
Pull Requestでmain以外のブランチでも実行してみたい。
でもその時にバージョンがインクリメントされたら困る。
そのような場合のテクニック
- main ブランチ以外への push は Pipeline でトリガしない。
但し、Manual Run で実行は可能。 - マイナー バージョン番号はブランチ別に管理
- main ブランチの更新は releases ディレクトリに push
- Dev Container は devcontainer-build ディレクトリで開発
- 開発者の Dev Container は Azure Container Registry のイメージを使用
{
"name": "Debian",
"image": "yourregistry.azurecr.io/debian/releases:latest"
}
{
"name": "Debian",
"image": "mcr.microsoft.com/devcontainers/base:bullseye"
}
trigger:
branches:
include:
# IndividualCI をトリガするのは main のみ (Manual は他のブランチも実行可能)
- main
paths:
include:
# トリガ対象のディレクトリ
- devcontainer-build/*
pool:
vmImage: ubuntu-latest
variables:
ver_major: 1
# ブランチ名.(major) 別に minor のカウンタを管理
ver_minor: $[counter(format('{0}.{1}', variables['Build.SourceBranch'], variables['ver_major']), 0)]
${{ if eq(variables['Build.SourceBranchName'], 'main') }}:
# main ブランチの更新は releases に push
stage: 'releases'
${{ else }}:
# main ブランチ以外はブランチ名に push
stage: '$(Build.SourceBranchName)'
steps:
- script: |
docker login -u build-container -p $ACR_TOKEN yourregistry.azurecr.io
displayName: 'Log in to Container Registry'
env:
# Container Registry のトークン(パスワードは環境変数で管理)
ACR_TOKEN: $(ACR_TOKEN)
- task: DevcontainersCi@0
inputs:
# ステージ別のディレクトリに push
imageName: 'yourregistry.azurecr.io/debian/$(stage)'
# インクリメントされるバージョンを設定、latest を更新
imageTag: '$(ver_major).$(ver_minor),latest'
# ビルド対象のディレクトリ
subFolder: 'devcontainer-build'
displayName: 'Run a DevcontainersCi'
その他
Azure DevOpsに拡張機能をインストールする事により、これらの機能が提供されます。
拡張機能のバージョンが指定できない事により、破壊的変更があった場合の対応や
提供終了された場合の対応等は、考慮する必要があるかもしれません。
(但し幸いにも、プロジェクトはオープンソース、ライセンスはMITとなっています)



























