Azure Container Registry にカスタム イメージを継続的にデプロイする方法
フルスタック デベロッパー兼テクニカル ライター
Azure Container Registry (ACR) は、Microsoft 独自のDocker イメージ ホスト プラットフォームです。ACR はプライベートなレジストリであり、プライベート docker コンテナ イメージや関連成果物の保存と管理を行えます。保存されているイメージは、プルしてローカルで実行することも、各種ホスティング プラットフォームへのコンテナ ベースでのデプロイに活用することもできます。
このチュートリアルでは、カスタム docker イメージを作成して、Azure Container Registry への継続的デプロイを行う方法について説明します。
前提条件
このチュートリアルを進めるには、いくつかの準備が必要です。
- Node.js (バージョン 10.3 以上) をローカル システムにインストールする
- Azure アカウントを用意する
- CircleCIアカウントを用意する
- GitHub アカウントを用意する
- Azure CLI をローカル システムにインストールする
- Docker をローカル システムにインストールする
これらのインストールとセットアップが済んだら、チュートリアルを始めましょう。
Azure 上にコンテナ レジストリを作成する
まず、Docker コンテナの保存およびビルド先となるコンテナ レジストリを Azure 上に作成する必要があります。Azure portal のホーム ページで [作成] ボタンをクリックして、[コンテナー]、 [コンテナー レジストリ] の順に移動します。

レジストリの作成ページで、レジストリの名前をはじめ、該当する情報を入力します。

[確認および作成] ボタンをクリックします。確認ページでレジストリ情報を確認し、[作成] をクリックしてレジストリ作成プロセスを開始します。
リソースの作成に Azure CLI を使用する場合は、次のコマンドでレジストリを作成することもできます。
az acr create --name circlecigwpregistry --resource-group Demos-Group --sku standard --admin-enabled true
今回は、レジストリに circlecigwpregistry という名前を付けています。前に述べたように、別の名前を使いたい場合は、このチュートリアルのすべてのステップでレジストリ名を置き替えてください。
デモ プロジェクトをクローンする
次は、Docker コンテナのビルドと Azure Container Registry でのホストに使用する Node.js プロジェクトを取得します。以下のコマンドを実行して、プロジェクトをクローンします。
git clone --single-branch --branch base-project https://github.com/CIRCLECI-GWP/azure-custom-images.git
このプロジェクトは基本的な Node.js API であり、次の 2 つのエンドポイントを持ちます。
- ルート エンドポイント(
/): ようこそメッセージを出力するだけのエンドポイントです。 /todosエンドポイント:todoタスク オブジェクトの配列を返します。また、/todosエンドポイントをテストするためのテスト スイートを含みます。
カスタム Docker イメージを作成しビルドする
次は、アプリケーションをホストするためのカスタム Docker イメージを記述します。プロジェクト フォルダーのルートに移動して (cd azure-custom-images)、Dockerfile ファイルを作成します。ファイルに、以下のコードを記述します。
FROM node:current-alpine
WORKDIR /app
COPY ./package.json ./
RUN npm install
COPY ./ ./
CMD ["npm", "start"]
この docker ファイルでは、node:current-alpine をベース イメージとして使用し、(このイメージを基に作成される) コンテナ内の作業ディレクトリを /appに設定しています。まずpackage.jsonファイルを /app にプルし、npm installを使用して依存関係をインストールします。最後に、プロジェクトの残りのコンテンツをイメージにコピーし、実行時に npm start でアプリケーションを起動します。Docker イメージとコンテナに関する詳細は、こちらのページを参照してください。
以下のコマンドをプロジェクトのルートで実行し、customnodeimageという名前のタグを付けてイメージをビルドします。
docker build -t customnodeimage .
コマンド末尾のピリオド (.) に注意してください。これは、ビルド コンテキストが現在のディレクトリにあると定義するものですので、省略しないようにしてください。
ビルドが完了したら、以下のコマンドを実行して、customnodeimage Docker イメージを基にしたコンテナとして Node.js アプリケーションを実行します。
docker run -p 1337:1337 customnodeimage
CLI には、このコマンドの出力として、Server running on localhost:1337 という行が表示されます。これは、アプリケーションが実行中であることを示します。
上記コマンドは、コンテナのアプリケーション ポート (1337) をマシンのポート 1337 に転送します。アプリケーションのベース エンドポイントは、http://localhost:1337 にアクセスすると確認できます。

また、/todos ルートにアクセスすると、todo オブジェクトを読み込むことができます。

このイメージをレジストリに取得するために、以下のコマンドを実行して Dockerfile に基づいて ACR でイメージをビルドします。なお、<container_registry_name> は自分のレジストリ名に置き替えて下さい。
az acr build --registry <container_registry_name> --image customnodeimage .
これで、レジストリにこのイメージが表示されるようになりました。Azure リソース ページでレジストリをクリックします。Azure portal ホーム ページの [最近のリソース] にイメージが表示されます。 [サービス]、 [リポジトリ] の順に移動します。

