nikkie-ftnextの日記

イベントレポートや読書メモを発信

マルチプラットフォームに対応したDockerイメージをGitHub Actionsでビルドする

はじめに

届けさせてください! nikkieです。

このあたり疎かったのですが、GitHub ActionsでビルドしてDocker Hubに上げたイメージをM1 Macでは動かせないという事象に直面しました。
これを解決するためのマルチプラットフォームビルドについて記事にします。

目次

まとめ:GitHub Actionsでマルチプラットフォームビルド

ズバリなドキュメントがあります

一番上にあるYAMLファイル(GitHub Actionsの定義)をまねるのがオススメです。
docker社が用意しているActionを順番に呼んでいきます。

  1. docker/setup-qemu-action
  2. docker/setup-buildx-action
  3. docker/login-action
  4. docker/build-push-action

以上で、マルチプラットフォームビルドされたイメージがDocker Hubにpushされます。

なお、これは1つのrunnerで2つのプラットフォーム用のビルドを直列でする例です。
GitHub Actionsのmatrixを使って複数のrunnerで動かし、マージする例も紹介されています(指定するプラットフォームが2つだけなので今回は採用していません)。

きっかけ:直面していた事象

『かがみの孤城』ファンアートコマンドをDockerイメージとしても配布しようとして直面しました。

  • M1 Macでビルドしたイメージは、M1 Macでrunできる
  • GitHub ActionsでビルドしてDocker Hubに上げたイメージは、M1 Macでrunできない
    • GitHub Actionsではubuntuのrunnerでビルドしている
    • Docker Hubからのpullができない
      • docker: no matching manifest for linux/arm64/v8 in the manifest list entries.

      • ubuntuでビルドしたから
    • ワークアラウンドdocker run --platform linux/x86_641
      • pullしてrunできます

例えばDocker Hubにある公式のpythonイメージって、M1 Macだからといって--platformを付けなくてもrunできますよね?
自作イメージもpythonイメージと同じにしたい! --platformなしでもrunしたい!

マルチプラットフォームイメージ

ドキュメントがあります。

Docker images can support multiple platforms, which means that a single image may contain variants for different architectures, and sometimes for different operating systems, such as Windows.

(意訳) Dockerイメージはマルチプラットフォームをサポートできます。これは、単一のイメージが異なるアーキテクチャ向け、時としてWindowsのような異なるOS向けの変種を含むかもしれないことを意味します。

When you run an image with multi-platform support, Docker automatically selects the image that matches your OS and architecture.

(意訳) マルチプラットフォームをサポートしたイメージをrunするとき、Dockerは自動であなたのOSとアーキテクチャに合致するイメージを選びます。

公式のpythonイメージを思い浮かべると分かりやすいですね。

マルチプラットフォームをビルドするための設定や戦略が、このドキュメントの「Building multi-platform images」や「Strategies」で解説されています。
後述する日本語記事でキャッチアップしました。

とても助かった「docker-buildxとmulti-platform build周りについてまとめ」

コンテナイメージを作成する際にamd64アーキテクチャ向けのイメージだけじゃなくて、arm向けのイメージとかも作りたいとき

👉 docker-buildx を使う。
インストール方法も案内されます

buildxを使って例えばamd64環境でarm向けのイメージを作成する場合は、buildx本体以外にもQEMUというエミュレータをインストールしておく必要があるらしい。

「Strategies」に挙がっていたQEMU

Github Actionsでmulti-platform buildイメージをpushする」にYAMLの例があります。
今はもっと新しいバージョンのActionがリリースされているので、上のまとめで紹介した「ズバリなドキュメント」中の例に読み替えるのがオススメです。
これらのActionで何をしているかを見たことで、ブラックボックスが開き、大変助かりました。

docker社提供の一連のActionたちは何をしているのか

まとめで紹介した「Multi-platform image with GitHub Actions」の一連のActionは、docker buildxコマンドをラップしていると分かりました。

docker run --privileged --rm tonistiigi/binfmt --install allを実行してQEMUをインストール

  • docker buildxコマンドが使えるようにインストール
  • docker buildx create --useを実行して、multi-node builderなるものを作成

Docker Hubにpushできるよう、docker login

イメージをbuildして(docker buildx build)、Docker Hubにpush。
platforms: linux/amd64,linux/arm64と指定することで、マルチプラットフォームをサポートするイメージをビルドできます!

対処できました!

ここまでを元に作ったGitHub Actionsはこちら:

Docker Hubの「OS/ARCH」に2行ある!

このイメージを指定して、--platformなしでdocker runできました🙌

% docker run --rm ftnext/kojo-day:0.1.1
{"kokoro": "Tuesday", "aki": "Friday", "fuka": "Friday", "rion": "Tuesday", "subaru": "Thursday", "masamune": "Thursday", "ureshino": "Sunday"}

終わりに

Dockerイメージのマルチプラットフォームビルドを知りました。
docker buildxコマンド、そしてそれをラップしたActionたち!

公式のpythonイメージはM1 Macでも問題なく動いてましたが、その裏にはマルチプラットフォームサポートのための技術が隠れていたのですね。
これでイメージ作りたい放題だ!

今回の記事の元ツイートです


  1. こちらで知りました。