Docker build x86/ARM multi-arch images with AWS ECR

2021-04-03 AWS, Docker

這幾年整個 CPU 的市場從原本的 x86 開始翻轉到 Arm based 的 CPU,從 AWS Graviton2 和 Apple M1 都是 Arm CPU 的佼佼者,成本跟效能都有明顯的改善,就連作者都快被 Arm 給香爆,但是從 x86 到 Arm 的轉換期總是有一些事情要做,今天這篇要講的時下最夯的 Container 如何建立多種架構的 Container image 到 AWS ECR (Elastic Container Registry)

首先 AWS ECR 和 Docker 都有支援 manifest lists,使用 manifest lists 可以將 x86 或 Arm 等不同架構儲存在單個 ECR Container image,當啟動 Container image 時會自動選擇適合當前 CPU 架構的 image 使用。

Docker buildx mode

Docker 支援 buildx, manifest 建立 multi-arch,作者試過兩種都可以使用,用法也都大同小異可以自行選擇,在這篇採用 buildx 示範

先建立 AWS ECR Repository 待會上傳 Container image 的使用空間

$ aws ecr create-repository \
    --repository-name multi-arch \
    --image-scanning-configuration scanOnPush=true \
    --image-tag-mutability MUTABLE \
    --region us-east-1

拿到 repositoryArn 後先記錄下來

arn:aws:ecr:${region}:${accountId}:repository/multi-arch

Dockerfile 執行 uname -m 用於檢測 CPU 架構

# Dockerfile
FROM alpine:latest
CMD echo “Running on $(uname -m)”

buildx inspect 可以查看目前 Docker build mode

$ docker buildx inspect

Name:   default
Driver: docker

Nodes:
Name:      default
Endpoint:  default
Status:    running
Platforms: linux/amd64, linux/arm64, linux/riscv64 ...

但預設並不支援 multi-arch 的方式建構 container image,所以要透過 buildx 建立支援 multi-arch 的 builder instance

$ docker buildx create --name mybuilder
$ docker buildx use mybuilder

再次 buildx inspect 檢查可以看到 builder instance 換成 mybuilder,而 Driver 也從 docker 變成 docker-container

$ docker buildx inspect

Name:   mybuilder
Driver: docker-container

Nodes:
Name:      mybuilder0
Endpoint:  unix:///var/run/docker.sock
Status:    inactive
Platforms: linux/amd64, linux/arm64, linux/riscv64 ...

但是 Status 仍是 inactive,使用 --bootstrap 讓 builder 初始化

$ docker buildx inspect --bootstrap

...
Status:    running

確定狀態為 running 後就可以建構 multi-arch 的模式了

Docker Login with AWS ECR

預設 Docker 支援的 registry 是 DockerHub 如果要將 registry 改成 ECR 則要修改 docker login

$ aws ecr get-login-password --region us-east-1 \
     | docker login --username AWS \
       --password-stdin ${accountId}.dkr.ecr.region.amazonaws.com

Docker build multi-arch image

建構 multi-arch 一樣要使用 docker buildx 執行

$ docker buildx build \
         --platform linux/amd64,linux/arm64 \
         --push \
         -t ${accountId}.dkr.ecr.us-east-1.amazonaws.com/multi-arch:latest \
         .
  • --platform 用於指定要建構哪些平台架構,範例為 linux/amd64, linux/arm64,除此之外可以從 docker buildx inspect 找到支援的 platform
  • --push 指定後可以將 manifest lists 推送到 registry (ECR)

Verification

buildx build 成功之後在 AWS ECR 可以看到新的 image tag 被建立,但是卻無法看到支援哪些 architecture?

buildx 支援 imagetools 用來查看 container image 的詳細資訊,其中就包含 Manifests platform

$ docker buildx imagetools inspect ${accountId}.dkr.ecr.us-east-1.amazonaws.com/multi-arch:latest

...
Manifests:
    Platform: linux/amd64
    ...
    Platform: linux/arm64

預設情況下 docker run 會依照當前的 CPU chip 去選擇對應的 arch

$ docker run --rm ${accountId}.dkr.ecr.us-east-1.amazonaws.com/multi-arch:latest

"Running on x86_64"

當然也可以指定 –platform 選擇啟動的 image arch

$ docker run --rm --platform linux/aarch64  ${accountId}.dkr.ecr.us-east-1.amazonaws.com/multi-arch:latest

"Running on aarch64"

References

2 Replies to “Docker build x86/ARM multi-arch images with AWS ECR”

  1. uuuyyttu表示:

    要注意 ECR 不能開啟 tag immutability
    詳情可以參閱:https://github.com/moby/buildkit/issues/2004

給 Mr. 沙先生一點建議

彙整

分類

展開全部 | 收合全部

License

訂閱 Mr. 沙先生 的文章

輸入你的 email 用於訂閱