Ponz Dev Log

ゆるくてマイペースな開発日記

skopeoのイメージコピー時にdigestを出力する

この記事は、skopeoでコンテナイメージをコピーしたときに同時にイメージdigestも一緒に出力できるからKubernetesマニフェストへの埋め込みに便利だぞという話です。

skopeoはレジストリ間のコンテナイメージのコピーやタグ一覧の参照など、コンテナイメージのちょっとした操作を便利に実行できるユーティリティです。実践的な例としては、CIパイプラインでビルドしたイメージを検証環境や本番環境に昇格するといった使い方ができます。 この使い方をTektonから実行する解説記事がRed Hatさんのブログで紹介されています。

github.com

rheb.hatenablog.com

なぜdigestが必要か

Kubernetesなどのコンテナオーケストレーションツールでコンテナイメージを使うためには、イメージの識別子(タグなど)をマニフェストファイルに埋め込む必要があります。 識別子の埋め込むタイミングとしては、ビルド時やイメージの昇格時などが考えられるので、skopeoのイメージコピー操作と一緒に実行してあげると都合が良さそうです。

ここで問題になるのが、イメージの識別子として何を使うかです。 最も簡単なのはタグ名です。しかし、イメージを一意にかつ不変なものを指定するのであれば、digestの指定が確実です。 イメージの再プッシュが発生しうる場面では、同一のタグ名でも昨日と今日では別のイメージである可能性があります。 一方で同じタグ名でも内容が別のコンテナイメージであればdigestは別の値になります。

イメージの再プッシュが発生しない場面であればdigestではなくタグ名を識別子としても良いでしょう。 例えばAmazon ECRではレジストリリポジトリ単位にイミュータブルタグを設定することでタグの再プッシュを防止できます。

docs.aws.amazon.com

dev.classmethod.jp

digestを出力してみる

それではskopeoのコピー時にdigestを出力してみます。

開発用のレジストリ dev.registry.local/sample-app から 検証環境のレジストリ staging.registry.local/sample-app にイメージをコピーすると仮定します。

以下のサンプルでは digest.txt ファイルにdigestを出力しています。 ここでポイントは、 skopeoの copy コマンド実行時にdigestを出力するファイル名と一緒に --digestfile を指定します。 --digestfile オプションはskopeo 1.3.0から使えるようです。

$ skopeo copy --digestfile digest.txt \
        docker://dev.registry.local/sample-app:20220313  \
        docker://staging.registry.local/sample-app:20220313

Getting image source signatures
Copying blob sha256:8d66994d054da0091fad11fb497b2a23c0cfd350d897d78d57f78b3200b90fd6
Copying blob sha256:52355207fda65c2219b38c373cef4a25e868a97641e484f1393e632843705bff
Copying blob sha256:c934f4d5f4297067be69f40f99b06c810790e6ecf5d54e30bba34a2dfa4b7684
(...中略...)
Writing manifest to image destination
Storing signatures

$ cat digest.txt
sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa

これでイメージを一意に特定するdigestを得られたので、マニフェストsed などで置換すればコピーしたイメージを昇格先の環境にデプロイすることができそうです。

補足

ちなみにdigestをファイルに書き込むのはskopeo以外のツール/ユーティリティでも可能です。 例えばイメージビルドツールの kaniko だと --digest-file オプションをつけて実行することで同じことを実現できます。

github.com


以上。