コンテナ用のビルド タスクをセットアップする
アプリケーション コードまたは Dockerfile が更新された場合に、その更新をプッシュして ACR でビルドし、ACR上に常に最新のイメージが存在するようにしたいと思います。つまり継続的デプロイメントです。
さいわい、ACR はリモート リポジトリ上のブランチを監視して、そのブランチの更新に応じてビルドをトリガーするように構成できます。イメージの継続的デプロイメント戦略は次のとおりです。ACRで監視しビルドのトリガーとするブランチを、イメージのリモート リポジトリ上に作成します。アプリケーション テストに合格したら、監視対象のブランチに自動的に更新をプッシュして、更新後のコンテンツを使用したイメージの再ビルドをトリガーします。
それでは、作業を始めましょう。プロジェクトのルートでコマンド rm -rf .git を実行して、既存の git 履歴を削除します。その後、そのプロジェクトを GitHub にプッシュします。
次に、GitHub リポジトリで、メイン ブランチから buildimage ブランチを作成します。

作成したブランチを監視するには、ACR タスクが必要です。 この ACR タスクを作成するには、GitHub パーソナル アクセス トークンが必要です。
GitHub トークンを作成するには、GitHub ページで [Settings (設定)] 、[Developer Settings (開発者設定)] の順に移動します。サイド メニューで [Personal access tokens (パーソナル アクセス トークン)] をクリックした後、 [Generate new token (新しいトークンを生成)] ボタンをクリックします。確認のためパスワードを入力すると、トークン作成ページに移動します。
キーの説明を入力します。このデモでは、すべての repo 権限 (delete_repo権限を除く) を付与します。また、webhook 権限も付与します。この webhook が最も重要な権限です。これによって、新しい Docker イメージのビルド開始シグナルを ACR に送信する Webhook をリポジトリに作成できるようになるからです。

[Generate token (トークンを生成)] ボタンをクリックします。生成が完了したら、トークンをコピーします。トークンが再度表示されることはありません。
ACR タスクを作成するために、プロジェクトのルートで、リポジトリ アドレス、リポジトリ名、GitHub アクセス トークンを指定して以下のコマンドを実行します。
az acr task create --registry <container_registry_name> --name buildcustomimage --image customnodeimage --context <your_github_repo>#buildimage --file Dockerfile --git-access-token <access_token>
このチュートリアルのレジストリとリポジトリを指定した場合、コマンドは以下のようになります。
az acr task create --registry circlecigwpregistry --name buildcustomimage --image customnodeimage --context https://github.com/CIRCLECI-GWP/azure-custom-images.git#buildimage --file Dockerfile --git-access-token [My_TOKEN]
これで、buildcustomimage タスクが作成されます。このタスクでは、buildimage ブランチに更新がプッシュされるたびに、customnodeimage イメージを再ビルドします。新しく作成したタスクを表示するには、レジストリ ページにアクセスして [サービス] 、[タスク] の順に移動します。

CircleCI プロジェクトを作成する
CircleCI ダッシュボードの [Projects(プロジェクト)] ページに移動します。このチュートリアルで使用している GitHub アカウントを選択して、プロジェクトを追加します。

[Set Up Project(プロジェクトをセットアップ)] ボタンをクリックして、情報の追加を始めます。

セットアップ ページで、表示されたサンプルを無視して設定ファイルを手動で追加するため、[Use Existing Config(既存の設定ファイルを使用する)] をクリックします。パイプラインの設定ファイルをダウンロードするのか、ビルドを開始するのかを確認するメッセージが表示されます。

[Start Building(ビルドを開始)] をクリックして、ビルドを開始します。設定ファイルのセットアップがまだのため、このビルドは失敗します。このタスクは、チュートリアル後半で行います。
GitHub 認証をセットアップする
継続的デプロイメント戦略の次の一手として、このプロジェクト用に作成したパイプライン設定ファイルから buildimage ブランチへのプッシュを行います。そのため、CircleCI が GitHub 上のリポジトリにアクセスするための認証済みアクセスが必要になります。
さいわい、CircleCI では、このようなアクセスを可能にするユーザー API キーを追加できます。プロジェクトで、 [Project Settings(プロジェクト設定)] 、 [SSH Keys(SSH キー)] の順に移動し、 [User Key (ユーザー キー)] セクションまでスクロールします。GitHub に接続するために、[Authorize with GitHub(GitHub で承認)] ボタンをクリックします。
この手順が完了すると、[User API Key (ユーザー API キー)] セクションに [Add User Key(ユーザー キーの追加)] ボタンが表示されます。

