Amazon ECR に Windows コンテナの Docker イメージを保存する前に考慮したいこと
Windows コンテナの実行基盤としてAWSでは Amazon ECS(ECS on EC2)と、AWS Fargate の2つが提供されています。共に Windows コンテナのイメージは Amazon ECR で管理することが多いかと思います。
意外に気付かない点なのですが、Windows コンテナ実行(タスク起動)するときに ECR から Docker イメージを Pull すると同時に Microsoft Container Registry(MCR) からも Pull します。
Windows OS イメージの仕様と ECR だけで完結させるにはどうすればよいのか紹介します。
どうしてこうなった?
ECR のドキュメントに理由について以下の記載があります。
要はライセンスの都合で Windows の全イメージレイヤーを ECR に Push できません。
Images based on the Windows operating system include artifacts that are restricted by license from being distributed. By default, when you push Windows images to an Amazon ECR repository, the layers that include these artifacts are not pushed as they are considered foreign layers. When the artifacts are provided by Microsoft, the foreign layers are retrieved from Microsoft Azure infrastructure.
ECR 外にイメージがあると困るケース
配布制限のあるレイヤーを外部の Microsoft Container Registry(MCR) から取得するためにインターネットアクセスが発生します。パブリックアクセスが禁止されていたり、制限されているネットワーク環境下ですとインターネット経由で必要なレイヤーを取得できません。
例として NAT Gateway がなくプライベートサブネットからのインターネットアクセスはできなく、ECR へは VPCエンドポイントを設置することで通信経路を確保したとしましょう。これだと Windows コンテナは起動できません。Microsoft Container Registry(MCR) へアクセスするインターネットへの経路がなくコンテナ起動に至りません。
対処
同じく ECR のドキュメントに対処方法と、注意事項について記載があります。
対処方法
Dockerデーモンに--allow-nondistributable-artifacts
フラグをセットすることで、本来 Microsoft Container Registry(MCR)に保存されている配布制限のあるレイヤーも含めてすべて ECR へ Psuhできます。これで必要なアクセス経路を ECR のみで完結させることができます。
It is possible to override this behavior when pushing Windows images to Amazon ECR by using the --allow-nondistributable-artifacts flag in the Docker daemon. When enabled, this flag will push the licensed layers to Amazon ECR which enables these images to be pulled from Amazon ECR via the VPC endpoint without additional access to Azure being required.
Dockerデーモンにフラグをセットする方法は動作検証の項で紹介します。
注意事項
ECR に全レイヤーを保存することはできますがあくまでも自分の環境内での使用のみ許可されています。ライセンスを守らなくてよいとは言っていなく、パブリックでの配布や、再配布をしてはいけないと記載があります。
Using the --allow-nondistributable-artifacts flag does not preclude your obligation to comply with the terms of the Windows container base image license; you cannot post Windows content for public or third-party redistribution. Usage within your own environment is allowed.
検証環境
Windows の Fargate 環境です。
Product | Version |
---|---|
OS Famliy | Windows Server 2019 Full |
Fargate platform | 1.0.0 |
Dockerイメージ
IIS のイメージに自前のindex.html
に入れ替えます。
FROM mcr.microsoft.com/windows/servercore/iis RUN powershell -NoProfile -Command Remove-Item -Recurse C:\inetpub\wwwroot\* WORKDIR /inetpub/wwwroot COPY content/ .
index.html
の内容はただのテストページです。
<html> <head> <title>AWS Fargate Sample Windows App</title> <style> body { margin-top: 40px; background-color: rgb(42, 6, 173); } </style> </head> <body> <div style=color:white;text-align:center> <h1>AWS Fargate Sample Windows App</h1> <p>Your application is now running on a container in AWS Fargate.</p>⏎
動作検証してみた
Windows の Fargate と ECR の組み合わせで Windows コンテナを実行した際の挙動を確認します。
VPCエンドポイントあり構成と、ECR に全レイヤー格納してVPCエンドポイントあり構成の紹介が本編です。
インターネットアクセス許可構成
NAT Gateway を配置しプライベートサブネットからインターネットアクセスを許可した構成です。
項目 | 設定値 |
---|---|
NAT Gateway | あり |
VPCエンドポイント | なし |
Docker イメージ | Dockerデーモンのフラグ未設定 |
タスク起動結果 | 成功 |
Let's Try
docker build
コマンドで Docker イメージを作成します。
docker build -t sample-windows-iis .
作成した Docker イメージに ECR のリポジトリ名でlatest
タグを付けます。
docker tag sample-windows-iis:latest 123456789012.dkr.ecr.ap-northeast-1.amazonaws.com/sample-windows-iis:latest
普通に docker push
コマンドで ECR へ Docker イメージを Push しました。
docker push 123456789012.dkr.ecr.ap-northeast-1.amazonaws.com/sample-windows-iis:latest
76.45 MBの軽量な Docker イメージを ECR から確認できました。
Windows の Fargate で 123456789012.dkr.ecr.ap-northeast-1.amazonaws.com/sample-windows-iis:latest
の Docker イメージを指定してタスクを起動しました。ちなみに ELB のバックエンドで起動する IIS の Windowsコンテナです。
ELB の DNS 名に Web ブラウザからアクセスして Dockerfile で指定した content/index.html
の内容を確認できます。
MCR と ECR から Pull したのかは確認できませんが問題なくタスク起動に成功しました。
インターネットアクセス不可構成
NAT Gateway をなくしプライベートサブネットからインターネットアクセスを禁止した構成です。
項目 | 設定値 |
---|---|
NAT Gateway | なし |
VPCエンドポイント | なし |
Docker イメージ | Dockerデーモンのフラグ未設定 |
タスク起動結果 | 失敗 |
Let's Try
新しいタスクを起動しようとすると、ECR へもアクセスできないため Pull できずにタスクの起動に失敗します。
停止理由 ResourceInitializationError: unable to pull secrets or registry auth: pull command failed: : exit status 1
ここまでは想像通りだったと思います次からが本編です。
VPCエンドポイントあり構成
NAT Gateway をなくしたまま、ECR への VPCエンドポイントを用意しました。依然としてプライベートサブネットからインターネットアクセスを禁止した構成です。いよいよ核心に迫ります。
項目 | 設定値 |
---|---|
NAT Gateway | なし |
VPCエンドポイント | あり |
Docker イメージ | Dockerデーモンのフラグ未設定 |
タスク起動結果 | 失敗 |
Let's Try
インターネットアクセス不可構成とはエラーメッセージが変わり、`https://mcr.microsoft.com/v2/windows/servercore/blobs/...`へアクセスしようとしているのが確認できます。ECR へは VPCエンドポイント経由でアクセスできますが、Microsoft Container Registry(MCR)へはインターネット経由のアクセスが必要になり失敗しています。
停止理由 CannotPullContainerError: ref pull has been retried 5 time(s): failed to copy: httpReadSeeker: failed open: failed to do request: Get https://mcr.microsoft.com/v2/windows/servercore/blobs/sha256:567fd00846e9a9f44eea5925b497356dda00fe89b8335d2a3b2a8b9d8...
必要なレイヤーが揃わないのでタスク起動に失敗しました。
ECR に全レイヤー格納してVPCエンドポイントあり構成
VPCエンドポイントはありますが依然としてプライベートサブネットからインターネットアクセスを禁止した構成です。Docker デーモンにフラグをセットして ECR へ Docker イメージを Push し直してから試します。
項目 | 設定値 |
---|---|
NAT Gateway | なし |
VPCエンドポイント | あり |
Docker イメージ | Dockerデーモンのフラグあり |
タスク起動結果 | 成功 |
以下を参考にDockerデーモンのコンフィグファイルを編集します。
C:\ProgramData\docker\config
フォルダを開きdaemon.json
ファイルを新規作成しました。内容は以下の様にご自身のAWSアカウントを指定して入力してください。
{ "allow-nondistributable-artifacts": [ "123456789012".dkr.ecr.ap-northeast-1.amazonaws.com" ] }
当初ProgramData
フォルダの存在がわからずに困りました。隠しフォルダになっているのでエクスプローラーの設定からHidden itemsにチェックを入れて表示してください。
Docker デーモンを再起動すると設定が反映されます。Windows のデーモン再起動方法がわからなかったので OS 再起動しました。
ビルド済みのsample-windows-iis:latest
に新たにflag
タグを付けました。
docker tag sample-windows-iis:latest 123456789012.dkr.ecr.ap-northeast-1.amazonaws.com/sample-windows-iis:flag
flag
タグを付けた Docker イメージを Push します。Docker デーモンの設定により全イメージレイヤーを ECR へ Push するため時間がかかります。
docker push 123456789012.dkr.ecr.ap-northeast-1.amazonaws.com/sample-windows-iis:flag
2.8 GBにもなる巨大な Docker イメージを ECR から確認できました。
Let's Try
タスク定義を編集しflag
タグのイメージを利用するようにしてタスクを起動します。
インターネットアクセスは禁止されていても、ECR へのアクセス経路を VPCをエンドポイントで確保すれば Windows コンテナの起動に成功できることを確認できました。
Web ブラウザからテストページを確認できました。
Docker イメージの Push 方法の違いによる挙動の違いを確認できました。
ネットワーク構成によっては Push 方法を検討しないとタスク起動できないことや、知らないところでパブリックアクセスが発生しているかもしれません。
以上Windows コンテナの Docker イメージを ECR へ Pushしたときに気をつけて欲しいポイントでした。
おわりに
ECR のドキュメントに書いてあるから読めばわかる話なのですが、ECS の Windows コンテナのドキュメントしか知らなく、ECR のドキュメントに Windows コンテナの記述があることに気づきませんでした。ですので、本記事で共有できればなと思います。
その他、スケールアウト・インが多く見込まれており、NAT Gateway経由でインターネットアクセスする場合は、通信量によっては ECR にすべて格納して VPCエンドポイント設置する方が安く上がることも考えられます。環境に適したネットワーク構成をご検討ください。