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 の無料トライアル にご登録ください。
すばらしいコーディングができますように!
Fikayo Adepoju は、Web とモバイル テクノロジー、DevOps に精通した LinkedIn Learning (Lynda.com) 講師、フルスタック開発者、テクニカル ライター、テクニカル コンテンツ クリエイターです。スケーラブルな分散アプリケーション開発については 10 年以上の経験を持っています。 CircleCI、Twilio、Auth0、The New Stack のブログで 40 以上の記事を執筆するほか、個人の Medium ページでも情報を発信しており、役立つ知識を多くの開発者に広めることに専心しています。 また、Udemy で動画形式のコース (英語) も開講しています。ぜひご覧ください。