Docker Buildx 多重架構建置

隨著 Apple Silicon (M1/M2/M3) 的普及以及 AWS Graviton (Arm) 伺服器的流行,開發者經常遇到一個問題:我在 Mac 上建置的映像檔,丟到 Linux 伺服器上卻跑不動?

這是因為 CPU 架構不同(arm64 vs. amd64)。為了解決這個問題,Docker 推出了 Buildx,它將建置流程從單純的本地編譯提升到了真正的「跨平台」自動化。

什麼是 Docker Buildx?

Buildx 是一個 Docker 的外掛插件,底層依賴 BuildKit 引擎。相比於傳統的 docker build,它具備以下核心優勢:

  • 多重架構建置 (Multi-platform builds):一次建置出支援多種 CPU 的映像檔。
  • 高階快取機制:支援將快取存放在 Registry 或本地目錄,大幅加速團隊開發。
  • Dockerfile Mounts:支援在建置期間安全地掛載 Secrets、SSH Keys 或編譯快取目錄。

實戰:建置多重架構映像檔

建立新的 Builder (docker-container 驅動)

預設的 Docker builder 有時受限於本地環境。我們建議建立一個使用 docker-container 驅動的 Builder,這能釋放 Buildx 的完整功能:

# 建立並使用名為 mybuilder 的實例
docker buildx create --name mybuilder --driver docker-container --use
docker buildx inspect --bootstrap

建置並推送到 Registry

由於多重架構映像檔是由一個「Manifest (清單)」檔案連接著不同架構的 Image,因此通常需要直接推送到 Registry (如 Docker Hub) 才能完成。

docker buildx build \
  --platform linux/amd64,linux/arm64 \
  -t mikelee/my-app:latest \
  --push .
  • --platform: 指定支援架構(如 amd64, arm64, arm/v7 等)。
  • --push: 直接推向倉庫,否則本地難以存放多重架構的同名映像檔。

BuildKit 高階功能:快取 (Caching)

在 CI/CD 流程中,重複下載依賴包是非常耗時的。Buildx 允許你將建置快取儲存在遠端。

docker buildx build \
  --push \
  -t mikelee/my-app:latest \
  --cache-from type=registry,ref=mikelee/my-app:buildcache \
  --cache-to type=registry,ref=mikelee/my-app:buildcache,mode=max \
  .
  • type=registry: 快取存放在 Docker Registry 中。
  • mode=max: 同時快取最終映像檔與中間所有的層級 (Layers)。

Dockerfile Mounts:建置時的秘密與快取

BuildKit 引入了 --mount 語法,讓寫 Dockerfile 的效率與安全性大幅提升。

秘密管理 (Secret Mount)

避免將 API Key 或 SSH Key 寫死在映像檔層級中:

# Dockerfile 範例
RUN --mount=type=secret,id=api_key \
    export KEY=$(cat /run/secrets/api_key) && \
    ./fetch-data.sh

建置指令:docker buildx build --secret id=api_key,src=./key.txt .

編譯快取 (Cache Mount)

加速套件管理器的安裝過程(如 npmapt):

# 複用 apt 的快取,減少重複下載
RUN --mount=type=cache,target=/var/cache/apt \
    apt-get update && apt-get install -y git

自動化建置:Docker Bake

當你的專案有多個映像檔、多種環境時,手動打 buildx 指令會變得很混亂。Docker Bake 就像是建置版的 docker-compose

你可以建立一個 docker-bake.hcl

group "default" {
  targets = ["webapp", "api"]
}

target "webapp" {
  context = "./frontend"
  platforms = ["linux/amd64", "linux/arm64"]
}

target "api" {
  context = "./backend"
  platforms = ["linux/amd64"]
}

執行指令:docker buildx bake,它會依照順序或平行地處理所有建置任務。

總結

現在的開發環境已經進入「多架構並存」且追求 CI/CD 極致效率的時代。掌握 docker buildx 的進階功能,不僅能解決跨平台部署問題,更能透過快取與 Secret 管理,讓你的建置流程更加安全且快速。