Docker Buildx 多平台映像建置

Docker Buildx Multi-Platform Image Build

前言

隨著 ARM 架構處理器(如 Apple M1/M2、AWS Graviton)的普及,開發者經常需要建置同時支援 x86_64 和 ARM64 架構的 Docker 映像。Docker Buildx 是 Docker 官方提供的 CLI 擴充工具,讓我們能夠輕鬆地建置多平台映像。

Buildx 概述

Docker Buildx 是基於 BuildKit 的進階建置工具,提供以下主要功能:

  • 多平台建置:單一指令同時建置多種 CPU 架構的映像
  • 快取優化:支援本地與遠端快取,加速建置流程
  • 並行建置:同時建置多個目標平台
  • 進階輸出格式:支援 OCI 標準格式與多種輸出方式

確認與啟用 Buildx

檢查 Buildx 版本

首先確認系統已安裝 Buildx:

1
docker buildx version

輸出範例:

1
github.com/docker/buildx v0.11.2 9872040

查看現有 Builder

1
docker buildx ls

輸出範例:

1
2
3
4
5
NAME/NODE       DRIVER/ENDPOINT STATUS  BUILDKIT PLATFORMS
default         docker
  default       default         running 23.0.6   linux/amd64, linux/amd64/v2, linux/amd64/v3
desktop-linux   docker
  desktop-linux desktop-linux   running 23.0.6   linux/amd64, linux/amd64/v2, linux/amd64/v3

建立 Builder 實例

建立支援多平台的 Builder

使用 docker-container 驅動建立新的 Builder 實例:

1
2
3
4
docker buildx create --name multiplatform-builder \
  --driver docker-container \
  --bootstrap \
  --use

參數說明:

  • --name:指定 Builder 名稱
  • --driver docker-container:使用容器驅動,支援多平台建置
  • --bootstrap:立即啟動 Builder 實例
  • --use:設定為預設使用的 Builder

檢視 Builder 詳細資訊

1
docker buildx inspect multiplatform-builder

輸出範例:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
Name:          multiplatform-builder
Driver:        docker-container
Last Activity: 2024-10-07 08:30:00 +0000 UTC

Nodes:
Name:      multiplatform-builder0
Endpoint:  unix:///var/run/docker.sock
Status:    running
Buildkit:  v0.12.2
Platforms: linux/amd64, linux/amd64/v2, linux/arm64, linux/arm/v7, linux/arm/v6

支援的平台

Buildx 透過 QEMU 模擬器支援多種平台架構:

平台標識說明
linux/amd6464 位元 x86 架構(Intel/AMD)
linux/arm6464 位元 ARM 架構(Apple M1/M2、AWS Graviton)
linux/arm/v732 位元 ARM 架構(Raspberry Pi 2/3)
linux/arm/v632 位元 ARM 架構(Raspberry Pi 1/Zero)
linux/38632 位元 x86 架構
linux/ppc64leIBM Power 架構
linux/s390xIBM Z 系列架構

多平台建置指令

基本多平台建置

1
2
3
4
docker buildx build \
  --platform linux/amd64,linux/arm64 \
  -t myapp:latest \
  .

建置並載入到本地

注意:載入到本地 Docker 時只能選擇單一平台:

1
2
3
4
5
docker buildx build \
  --platform linux/amd64 \
  -t myapp:latest \
  --load \
  .

建置並輸出為 tar 檔案

1
2
3
4
5
docker buildx build \
  --platform linux/amd64,linux/arm64 \
  -t myapp:latest \
  --output type=oci,dest=./myapp-multiarch.tar \
  .

推送到 Registry

推送到 Docker Hub

1
2
3
4
5
6
docker buildx build \
  --platform linux/amd64,linux/arm64,linux/arm/v7 \
  -t username/myapp:latest \
  -t username/myapp:v1.0.0 \
  --push \
  .

推送到私有 Registry

1
2
3
4
5
docker buildx build \
  --platform linux/amd64,linux/arm64 \
  -t registry.example.com/myapp:latest \
  --push \
  .

檢視多平台映像資訊

1
docker buildx imagetools inspect username/myapp:latest

