概要
ACR(コンテナレジストリ)にコンテナイメージをプッシュして、ACI(コンテナインスタンス)で実行してみます。
Azure Container Registry(ACR)とは
Microsoft Azureが提供するコンテナイメージを安全かつ効率的に管理&保管できるレジストリサービスです。
そもそもコンテナのイメージとは
コンテナのイメージは、アプリケーションを実行するのにアプリケーションのコード、ランタイム、ライブラリ、設定ファイルなどがパッケージ化されたものです。ACIなどのコンテナ実行サービスは、このイメージを元にコンテナを実行します。実行環境を含めてパッケージされているため、プラットフォームや環境が異なる場合でも同じように動作するので大変便利です。
ACRの料金
2023年12月現在、Basicプランで1日約25円程度掛かります。
Azure Container Instances(ACI)とは
Azure Container Instances(ACI)は、Azureの環境でコンテナを実行するためのサービスです。ACIを利用すれば、物理サーバを管理することなくクラウド上でコンテナを作成・デプロイ・実行&停止することができます。これらの操作は、Azure PortalやAzure CLIから簡単に実施可能です。
ACIは、ACRなどのコンテナレジストリサービスからイメージをプルしてコンテナを実行します。
ACIでは、ACR以外のコンテナイメージのレジストリサービス(DockerHub, Amazon ECRなど)も使用することができます。しかし、同じAzureサービスのACRの相性が良いため、特別な理由がない限りACRを使うのが一般的です。
料金
ACIの料金は、使用時間(秒単位)とCPUコア数やメモリ量によって決まります。
CPUコア数やメモリ量を増やせば増やすほど、秒単価も高くなります。
ハンズオン
ACRとACIの概要説明が終わりましたので、ここからは実際にコンテナを実行してみます。
次の手順で進めて行きます。
- コンテナで実行するサンプルアプリケーションを準備する
- ACRを作成する
- ACRへイメージをプッシュする
- ACIがACRからイメージをプルするロールを準備する
- ACIでコンテナを実行する
サンプルアプリケーションの準備
Node.jsで"Hello, World!"を表示するだけの簡単なアプリケーションです。
const http = require('http');
const server = http.createServer((req, res) => {
res.writeHead(200, {'Content-Type': 'text/plain; charset=utf-8'});
res.end('Hello, World!\n');
});
const port = 8080;
server.listen(port, () => {
console.log(`Server running at ${port} port/`);
});
# Node.jsのLTSバージョンを使用
FROM node:lts
# アプリケーションディレクトリを作成
WORKDIR /usr/src/app
# アプリケーションの依存関係をインストール
COPY package*.json ./
RUN npm install
# アプリケーションのソースをバンドル
COPY . .
# ポート8080で実行
EXPOSE 8080
CMD [ "node", "app.js" ]
まずはローカルPCで挙動を確認してみます。
$ npm init
$ npm install http
# test-node-appという名前を付けてビルドします
$ docker build -t test-node-app .
# イメージが作成されたことを確認します
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
test-node-app latest ********** 2 minutes ago 1.1GB
# コンテナを起動します
$ docker run -p 8080:8080 -d test-node-app
# コンテナの起動を確認します
$ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
******** test-node-app "docker-entrypoint.s…" 5 minutes ago Up 5 minutes 0.0.0.0:8080->8080/tcp upbeat_leavitt
ブラウザでhttp://localhost:8080/
を打ち込むと「Hello World!」が表示されるのを確認できました。
ACRリソースを作成する
まず、コンテナイメージをプッシュする先であるレジストリを作成する必要がありますので、ACRのリソースを作って行きます。
Azure portalからACRリソースを作成します。
まず、コンテナレジストリのページに遷移します。portalで「レジストリ」と検索すると出てきます。
作成ボタンを押し、以下の内容を入力します。
基本 | ||
---|---|---|
リソースグループ | rg-acr-dev(新規作成/任意の名前) | |
レジストリ名 | acrdevys(任意の名前) | 英数字のみの5~50文字の制限あり |
場所 | Japan East | |
料金プラン | Basic | 1番安いプランを選択 |
ネットワーク | ||
---|---|---|
接続の構成 | パブリックアクセス(全てのネットワーク) | Basicプランではパブリックしか選択できません |
プライベートはPremiumプランでのみ選択できます。
「確認および作成」タブまで進み、作成ボタンを押します。
新しいACRが作成されました。
ACRへコンテナイメージをプッシュする
ACRへのコンテナイメージプッシュは、Azure CLIを使って行います。
Azureにログインする
まず、Azure CLIを使ってAzureにログインします。
$ az login
A web browser has been opened at https://login.microsoftonline.com/organizations/oauth2/v2.0/authorize. Please continue the login in the web browser. If no web browser is available or if the web browser fails to open, use device code flow with `az login --use-device-code`.
ブラウザが立ち上がるので認証を済ませます。
ログインしたユーザー情報が表示されたらログイン完了です。
[
{
"cloudName": "AzureCloud",
"homeTenantId": "***",
"id": "***",
"isDefault": true,
"managedByTenants": [],
"name": "Azure サブスクリプション 1",
"state": "Enabled",
"tenantId": "***",
"user": {
"name": "***",
"type": "user"
}
}
]
ロールを確認する
この後実施する作業は、以下のロールが割り当てられたユーザーで実施する必要があります。
- AcrPush ロール: 名前の通り、ACRへコンテナイメージをプッシュする権限です
ここでは、権限の強い所有者ロールを割り当てられたユーザーを用いて以下の作業を実施します。
※ 実環境では、所有者のような強権限のロールを持つユーザーで作業することは推奨されません。必要なロールのみを付与したユーザーで作業することを検討してください(最小権限の原則)。
イメージをACRにプッシュする
先ほど作成したコンテナレジストリ(ACR)にイメージをプッシュします。
これは、az acr build
コマンドを使って行います。
az acr build
コマンドは、ローカルコードをビルドして、ビルドの成果物(コンテナイメージ)をACRにプッシュするコマンドです。
# Dockerfileを含む今回のプロジェクトのディレクトリに移動します
$ cd node
$ az acr build --image node-app:v1.0.0 --registry acrdevys .
--imageオプションで、ビルドして生成されるイメージの名前やタグを指定します。イメージの名前:タグ
の形式で指定できます。
--registryオプションでは、先ほど作成したACRのリソース名を指定します。
$ az acr build --image node-app:v1.0.0 --registry acrdevys .
....
2023/12/02 02:21:12 Successfully pushed image: acrdevys.azurecr.io/node-app:v1.0.0
2023/12/02 02:21:12 Step ID: build marked as successful (elapsed time in seconds: 31.661096)
2023/12/02 02:21:12 Populating digests for step ID: build...
2023/12/02 02:21:13 Successfully populated digests for step ID: build
2023/12/02 02:21:13 Step ID: push marked as successful (elapsed time in seconds: 39.552949)
2023/12/02 02:21:13 The following dependencies were found:
2023/12/02 02:21:13
- image:
registry: acrdevys.azurecr.io
repository: node-app
tag: v1.0.0
digest: sha256:****
runtime-dependency:
registry: registry.hub.docker.com
repository: library/node
tag: lts
digest: sha256::****
git: {}
Run ID: ce1 was successful after 1m15s
このコマンドを実行すると、以下のことが行われます。
- ローカルのソースコード(Dockerfile含む)がACRにアップロードされる
- アップロードされたローカルコードがビルドされ、コンテナイメージが生成される
- 生成されたコンテナイメージを--registryで指定したレジストリにプッシュする
コンテナレジストリ > サービス > リポジトリを確認すると、今ビルド&プッシュをしたイメージ(node-app:v1.0.0)が確認できます。
ACIがACRからコンテナイメージをプルする権限を準備する
前提
この後、ACIを使ってコンテナを実行していきます。
コンテナ実行時、ACIはACRのイメージをプル(ダウンロード)するため、ACIにはイメージをプルする権限が必要です。
ここでは、この認証をマネージドIDを使用して行います。
マネージドIDを作成する
Azure Portalで「マネージドID」のページに行き、作成ボタンを押します。
基本 | ||
---|---|---|
リソースグループ | rg-acr-dev | |
リージョン | Japan East | |
名前 | aci-image-pull-id |
上記の条件で、マネージドIDを作成します。
マネージドIDが作成されました。
マネージドIDにACRのイメージをプルする権限を付与する
コンテナレジストリのページに行き、アクセス制御(IAM)を選択します。
ロールの割り当ての追加を押します。
AcrPullを選択し、「次へ」を押します。
アクセスの割り当て先で「マネージドID」を選択し、「メンバーを選択する」を押します。先ほど作成したマネージドID(aci-image-pull-id
)を選択します。
「レビューと割り当て」を押します。
アクセス制御 (IAM)を確認すると、今追加した「ユーザー割り当てマネージド ID」が反映されていることが分かります。
コンテナを実行する
Azure CLIから実行する
Azure CLIのaz container create
コマンドでACIを作成し、コンテナを実行します。
$ az container create \
--name node-app-container \
--resource-group rg-acr-dev \
--image acrdevys.azurecr.io/node-app:v1.0.0 \
--assign-identity [ユーザー割り当てマネージドIDのリソースID] \
# ACRへのアクセスに使用されるマネージドIDを指定
--acr-identity [ユーザー割り当てマネージドIDのリソースID] \
# コンテナー再起動ポリシーを指定
--restart-policy Never \
--ip-address Public \
--ports 80
ユーザー割り当てマネージドIDのリソースIDは、以下のコマンドやPortal(管理 > プロパティ)で確認できます。
$ az identity show --name <マネージドIDの名前> --resource-group <リソースグループ名> --query id
--restart-policy
は、コンテナー再起動ポリシーを指定するものです。
しばらく時間が掛かりますが、コンテナ作成が終わると以下のようなJSONが返却されます。
{
"confidentialComputeProperties": null,
"containers": [
{
"command": null,
"environmentVariables": [],
"image": "acrdevys.azurecr.io/node-app:v1.0.0",
"instanceView": {
....以下略
Azure PortalのACIのページに行くと、今作成したnode-app-container
が作成されていることを確認できます。
ステータスは実行中になっています。
アプリ側で出力したログも確認できました。
続いて、コンテナにブラウザからアクセスしてみます。
http://{コンテナのIPアドレス}:80
をブラウザに打ち込みます。コンテナのIPアドレスは、Portalから確認できます。また、コンテナ作成時に返却されたJSONにもIPアドレスが記載されています。
アクセスできませんでした。
ACIにはDockerで使用されるようなポートマッピング機能がありません。必ず、コンテナ内のポートと外部に公開するポートを一致させる必要があります。
今回のケースでは、コンテナ内のポートを8080
に設定しています。そのため、コンテナ作成時に指定するポートも8080
である必要がありました。指定ポートを8080
に変更の上、再度コンテナを実行します。
先ほど作成したコンテナを削除します。コンテナの削除は、Portalから実施します。
az container create
でACIを作成し、コンテナを実行します。
$ az container create \
--name node-app-container \
--resource-group rg-acr-dev \
--image acrdevys.azurecr.io/node-app:v1.0.0 \
--assign-identity [ユーザー割り当てマネージドIDのリソースID] \
--acr-identity [ユーザー割り当てマネージドIDのリソースID] \
--restart-policy Never \
--ip-address Public \
--ports 8080 # コンテナ内のポートと一致させる
http://{コンテナのIPアドレス}:8080
にアクセスします。
今度は、期待通りHello, World!
が表示されました。
動作を確認できたので、コンテナインスタンスは削除しておきます。
アプリを修正して再デプロイする
おさらいの意味も込めて、アプリケーションの内容を変更して、再度デプロイし、コンテナを実行してみます。
アプリケーションに変更を加える
アプリケーションコードを修正し、表示する文字列を変えます。
const server = http.createServer((req, res) => {
res.writeHead(200, {'Content-Type': 'text/plain; charset=utf-8'});
// 表示する文字列を変更する
res.end('コンテナインスタンス実行中です。\n');
});
ACRにコンテナイメージをプッシュする
アプリケーションに変更を加えたので、この内容でビルドし、コンテナイメージをACRにプッシュします。
バージョンもv1.0.0
から v1.0.1
に変更しておきます。
# Dockerfileのあるディレクトリに移動してから実施します
$ cd node
# バージョンを v1.0.0 から v1.0.1 に上げます
$ az acr build --image node-app:v1.0.1 --registry acrdevys .
コンテナイメージを確認する
PortalのACRのページに行きます。
今追加したv1.0.1
が追加されていることを確認できます。
なお、以下のコマンドでもイメージのタグ一覧を確認できます。
$ az acr repository show-tags --name acrdevys --repository node-app --output table
Result
--------
v1.0.0
v1.0.1
コンテナを実行する
az container create
でACIを作成し、コンテナを実行します。
$ az container create \
--name node-app-container \
--resource-group rg-acr-dev \
# 今追加した新しいバージョンを指定します
--image acrdevys.azurecr.io/node-app:v1.0.1 \
--assign-identity [ユーザー割り当てマネージドIDのリソースID] \
--acr-identity [ユーザー割り当てマネージドIDのリソースID] \
--restart-policy Never \
--ip-address Public \
--ports 8080
http://{コンテナのIPアドレス}:8080
にアクセスします。
すると、今加えた変更が反映されたのが分かります。
今回の作業で掛かった料金
ACR
今回はBasicプランを選択したので、1日24.64円掛かりました。
注意点
- 作成したままにしておくと、月額750円ほど掛かります。終わったら必ず、コンテナレジストリ自体を削除するのを忘れないでください。
- 今回選択したプランはBasicです。Basicよりも上のプランを選択すればさらに追加の料金が掛かります。Container Registry の価格
ACI
今回の検証で5,6回ACIを作成しましたが、総額14.70円でした。
「勉強のために少しだけ動かしてみる」という用途であれば、許容できる金額に収まりそうです。
注意点
- ACIは、使用時間に応じて料金が掛かります。余計な課金を防ぐため、不要なインスタンスは削除してください。
- 今回、ACIは
1 vCPU と 1.5 GB
で実行しました。これより上のスペックを指定した場合、さらに料金が掛かります。
CPUやメモリは、ACI作成時に返却されるJSONデータのresources
で確認できます。
コンテナ作成時に何も指定しない場合、デフォルト値の1 vCPU と 1.5 GB
が指定されます。
"resources": {
"limits": null,
"requests": {
"cpu": 1.0,
"gpu": null,
"memoryInGb": 1.5
}
}