Azure Container Registry (ACR) は、Microsoft 独自のDocker イメージ ホスト プラットフォームです。ACR はプライベートなレジストリであり、プライベート docker コンテナ イメージや関連成果物の保存と管理を行えます。保存されているイメージは、プルしてローカルで実行することも、各種ホスティング プラットフォームへのコンテナ ベースでのデプロイに活用することもできます。

このチュートリアルでは、カスタム docker イメージを作成して、Azure Container Registry への継続的デプロイを行う方法について説明します。

前提条件

このチュートリアルを進めるには、いくつかの準備が必要です。

  1. Node.js (バージョン 10.3 以上) をローカル システムにインストールする
  2. Azure アカウントを用意する
  3. CircleCIアカウントを用意する
  4. GitHub アカウントを用意する
  5. Azure CLI をローカル システムにインストールする
  6. Docker をローカル システムにインストールする

これらのインストールとセットアップが済んだら、チュートリアルを始めましょう。

Azure 上にコンテナ レジストリを作成する

まず、Docker コンテナの保存およびビルド先となるコンテナ レジストリを Azure 上に作成する必要があります。Azure portal のホーム ページで [作成] ボタンをクリックして、[コンテナー][コンテナー レジストリ] の順に移動します。

Azure registryの作成

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

Create registry Page - Azure

[確認および作成] ボタンをクリックします。確認ページでレジストリ情報を確認し、[作成] をクリックしてレジストリ作成プロセスを開始します。

リソースの作成に 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 にアクセスすると確認できます。

App Local Run - Browser

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

App Local Run - Browser

このイメージをレジストリに取得するために、以下のコマンドを実行して Dockerfile に基づいて ACR でイメージをビルドします。なお、<container_registry_name> は自分のレジストリ名に置き替えて下さい。

az acr build --registry <container_registry_name> --image customnodeimage .

これで、レジストリにこのイメージが表示されるようになりました。Azure リソース ページでレジストリをクリックします。Azure portal ホーム ページ[最近のリソース] にイメージが表示されます。 [サービス][リポジトリ] の順に移動します。

ACRのイラスト

コンテナ用のビルド タスクをセットアップする

アプリケーション コードまたは Dockerfile が更新された場合に、その更新をプッシュして ACR でビルドし、ACR上に常に最新のイメージが存在するようにしたいと思います。つまり継続的デプロイメントです。

さいわい、ACR はリモート リポジトリ上のブランチを監視して、そのブランチの更新に応じてビルドをトリガーするように構成できます。イメージの継続的デプロイメント戦略は次のとおりです。ACRで監視しビルドのトリガーとするブランチを、イメージのリモート リポジトリ上に作成します。アプリケーション テストに合格したら、監視対象のブランチに自動的に更新をプッシュして、更新後のコンテンツを使用したイメージの再ビルドをトリガーします。

それでは、作業を始めましょう。プロジェクトのルートでコマンド rm -rf .git を実行して、既存の git 履歴を削除します。その後、そのプロジェクトを GitHub にプッシュします。

次に、GitHub リポジトリで、メイン ブランチから buildimage ブランチを作成します。

ブラントの作成 - GitHub

作成したブランチを監視するには、ACR タスクが必要です。 この ACR タスクを作成するには、GitHub パーソナル アクセス トークンが必要です。

GitHub トークンを作成するには、GitHub ページで [Settings (設定)][Developer Settings (開発者設定)] の順に移動します。サイド メニューで [Personal access tokens (パーソナル アクセス トークン)] をクリックした後、 [Generate new token (新しいトークンを生成)] ボタンをクリックします。確認のためパスワードを入力すると、トークン作成ページに移動します。

キーの説明を入力します。このデモでは、すべての repo 権限 (delete_repo権限を除く) を付与します。また、webhook 権限も付与します。この webhook が最も重要な権限です。これによって、新しい Docker イメージのビルド開始シグナルを ACR に送信する Webhook をリポジトリに作成できるようになるからです。

GitHubのトークンイラスト

[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 イメージを再ビルドします。新しく作成したタスクを表示するには、レジストリ ページにアクセスして [サービス][タスク] の順に移動します。

ACR タスク - Azure

CircleCI プロジェクトを作成する

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

CircleCIにプロジェクトを追加

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

コンフィグの追加 - CircleCI

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

Build Prompt - CircleCI

[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(ユーザー キーの追加)] ボタンが表示されます。

ユーザーAPIキーの追加

デプロイ パイプラインで後ほど使用するフィンガープリントが生成されます。フィンガープリントをコピーして、安全な場所に保管します。

フィンガープリントはパイプライン スクリプトで 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 Image build running

しばらくすると、ビルドが完了し、[成功] としてマークされます。

[サービス][リポジトリ] の順に移動してイメージを表示し、クリックすると、[最終更新日] が変化して、新しいビルドが最新であることが示されます。

まとめ

Azure Container Registry を利用すると、コンテナ イメージを格納して、コンテナ ワークロードをすばやく、スケーラブルに取得できるようになります。このチュートリアルでは、カスタム docker イメージを作成しました。そして、アプリケーション コードまたは Dockerfile が変更されるたびに、そのイメージを ACR に継続的にデプロイするよう構成ししました。ここで学んだ内容を業務に応用するため、 ぜひCircleCI の無料トライアル にご登録ください。

すばらしいコーディングができますように!


Fikayo Adepojuは、Web とモバイル テクノロジー、DevOps に精通したフルスタック開発者、テクニカル ライター、テクニカル コンテンツ クリエイターです。スケーラブルな分散アプリケーション開発については 10 年以上の経験を持っています。CircleCI、Twilio、Auth0、The New Stack のブログで 40 以上の記事を執筆するほか、個人の Medium ページでも情報を発信しており、役立つ知識を多くの開発者に広めることに専心しています。また、Udemyで動画形式のコースも開講しています。ぜひご覧ください。