Azure での Docker コンテナーのデプロイ
読む時間の目安: 8 分
概要
Docker Azure 統合は、Azure コンテナーインスタンス(Azure Container Instances; ACI) の中で、ネイティブな Docker コマンドの利用を可能にします。 これを使って、クラウドに適したアプリケーションを構築し実行します。 この新たな仕組みによって、Docker Desktop と Microsoft Azure の緊密な統合が実現され、開発者にとっては、Docker CLI や VS Code 拡張機能を使ったアプリケーション実行が即座にできるようになり、またローカル開発環境とクラウドデプロイ環境をシームレスに切り替えることができます。
さらに Docker と Microsoft の開発技術の統合により、開発者が Docker CLI を用いる際には、以下のことが可能になります。
- Azure に簡単にログインすることができます。
- 1 つの Docker コマンドに対して ACI コンテキストを設定することができます。 これによってローカルコンテキストとクラウドコンテキストを切り替えられるようになり、アプリケーションの実行をすばやく簡単に行うことができます。
- Compose を利用すれば、単一コンテナーアプリケーション、複数コンテナーアプリケーションの開発を単純化できます。 開発者にとってはクラウドコンテナーサービスに対して、シームレスな Docker 完全互換コマンドの実行が初めて可能になります。
ACI においてサポートされているコンテナー機能の一覧 や ACI においてサポートされている Compose 機能の一覧 も参照してください。
前提条件
Docker コンテナーを Azure にデプロイするには、以下の条件を満たしていることが必要です。
-
Docker Desktop 最新版をダウンロードしインストールしていることが必要です。
あるいは Docker ACI Integration for Linux をインストールしていることが必要です。
-
Azure サブスクリプションを持っていることが必要です。 Azure free account にアクセスして取得操作を進めることができます。
ACI での Docker コンテナー実行
Docker は、単にローカルのコンテナーを実行するだけのものではなくなります。
docker run
を使って ACI 上の Docker コンテナーをシームレスにデプロイできます。
あるいは Compose ファイルに定義されたマルチコンテナーのアプリケーションをdocker compose up
コマンドを使ってデプロイできるようになります。
以下の節では ACI 上において Docker コンテナーをデプロイする手順を説明します。 ACI においてサポートされているコンテナー機能の一覧 も参照してください。
Azure へのログイン
以下のコマンドを実行して Azure にログインします。
$ docker login azure
ここからブラウザーが開いて Azure のログイン情報の入力が求められます。 Docker CLI からブラウザーが開かない場合は、そこから Azure デバイスコードフロー へ進み、手動で接続します。 なお Azure コマンドライン のログインは Docker CLI Azure ログインからは切り離されています。
これとは別に、対話形式でない方法(スクリプトや継続的インテグレーションの利用時)でのログインも可能です。
その場合には Azure サービスプリンシパルを利用しdocker login azure --client-id xx --client-secret yy --tenant-id zz
のようにコマンド実行します。
メモ
Azure サービスプロバイダーを通じたログインでは、アクセストークンの有効期間は短いもの(通常は 1 時間)になっています。 だからといって、このトークンを自動的、透過的に更新することはできません。 サービスプロバイダーを利用したログイン中にそのアクセストークンの有効期間が過ぎた場合は、手動で再ログインしなければなりません。
Azure 上に複数のテナントを有している場合、--tenant-id
オプションを単独で用いることもできます。
ACI コンテキストの生成
ログインした後は、ACI においてコンテナーをデプロイできるようにするために、ACI に関する Docker コンテキストを生成することが必要です。
ACI コンテキストの生成には Azure サブスクリプション、リソースグループ、地域設定が必要です。
たとえば新たなコンテキストとしてmyacicontext
を生成することにします。
$ docker context create aci myacicontext
このコマンドは自動的に Azure ログイン情報を利用して、サブスクリプション ID やリソースグループを識別するものです。
コマンド実行においては、利用するサブスクリプションやグループを対話的に選択します。
必要であれば CLI の以下のようなフラグ--subscription-id
、--resource-group
、--location
を使って指定することもできます。
Azure アカウントにおいてリソースグループを 1 つも生成していない場合、docker context create aci myacicontext
コマンドの実行によって、リソースグループが生成されます。
その際には特別なオプションを設定する必要はありません。
ACI コンテキストを生成したら、docker context ls
コマンドを実行して Docker コンテキストの一覧を確認します。
NAME TYPE DESCRIPTION DOCKER ENDPOINT KUBERNETES ENDPOINT ORCHESTRATOR
myacicontext aci myResourceGroupGTA@eastus
default * moby Current DOCKER_HOST based configuration unix:///var/run/docker.sock swarm
コンテナーの実行
ログインを済ませて ACI コンテキストも生成したので、ACI 上にコンテナーをデプロイするための Docker コマンド操作を進めていきます。
新しく生成した ACI コンテキストを利用する方法は 2 つあります。
1 つは Docker コマンドにおいて--context
フラグを利用する方法です。
新たに生成した ACI コンテキストをここに指定して、コマンド実行を行います。
$ docker --context myacicontext run -p 80:80 nginx
もう 1 つはdocker context use
を使ってコンテキストを切り替える方法です。
Docker コマンドの実行にあたって、対象とするコンテキストを ACI コンテキストとします。
たとえばdocker context use
コマンドを利用して、Nginx コンテナーをデプロイしてみます。
$ docker context use myacicontext
$ docker run -p 80:80 nginx
コンテキストをmyacicontext
に切り替えたら、docker ps
を使って ACI 上に動作するコンテナー一覧を確認することができます。
上に示した Nginx コンテナーの利用例において ps コマンドの出力結果にある「PORTS」カラムには、コンテナーが動作している IP アドレスとポートが表示されます。
たとえば52.154.202.35:80->80/tcp
のような表示です。
そしてブラウザーからhttp://52.154.202.35
にアクセスすれば、Nginx の Welcome ページが開きます。
コンテナーからログを確認するには以下を実行します。
$ docker logs <コンテナーID>
実行中のコンテナーにおいてコマンドを実行するには、以下のようにします。
$ docker exec -t <コンテナーID> COMMAND
ACI 上のコンテナーを停止して削除するには、以下のようにします。
$ docker stop <コンテナーID>
$ docker rm <コンテナーID>
コンテナーの削除にはdocker rm
を用います。
コンテナーが実行中である場合には--force
フラグをつける必要があります。
あるいは削除の前にdocker stop
を実行してコンテナーを停止させておくことが必要です。
メモ
ACI 上においてコンテナーを再起動する意味は、ローカル環境においてローカルな Docker コンテキストを利用している場合とは異なります。 ACI の場合、コンテナーはいったん初期状態にリセットされ、新たなノードとして起動されます。 これはつまり、コンテナー内のファイルシステムにおいて、ボリューム内に保存されていない状態があったとしたら、再起動時にそれらは失われるということです。
Compose アプリケーションの実行
ACI に対しては、Compose ファイルにて定義されたマルチコンテナーアプリケーションのデプロイと管理も可能です。
その際にはdocker compose
コマンドを利用します。
同一の Compose アプリケーション内にあるコンテナーは、すべて同一のコンテナーグループ内において起動されます。
コンテナー間におけるサービス検出は、Compose ファイル内に指定されたサービス名を用いて行われます。
コンテナー間における名前解決は、/etc/hosts
ファイル内にサービス名を記述することによって実現されます。
/etc/hosts
ファイルは、コンテナーグループ内であればすべてのコンテナーが自動的に共有します。
ACI においてサポートされている Compose 機能の一覧 も参照してください。
-
ACI コンテキストを利用していることが必要です。 これは
--context myacicontext
フラグを指定するか、あるいはデフォルトのコンテキストを設定するコマンドdocker context use myacicontext
を実行します。 -
docker compose up
とdocker compose down
を実行して、Compose アプリケーションの開始、停止ができることが必要です。
デフォルトにおいてdocker compose up
は、カレントフォルダーのdocker-compose.yaml
ファイルを利用します。
ワーキングディレクトリは --workdir フラグにより指定することができます。
また Compose ファイルを直接docker compose --file mycomposefile.yaml up
と指定することもできます。
Compose アプリケーションのデプロイの際に--project-name
フラグを使って、アプリケーション名を指定することもできます。
アプリケーション名の指定がなかった場合は、ワーキングディレクトリから名前が定められます。
Compose アプリケーションの一部として起動したコンテナーは、docker ps
を実行した際に、単一のコンテナーとともに表示されます。
そのコンテナーの ID は<Composeプロジェクト>_<サービス>
という書式です。
こういったコンテナーは、個別に停止、起動、削除を行うことはできません。
これらは同一の ACI コンテナーグループを構成する一部であるからです。
各コンテナーのログはdocker logs
を使って参照します。
デプロイを行った Compose アプリケーションの一覧はdocker compose ls
を実行します。
この場合の一覧には Compose アプリケーションのみが表示され、docker run
によって起動した単一のコンテナーは表示されません。
Compose アプリケーションを削除するにはdocker compose down
を実行します。
メモ
現時点の Docker Azure 統合では、Compose アプリケーションを構成するコンテナーからのログを、すべて集めて取得するようなことはできません。
アプリケーションの更新
デプロイされた Compose アプリケーションに対しては、同一のプロジェクト名を用いて、docker compose --project-name PROJECT up
のようにアプリケーションの再デプロイを行い、アプリケーションの更新を行うことができます。
アプリケーションを更新すると ACI ノードは再利用されます。 そして公開ポートに割り当てられていた IP アドレスは、どのようなものであっても同一値が維持されます。 ACI においては、既存アプリケーションへのアップデート内容によって制限が発生するものがあります(たとえば CPU/メモリの予約確保量を制限することはできません)。 その場合は、アプリケーションを新たに一からデプロイすることが必要です。
すでにデプロイされた Compose ファイルに対してdocker compose up
を実行すれば、アプリケーションを更新するのがデフォルトの動作です。
そのときにはデフォルトで、Compose ファイルがあるディレクトリ名から Compose プロジェクト名を取り出します。
Compose アプリケーションを完全にリセットしたいのであれば、再度docker compose up
を実行する前に、明示的にdocker compose down
を実行することが必要です。
リソースの解放
単独のコンテナーや Compose アプリケーションはdocker prune
コマンドを使って ACI から削除することができます。
docker prune
コマンドは、現在実行されていないデプロイ内容を削除します。
実行中のデプロイ内容を削除するには--force
を指定します。
--dry-run
オプションを使えば、削除予定のデプロイ一覧が表示されます。
ただしこれは実際に削除を行うものではありません。
$ ./bin/docker --context acicontext prune --dry-run --force
Resources that would be deleted:
my-application
Total CPUs reclaimed: 2.01, total memory reclaimed: 2.30 GB
ポートの公開
単独のコンテナーや Compose アプリケーションは、オプションとしてポートを公開することができます。
単独のコンテナーの場合は、docker run
コマンドに--publish
(-p
)フラグをつけてdocker run -p 80:80 nginx
のように実行します。
また Compose アプリケーションの場合は、Compose ファイルのサービス定義において、公開するポートを設定する必要があります。
services:
nginx:
image: nginx
ports:
- "80:80"
メモ
ACI ではポートマッピングを行うことはできません(つまりポート公開においてポート番号を変更することはできません)。 したがって ACI へのデプロイにあたって公開元も公開先も同一のポートでなければなりません。
Compose アプリケーション内に含まれるコンテナーはすべて、同一の ACI コンテナーグループとしてデプロイされます。 同一の Compose アプリケーション内の異なるコンテナーは、ACI へのデプロイに際して同一のポートを公開することはできません。
アプリケーションにおいてポート公開を行う際には、デプロイするアプリケーション(単独のコンテナーまたは Compose アプリケーション)に対応するコンテナーグループに対して、ランダムな公開 IP アドレスが関連づけられるのがデフォルトです。
この IP アドレスはdocker ps
を使ってコンテナーを一覧表示したり、docker inspect
を実行したりしたときに確認することができます。
DNS ラベル名
ランダムな IP アドレスに対するポート公開に加えて、アプリケーションを FQDN の形式で公開するための DNS ラベル名を指定することができます。
たとえば<NAME>.region.azurecontainer.io
という形式です。
この名前はdocker run
の実行時に--domainname
フラグを用いて設定します。
あるいは Compose ファイル内のdomainname
項目を利用してdocker compose up
により実現します。
services:
nginx:
image: nginx
domainname: "myapp"
ports:
- "80:80"
メモ
複数のサービスに対して
domainname
を設定していたとしても、Compose アプリケーションのドメイン設定が行われるのは一度だけです。 したがってそれらは同一でなければなりません。FQDN である
<DOMAINNAME>.region.azurecontainer.io
が利用可能です。
ACI コンテナー内での Azure ファイル共有のボリュームとしての利用
コンテナーや Compose アプリケーションにおいてボリュームを使ったデータ保存を行っている場合でも、デプロイすることが可能です。 Azure ファイル共有を使えば、ACI コンテナーに対してのボリュームをサポートしています。
既存の Azure ファイル共有を利用して、ストレージアカウント名 がmystorageaccount
、ファイル共有名がmyfileshare
であるとしたときに、デプロイにおけるrun
コマンド実行を以下のように指定できます。
$ docker run -v mystorageaccount/myfileshare:/target/path myimage
これにより実行中のコンテナーからは、ファイル共有内容は/target/path
に見えるようになります。
Compose アプリケーションにおいて、ボリュームの指定は Compose ファイル内において以下のような文法に従う必要があります。
myservice:
image: nginx
volumes:
- mydata:/mount/testvolumes
volumes:
mydata:
driver: azure_file
driver_opts:
share_name: myfileshare
storage_account_name: mystorageaccount
メモ
Compose ファイル内においては、ボリュームを短い文法で記述することはできません。 ボリューム定義というものは、ローカルのバインドマウント向けを目的としているためです。 Compose ファイルにおいては、ボリュームドライバーやそのオプションを利用すれば、ボリューム定義がより明確になります。
単一または複数コンテナーのデプロイにおいて Docker CLI は、Azure ストレージアカウントに対する鍵情報を取得するために Azure ログインを行います。
そしてこの鍵をコンテナーデプロイ情報に利用します。
こうしてコンテナーがボリュームにアクセスできるようになります。
Azure ログインによってアクセスするストレージアカウント内であれば、ボリュームはどのファイル共有からでも利用できます。
ボリュームマウントの際にはrw
(読み書き)またはro
(読み取り専用)を指定します(デフォルトはrw
です)。
Azure ボリュームの管理
ACI Docker コンテキストを利用して、コンテナーや Compose アプリケーション内で用いるボリュームを生成するには、docker volume create
コマンドを実行します。
そこで Azure ストレージアカウント名とファイル共有名を指定します。
$ docker --context aci volume create test-volume --storage-account mystorageaccount
[+] Running 2/2
⠿ mystorageaccount Created 26.2s
⠿ test-volume Created 0.9s
mystorageaccount/test-volume
ストレージアカウントが存在しない場合、このコマンドがデフォルト SKU として 標準 LRS を利用してストレージアカウントを新規生成します。 そしてリソースグループや Docker ACI コンテキストに関連するディレクトリを生成します。
既存のストレージアカウントを指定した場合、このコマンドはそのアカウント内にファイル共有を新規生成します。
$ docker --context aci volume create test-volume2 --storage-account mystorageaccount
[+] Running 2/2
⠿ mystorageaccount Use existing 0.7s
⠿ test-volume2 Created 0.7s
mystorageaccount/test-volume2
別の方法として Azure ストレージアカウントを生成するか、
Azure ポータル、つまりaz
コマンドライン を用いてファイル共有を生成することができます。
コンテナーや Compose アプリケーションにおいて利用可能なボリュームの一覧を確認することができます。
$ docker --context aci volume ls
ID DESCRIPTION
mystorageaccount/test-volume Fileshare test-volume in mystorageaccount storage account
mystorageaccount/test-volume2 Fileshare test-volume2 in mystorageaccount storage account
ボリュームと対応する Azure ファイル共有を削除するにはvolume rm
コマンドを実行します。
$ docker --context aci volume rm mystorageaccount/test-volume
mystorageaccount/test-volume
これによって Azure ファイル共有とこれに関連するデータは、完全に削除されます。
Azure においてボリュームを削除するとこのコマンドは、指定されたファイル共有が、そのストレージアカウントにおいてのみ利用されているファイル共有であるかどうかをチェックします。
そのストレージアカウントがdocker volume create
コマンドによって作り出されたものである場合、docker volume rm
コマンドは、ストレージアカウントがファイル共有を持っていなければ、ストレージアカウントも削除します。
逆にストレージアカウントが(たとえば Azure ポータルやaz
コマンドを使った場合のように)docker volume create
以外において生成されたものである場合は、docker volume rm
はストレージアカウントを削除しません。
そのアカウントが一つのファイル共有も残っていなかったとしてもです。
環境変数
docker run
の実行時には、--env
フラグを利用して ACI コンテナーに環境変数を受け渡すことができます。
Compose アプリケーションの場合は、Compose ファイル内においてサービス項目environment
またはenv-file
において環境変数を指定するか、あるいはコマンドラインフラグ--environment
を利用して指定します。
ヘルスチェック
コンテナーのヘルスチェックを行うことができます。
docker run
の実行においては--healthcheck-
をプレフィックスに持つフラグを利用します。
また Compose ファイルにおいては、そのサービスのhealthcheck
セクションを利用します。
ヘルスチェックは ACI のLivenessProbe
に変換されます。
ACI ではヘルスチェックコマンドを定期的に実行します。
チェックに失敗したとき、そのコンテナーは停止されます。
したがってヘルスチェックには再起動ポリシーを含めて利用することが必要であり、コンテナーの停止後に再起動させることが必要です。
docker run
におけるデフォルトの再起動ポリシーはno
であり、これはコンテナーを再起動しません。
Compose に対するデフォルトの再起動ポリシーはany
であり、これは常にサービスコンテナーを再起動します。
docker run
の実行例は以下のとおりです。
$ docker --context acicontext run -p 80:80 --restart always --health-cmd "curl http://localhost:80" --health-interval 3s nginx
Compose ファイルの利用例は以下のとおりです。
services:
web:
image: nginx
deploy:
restart_policy:
condition: on-failure
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:80"]
interval: 10s
プライベートな Docker Hub イメージと Azure コンテナーレジストリの利用
どのようなコンテナーレジストリにホストされている ACI であっても、プライベートイメージをデプロイすることができます。
docker run
やdocker compose up
を実行するためには、その前にdocker login
を使ってそのレジストリにログインしておくことが必要です。
Docker CLI では、デプロイイメージに対するレジストリログイン情報を取得した上で、資格情報やイメージデプロイ情報を ACI に送信します。
Azure コンテナーレジストリ(Azure Container Registry; ACR)の場合は、Azure ログインから ACR へのログインを自動的に行います。
Azure ログインから ACR へのアクセスができていれば、わざわざ ACR レジストリへのログインを手動で行う必要はなくなります。
名前空間としての ACI リソースグループの利用
ACI に関連づける Docker コンテキストは、複数用意することができます。
個々のコンテキストは、一意の Azure リソースグループに関連づいていることが必要です。
こうしておくと Docker コンテキストを名前空間として利用することができます。
docker context use <CONTEXT>
を実行することで、複数の名前空間を切り替えることができます。
docker ps
コマンドを実行すると、現在の Docker コンテキスト内にあるコンテナーのみが一覧表示されます。
Docker コンテキストが異なれば、コンテナー名や Compose アプリケーション名が同一であっても、競合することにはなりません。
Linux における Docker Compose CLI のインストール
Docker Compose CLI は、Azure コンテナーインスタンス(ACI)上でのコンテナー実行と管理をサポートします。
インストールの前提条件
インストールスクリプト
新たな CLI は、インストールスクリプトを利用してインストールします。
$ curl -L https://raw.githubusercontent.com/docker/compose-cli/main/scripts/install/install_linux.sh | sh
手動インストール
Docker ACI 統合の CLI は、最新版 ページからダウンロードすることができます。
入手したらこれを実行可能にします。
$ chmod +x docker-aci
ローカルの Docker Engine の利用を有効にするため、そして既存の Docker コンテキストを利用可能にするため、既存の Docker CLI はcom.docker.cli
として、パス上のどこかに配置する必要があります。
$ ln -s /path/to/existing/docker /directory/in/PATH/com.docker.cli
メモ
環境変数
PATH
は、複数ディレクトリをコロンで区切るものであり、左にあるものが優先されます。 内容を確認するにはecho $PATH
を実行します。 既存の Docker CLI へのパスはwhich docker
を使って確認できます。 なお上のリンクを生成する際には root 権限を要するかもしれません。
Docker Engine が インストール されている Ubuntu 20.04 の場合、初期状態では以下のようになっています。
$ echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin
$ which docker
/usr/bin/docker
$ sudo ln -s /usr/bin/docker /usr/local/bin/com.docker.cli
新しい CLI が動作しているかどうかを確認するには、デフォルトのコンテキストを使って CLI を実行します。
$ ./docker-aci --context default ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
$ echo $?
0
ACI と統合された CLI を、デフォルトの Docker CLI とするためには、PATH
上のディレクトリにおいて、既存の Docker CLI よりも優先されるようなディレクトリに移動させる必要があります。
再び Ubuntu 20.04 の例を見ます。
$ which docker
/usr/bin/docker
$ echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin
$ sudo mv docker-aci /usr/local/bin/docker
$ which docker
/usr/local/bin/docker
$ docker version
...
Azure integration 0.1.4
...
サポートされているコマンド
Docker ACI 統合の CLI をインストールしたら、--help
をつけてコマンド実行し、この時点でのコマンド一覧を確認します。
アンインストール
Docker Azure 統合の CLI を削除する場合は、ダウンロードしたバイナリとcom.docker.cli
をPATH
上から削除します。
スクリプトを通じてインストールを行った場合は、以下により削除することができます。
$ sudo rm /usr/local/bin/docker /usr/local/bin/com.docker.cli
フィードバック
Docker Azure 統合ベータ版を利用していただき、ありがとうございます。 みなさんからのフィードバックが大変重要です。 フィードバックをいただくには、Github レポジトリ compose-cli に issue をあげてください。
Docker, Azure, Integration, ACI, context, Compose, cli, deploy, containers, cloud