ローファイ日記

出てくるコード片、ぼくが書いたものは断りがない場合 MIT License としています http://udzura.mit-license.org/

archof: リモートのままイメージのarchitectureを確認するコマンド

背景

Apple SiliconのMacが販売されてそれなりの時間も経ち、エコシステムもできてきてお仕事の開発に使っている人も増えてきたように思う。

ところで、colimaのようなツールを使い、Docker環境をMacに作成した時、Apple Silicon上ではデフォルトで arm64 版のDocker*1がインストールされる。

$ docker info | grep Archi
 Architecture: aarch64

この上で何も考えずにイメージをビルドしたら arm64 のイメージができる。

この時、このイメージをリモートのレジストリGCRGHCRなどを想像してほしい)にpushにしたら、もちろん arm64 のイメージがpushされる。

ここで、このイメージをx86_64の本番サーバにpullして走らせるような運用だったら、困ったことになるだろう...。

このような違うアーキテクチャのイメージをうっかりプッシュしてしまう事故は、意外と防ぐ仕組みが簡単ではない*2

さらに言うと、pushされたイメージのアーキテクチャがなんであるかを確認するのも意外と骨が折れる。pullしてしまえば docker inspect なりで確認すればすぐわかるが、何度もプッシュしていてそのうちいくつかに混ざってしまったような場合とか、そもそもイメージが大きい場合とかは難しいこともありそう。

と言うことで Docker Registory API を叩いてリモートから確認するコマンドを作った。

github.com

インストール

$ go install github.com/udzura/archof

Go 1.17 で動作確認しています。多分1.18などでも問題なさそう。

様子

$ archof docker.io/amd64/ubuntu:latest
amd64

$ archof docker.io/arm64v8/ubuntu:latest 
arm64

認証が必要なやつはBearer認証に対応しているので、たとえばGCRだとこう言う感じで使えます。

$ archof gcr.io/udzura-dev/sample:latest --bearer "$(gcloud auth print-access-token)"                                                                     
amd64

内部

マニフェストを取得して、そこからConfigのDigestを取得してBlobを取得すればいいんですが、今回利用した go-containerregisrty はBlobの方のAPIをどう叩けばいいかよくわからず、URLを自分で構築して直接叩くことになった。いい方法があるんだろうか。

ref, _ := name.ParseReference(target)
desc, _ := remote.Get(ref, remote.WithAuth(&authn.Bearer{Token: token}))

reg := ref.Context()
url := fmt.Sprintf("%s://%s/v2/%s/blobs/%s",
    reg.Scheme(),
    reg.RegistryStr(),
    reg.RepositoryStr(),
    sha,
)
res, _ := desc.Client.Get(url)

type BlobResponse struct {
    Architecture string `json:"architecture"`
}
b := BlobResponse{}

if err := json.NewDecoder(res.Body).Decode(&b); err != nil {
    panic(err)
}

fmt.Println(b.Architecture)

雑感

Go の思い出しも兼ねて作ったが、特に変わったことをしていないので思い出せたのかどうか。

あとコマンドの名前の主語が大きいかも?(対象はコンテナイメージだけなのに) と思ったが、覚えやすいしえいやと付けました。ご了承ください。

とりあえず不安になった時にお使いください。というかpush防ぐ方法ってないんですかね...。

*1:正確にはLinuxVMイメージ

*2:いい方法があれば知りたい、というのもこのブログを書いたモチベーションの一つ