Open22

Cross/multi-platform build for Docker

Yoshiharu SuzukiYoshiharu Suzuki
Yoshiharu SuzukiYoshiharu Suzuki

以下のQEMUのセットアップを忘れていたので、この結果が正しいものかはあやしいな…。

    steps:
      - name: Set up QEMU
        uses: docker/setup-qemu-action@v3
Yoshiharu SuzukiYoshiharu Suzuki

docker/build-push-action@v6の出力を見ると次の変化があった。

#12 [linux/amd64->arm64 builder 2/6] WORKDIR /usr/src/app
#12 DONE 0.4s

プラットフォームをamd64で固定したbuilderステージでは、linux/amd64->arm64となっていた。
ターゲットのプラットフォームとビルドプラットフォームが異なることがわかるログの出方をしている。

Yoshiharu SuzukiYoshiharu Suzuki

GitHub Actions と連携してやる場合。
https://docs.docker.com/build/ci/github-actions/multi-platform/

Yoshiharu SuzukiYoshiharu Suzuki

docker/build-push-action@v6アクションに以下を足すことでプラットフォームが指定可能になる。

          platforms: linux/amd64,linux/arm64
Yoshiharu SuzukiYoshiharu Suzuki

1つのrunner内で2つのプラットフォームのビルドが並行で走っているように見える。
次は出力の抜粋。

#4 [linux/amd64 internal] load metadata for docker.io/library/golang:1.22-alpine
#4 DONE 1.1s

#5 [linux/arm64 internal] load metadata for docker.io/library/golang:1.22-alpine
#5 DONE 1.1s

#6 [linux/amd64 internal] load metadata for docker.io/library/alpine:latest
#6 DONE 1.1s

#7 [linux/arm64 internal] load metadata for docker.io/library/alpine:latest
#7 DONE 1.1s
Yoshiharu SuzukiYoshiharu Suzuki

最後のほうにマニフェストが作れられてそれもpushされている。

#26 exporting to image
#26 exporting layers 0.1s done
#26 exporting manifest sha256:f642e371e1ad43b8367aa43fcc06d79986a1d2d0dc667326a65a60cf37d65868 done
#26 exporting config sha256:5f7608ccbe26ba59c14842fdca7f9c7b32c44d207d06f35373f7d133914120cc done
#26 exporting attestation manifest sha256:df6f2e9cf709d2ac65e36b820ef21de7d2de1b6eb16af27fecc8478b98dbf5ec done
#26 exporting manifest sha256:2341871ab41c137fdbef2f5e3747893c9ae42c88ddbb0b99f195a4fe74ce60e1 done
#26 exporting config sha256:12f06cd22b3c2c094b1f7ce08490c78ef577c5acef9aaacf23f2c25ec1c34386 done
#26 exporting attestation manifest sha256:889d106efa97797e951ea4bc494825d8fb5b12f07c7bc2dab81a6cbbff0ae26a done
#26 exporting manifest list sha256:9677db7ab12a8fecab6b07b4a41edc57877ff522d132782c6ec57c3fafb2a16d done
#26 pushing layers
#26 ...

#27 [auth] bellwood4486/sample-go:pull,push token for registry-1.docker.io
#27 DONE 0.0s

#26 exporting to image
#26 pushing layers 1.3s done
#26 pushing manifest for docker.io/bellwood4486/sample-go:gh@sha256:9677db7ab12a8fecab6b07b4a41edc57877ff522d132782c6ec57c3fafb2a16d
#26 pushing manifest for docker.io/bellwood4486/sample-go:gh@sha256:9677db7ab12a8fecab6b07b4a41edc57877ff522d132782c6ec57c3fafb2a16d 0.8s done
#26 DONE 2.4s
Yoshiharu SuzukiYoshiharu Suzuki

マルチプラットフォームのイメージとして作られた。

マルチプラットフォームの場合はINDEX DIGESTとなっている。

INDEX DIGEST sha256:9677db7ab1...

(非マルチの場合はここがMANIFEST DIGEST)

Yoshiharu SuzukiYoshiharu Suzuki

マニフェストの情報がコマンドから確認できる。

❯ docker buildx imagetools inspect bellwood4486/sample-go:gh
Name:      docker.io/bellwood4486/sample-go:gh
MediaType: application/vnd.oci.image.index.v1+json
Digest:    sha256:596676a7b2cf7114cbefa91728520e116cf7341edef5c569c6c7c6e7e6cbeae6

Manifests:
  Name:        docker.io/bellwood4486/sample-go:gh@sha256:0935257799f8e4974e55ffc226e6f04acfcb9cfac6bdf522bfe3327a13cc1a92
  MediaType:   application/vnd.oci.image.manifest.v1+json
  Platform:    linux/amd64

  Name:        docker.io/bellwood4486/sample-go:gh@sha256:ae4b6590554821ff4d1171ccf999b2a5a4f3b5db1c2618502e764f26606d31db
  MediaType:   application/vnd.oci.image.manifest.v1+json
  Platform:    linux/arm64

  Name:        docker.io/bellwood4486/sample-go:gh@sha256:2fb74abc811c6063b3ff224d39fac28e2a65b6c57050cbf66d35a6abacd599a0
  MediaType:   application/vnd.oci.image.manifest.v1+json
  Platform:    unknown/unknown
  Annotations:
    vnd.docker.reference.digest: sha256:0935257799f8e4974e55ffc226e6f04acfcb9cfac6bdf522bfe3327a13cc1a92
    vnd.docker.reference.type:   attestation-manifest

  Name:        docker.io/bellwood4486/sample-go:gh@sha256:79681852ad6d29abb2fda4accfbeade8beb0db791845d3be6eba490872ea638d
  MediaType:   application/vnd.oci.image.manifest.v1+json
  Platform:    unknown/unknown
  Annotations:
    vnd.docker.reference.digest: sha256:ae4b6590554821ff4d1171ccf999b2a5a4f3b5db1c2618502e764f26606d31db
    vnd.docker.reference.type:   attestation-manifest
Yoshiharu SuzukiYoshiharu Suzuki

docker コマンドのみでやる場合。一番シンプルな構成。
https://docs.docker.com/build/building/multi-platform/

Yoshiharu SuzukiYoshiharu Suzuki

初期設定のままやってみると次のエラーになる。

❯ docker build -t bellwood4486/sample-go:cli --platform linux/amd64,linux/arm64 .
[+] Building 0.0s (0/0)                                                                                                                           docker:desktop-linux
ERROR: Multi-platform build is not supported for the docker driver.
Switch to a different driver, or turn on the containerd image store, and try again.
Learn more at https://docs.docker.com/go/build-multi-platform/
Yoshiharu SuzukiYoshiharu Suzuki

By default, Docker can build for only one platform at a time. To build for multiple platforms concurrently, you can:
Enable the containerd image store: The default image store in Docker Engine doesn't support multi-platform images. The containerd image store does, and lets you create multi-platform images using the default builder. Refer to the containerd in Docker Desktop documentation.
Create a custom builder: Initialize a builder that uses the docker-container driver, which supports multi-platform builds. For more details, see the docker-container driver documentation.

デフォルトでは指定できるプラットフォームは1つのみ。

  • containerd image store を有効にする
  • カスタムビルダーを作る

をしないといけないらしい。