輸出範例:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
Name:      docker.io/username/myapp:latest
MediaType: application/vnd.oci.image.index.v1+json
Digest:    sha256:abc123...

Manifests:
  Name:      docker.io/username/myapp:latest@sha256:def456...
  MediaType: application/vnd.oci.image.manifest.v1+json
  Platform:  linux/amd64

  Name:      docker.io/username/myapp:latest@sha256:ghi789...
  MediaType: application/vnd.oci.image.manifest.v1+json
  Platform:  linux/arm64

QEMU 模擬器

安裝 QEMU 模擬器

在 Linux 系統上執行跨平台建置需要 QEMU:

1
docker run --privileged --rm tonistiigi/binfmt --install all

檢查已安裝的模擬器

1
docker run --privileged --rm tonistiigi/binfmt

移除模擬器

1
docker run --privileged --rm tonistiigi/binfmt --uninstall qemu-*

Dockerfile 多平台技巧

使用 TARGETPLATFORM 變數

Buildx 會自動注入平台相關變數:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
FROM --platform=$BUILDPLATFORM golang:1.21 AS builder

# 自動注入的變數
ARG TARGETPLATFORM
ARG TARGETOS
ARG TARGETARCH

WORKDIR /app
COPY . .

# 使用變數進行交叉編譯
RUN CGO_ENABLED=0 GOOS=${TARGETOS} GOARCH=${TARGETARCH} \
    go build -o /app/myapp .

FROM alpine:3.18
COPY --from=builder /app/myapp /usr/local/bin/
CMD ["myapp"]

平台特定安裝

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
FROM alpine:3.18

ARG TARGETARCH

RUN case ${TARGETARCH} in \
        "amd64")  ARCH="x86_64"  ;; \
        "arm64")  ARCH="aarch64" ;; \
        *)        ARCH=${TARGETARCH} ;; \
    esac && \
    wget -O /usr/local/bin/tool \
    "https://example.com/releases/tool-${ARCH}" && \
    chmod +x /usr/local/bin/tool

CI/CD 整合

GitHub Actions 範例

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
name: Build Multi-Platform Image

on:
  push:
    branches: [main]
    tags: ['v*']

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v4

      - name: Set up QEMU
        uses: docker/setup-qemu-action@v3

      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v3

      - name: Login to Docker Hub
        uses: docker/login-action@v3
        with:
          username: ${{ secrets.DOCKERHUB_USERNAME }}
          password: ${{ secrets.DOCKERHUB_TOKEN }}

      - name: Build and Push
        uses: docker/build-push-action@v5
        with:
          context: .
          platforms: linux/amd64,linux/arm64
          push: true
          tags: |
            username/myapp:latest
            username/myapp:${{ github.sha }}            
          cache-from: type=gha
          cache-to: type=gha,mode=max

GitLab CI 範例

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
build-multiplatform:
  image: docker:24
  services:
    - docker:24-dind
  variables:
    DOCKER_BUILDKIT: 1
  before_script:
    - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
    - docker buildx create --use --name gitlab-builder
  script:
    - docker buildx build
        --platform linux/amd64,linux/arm64
        --push
        -t $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
        -t $CI_REGISTRY_IMAGE:latest
        .

常見問題排解

建置快取

使用 Registry 作為快取:

1
2
3
4
5
6
7
docker buildx build \
  --platform linux/amd64,linux/arm64 \
  --cache-from type=registry,ref=username/myapp:cache \
  --cache-to type=registry,ref=username/myapp:cache,mode=max \
  --push \
  -t username/myapp:latest \
  .

清理 Builder

1
2
3
4
5
# 清理建置快取
docker buildx prune

# 移除 Builder 實例
docker buildx rm multiplatform-builder

總結

Docker Buildx 大幅簡化了多平台映像的建置流程。透過本文的介紹,您應該能夠:

  1. 建立並管理 Buildx Builder 實例
  2. 建置支援多種 CPU 架構的 Docker 映像
  3. 在 Dockerfile 中處理平台差異
  4. 將多平台建置整合到 CI/CD 流程中

參考資料

comments powered by Disqus
Built with Hugo
Theme Stack designed by Jimmy