デプロイ パイプラインで後ほど使用するフィンガープリントが生成されます。フィンガープリントをコピーして、安全な場所に保管します。
フィンガープリントはパイプライン スクリプトで GitHub のメール アドレスおよびユーザー名と一緒に使用するので、環境変数に格納するのが安全です。プロジェクト設定のサイド メニューで [Environment Variables (環境変数)] をクリックして、以下を追加します。
GITHUB_EMAIL: 接続先の GitHub アカウントのメール アドレスGITHUB_USERNAME: GitHub のユーザー名GITHUB_FINGERPRINT: 生成した認証フィンガープリント
パイプライン スクリプトを作成する
このチュートリアルの最後の作業は、カスタム docker イメージ用の継続的デプロイメント パイプライン スクリプトを作成することです。
パイプライン スクリプトから更新を GitHub リポジトリの buildimage ブランチにプッシュするために、Node パッケージ gh-pages を使用します。このパッケージは、任意のリポジトリのブランチから別のブランチにファイルをプッシュするように構成できます。
プロジェクトのルートで以下のコマンドを実行して、パッケージを開発用依存関係としてインストールします。
npm install gh-pages --save-dev
次に、以下の pushtobuild スクリプトを package.json ファイルに追加します。
"scripts" : {
.....,
"pushtobuild": "npx gh-pages -b buildimage --message '[skip ci] Updates' -d ./"
}
このスクリプトは、npx を使用して gh-pages 呼び出し、main ブランチのファイルを buildimage ブランチにプッシュします。--message パラメーターに [skip ci] Updates という値を追加することで、このブランチに変更がプッシュされたときに CircleCI がパイプラインを再実行しないようにしています。
これで、パイプライン スクリプトの作成に着手できます。プロジェクトのルートに .circleci という名前のフォルダーを作成します。このフォルダーの中に、config.yml いう名前のファイルを作成します。 config.yml に、以下を入力します。
version: 2
jobs:
build:
working_directory: ~/repo
docker:
- image: circleci/node:10.16.3
steps:
- checkout
- run:
name: npm のアップデート
command: "sudo npm install -g npm@5"
- restore_cache:
key: dependency-cache-{{ checksum "package-lock.json" }}
- run:
name: パッケージのインストール
command: npm install
- save_cache:
key: dependency-cache-{{ checksum "package-lock.json" }}
paths:
- ./node_modules
- run:
name: テストの実行
command: npm run test
deploy:
working_directory: ~/repo
docker:
- image: circleci/node:10.16.3
steps:
- checkout
- run:
name: Github 認証情報の構成
command: |
git config user.email $GITHUB_EMAIL
git config user.name $GITHUB_USERNAME
- add_ssh_keys:
fingerprints:
- $GITHUB_FINGERPRINT
- run:
name: Azure Container Registry にイメージをビルドするタスク
command: npm run pushtobuild
workflows:
version: 2
build:
jobs:
- build
- deploy:
requires:
- build # ビルド ジョブが完了したときのみデプロイ
filters:
branches:
only: main # メイン ブランチでのみデプロイ
このファイルは、2 つの jobs (ジョブ) を持つワークフローを定義しています。
build ジョブは、 リモート リポジトリからコードをチェックアウトし、必要な依存関係をインストールして、テストを実行してコードにバグが含まれていないことを確認します。 build ジョブが完了したら、deploy ジョブが引き継いで、コードのクリーン コピーをチェックアウトします node_modules フォルダーは監視対象のブランチにプッシュしません)。その後、GitHub へのアクセスを構成して、パイプライン スクリプトから更新を監視対象のブランチ(buildimage)にプッシュできるようにします。最後に、deploy ジョブが Node.js スクリプトを実行して更新をプッシュし、docker イメージの新しいビルドをトリガーします。
これで、更新をコミットして GitHub リポジトリにプッシュしたら、ワークフローが成功します。

build ジョブをクリックすると、テストに合格したことを確認できます。

プロセスの詳細を確認するには、deploy ジョブをクリックします (ブラウザーで、1 ページ戻ります)。

レジストリ タスクに移動 ([サービス] 、[タスク] の順に移動)して、[実行] タブをクリックします。ビルドが実行中であると表示されます。

しばらくすると、ビルドが完了し、[成功] としてマークされます。
[サービス] 、[リポジトリ] の順に移動してイメージを表示し、クリックすると、[最終更新日] が変化して、新しいビルドが最新であることが示されます。
まとめ
Azure Container Registry を利用すると、コンテナ イメージを格納して、コンテナ ワークロードをすばやく、スケーラブルに取得できるようになります。このチュートリアルでは、カスタム docker イメージを作成しました。そして、アプリケーション コードまたは Dockerfile が変更されるたびに、そのイメージを ACR に継続的にデプロイするよう構成ししました。ここで学んだ内容を業務に応用するため、 ぜひCircleCI の無料トライアル にご登録ください。
すばらしいコーディングができますように!