dockerイメージをマルチアーキテクチャイメージとしてプッシュする
記事の内容
dockerでイメージをプルするとき、下記のようにタグを10
と指定するだけでバージョン10の中で最新バージョンのイメージが自動でプルされることがあると思います。
docker pull image-name:10
このようなことを行う機能としてdocker manifest
というものがあります。
今回は既に作成したイメージに対して、manifestを作成して上記を実現してみたいと思います。
関係する技術・ツール
- Docker Desktop 4.23.0
- AWS ECR
おさえておくこと
DockerイメージはCPUアーキテクチャに対して最適なイメージがあります。
例えばNode.jsイメージを例にすると、下記のようにamd(x86_64)とarmとどちらにも対応していることが分かります。ですので、特に意識しなくてもdocker pullした際に、CPUに対して適切なイメージが自動でpullされます。
一方で、schemaspyのイメージを例にしてみると、こちらはamdのイメージしかないことが分かります。
この場合イメージをpullすることはできるものの、下記のようにdocker desktopでは警告が表示されます。これはM1 Mac(arm)に対して、amdのイメージがpullされてしまったため本来のパフォーマンスが出せない可能性があるためです。
もしプロジェクト内の事情で、異なるアーキテクチャのPCを使用する開発者が混在する場合、同じアーキテクチャのイメージを使っても上記の理由で動作しないことがあります。
マニフェストを使うと、このような悩みを解決できるかもしれません。
マニフェストとは
- あまりスッと入ってこない言葉かもしれませんが、あるdocker imageに対して別名をつけるようなイメージをすると良いと思います。
- マニフェストはいわゆるメタデータです。docker imageには最も知られているだろう「タグ」というメタデータがありますが、マニフェストでさらに高度にイメージを管理することができます。
活用方法
- CPU(OS)に対して、自動で最適なイメージをプルさせる
- 例えば、バージョン10.10とバージョン10.20のイメージに対して、両者とも
10
というタグで管理したいケースがあるとします。
理由があって10.10はarm、10.20はamdのイメージしか用意できない。しかしこのときcompose.ymlなどコードでコンテナのホストを管理していると、タグの指定に困ると思います。
タグを各々のPCに合わせて手動で設定することになってしまうでしょう。
- 例えば、バージョン10.10とバージョン10.20のイメージに対して、両者とも
servicename:
image: account_id.dkr.ecr.ap-northeast-1.amazonaws.com/image-name:10.10
マニフェストを作成して、下記のようにすればバージョン10でアーキテクチャに合わせて最適なイメージがプルされるようにできます。
servicename:
image: account_id.dkr.ecr.ap-northeast-1.amazonaws.com/image-name:10
マニフェスト作成の流れ
- manifest作成
- manifest内容の確認
- manifestプッシュ
1. manifest作成
既に10.10と10.20のイメージはビルド完了して、レジストリにプッシュ済みのものとします。
ビルドしたイメージがローカルにある状況で、マニフェストを作成します。
これで10.10と10.20が、別名タグ10
とするマニフェストが作成されます。
docker manifest create account_id.dkr.ecr.ap-northeast-1.amazonaws.com/my-image:10 account_id.dkr.ecr.ap-northeast-1.amazonaws.com/my-image:10.10 account_id.dkr.ecr.ap-northeast-1.amazonaws.com/my-image:10.20
=> Created manifest list account_id.dkr.ecr.ap-northeast-1.amazonaws.com/my-image:10
2. manifest内容の確認
作成したマニフェストを確認してみましょう。
下記のようなjsonが出力されると思います。architecture
がamd(10.10のイメージ)とarm(10.20のイメージ)の両方が含まれていることが確認できます。
docker manifest inspect account_id.dkr.ecr.ap-northeast-1.amazonaws.com/my-image:10
{
"schemaVersion": 2,
"mediaType": "application/vnd.docker.distribution.manifest.list.v2+json",
"manifests": [
{
"mediaType": "application/vnd.docker.distribution.manifest.v2+json",
"size": 1996,
"digest": "sha256:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
"platform": {
"architecture": "amd64",
"os": "linux"
}
},
{
"mediaType": "application/vnd.docker.distribution.manifest.v2+json",
"size": 1996,
"digest": "sha256:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
"platform": {
"architecture": "arm64",
"os": "linux",
"variant": "v8"
}
}
]
}
3. manifestプッシュ
作成したマニフェストをレジストリにプッシュします。
docker manifest push 695688866317.dkr.ecr.ap-northeast-1.amazonaws.com/my-image:10
すると下記のように10
のイメージが出来上がるのが分かります。アーティファクトタイプをみると、「Image Index」となっています。これはあくまで10
はイメージ10.10と10.20に対する参照であることを表しています。
このマニフェストを作成したことにより、アーキテクチャに合わせて10.20と10.20のいずれかがプルされるようになります。
まとめ
- マニフェストでイメージをより高度に管理できる
- CPUアーキテクチャが異なる場合、最適なイメージを自動でプルできるようにできる
以上になります。
最後になりますが、docker manifestは2023/11現在で実験的なコマンドのようです。プロダクション環境での使用には注意して活用していきましょう。
NCDC株式会社( ncdc.co.jp/ )のエンジニアチームです。 募集中のエンジニアのポジションや、採用している技術スタックの紹介などはこちら( github.com/ncdcdev/recruitment )をご覧ください! ※エンジニア以外も記事を投稿することがあります
Discussion