传统的 docker build 有几个限制:只能为当前机器架构构建镜像,缓存策略简单,不支持多阶段构建优化等高级功能。

Docker Buildx 是 Docker 官方推出的 BuildKit 构建工具,能解决这些问题。它支持多架构镜像构建、高级缓存管理和性能优化。

安装与配置

先检查环境:

Terminal window
# 检查 Docker 版本(需要 19.03+)
docker --version
# 检查 buildx 是否可用
docker buildx version
# 查看可用的 builder
docker buildx ls

对于 Docker 19.03+ 用户,需要启用实验性功能:

Terminal window
export DOCKER_BUILDKIT=1
docker buildx create --use

Builder 是 BuildKit 后端的配置,决定构建运行的位置和环境。Buildx 支持四种驱动类型:dockerdocker-containerkubernetesremote。单架构快速构建用 docker 驱动,多架构构建用 docker-container 驱动,CI/CD 大规模构建可以考虑 kubernetes 驱动。

创建支持多平台的 Builder:

Terminal window
# 创建新的 builder 实例(使用 docker-container 驱动)
docker buildx create --name multiarch-builder --driver docker-container --use
# 启动并检查 builder
docker buildx inspect --bootstrap
# 查看支持的平台
docker buildx inspect --bootstrap | grep Platforms
# 输出示例:Platforms: linux/amd64, linux/arm64, linux/arm/v7

推送到 Registry 前需要先登录:

Terminal window
# Docker Hub 登录
docker login
# 或者指定 registry
docker login ghcr.io
docker login docker.io

常用 Builder 管理命令:

Terminal window
# 查看现有 builder
docker buildx ls
# 切换 builder
docker buildx use mybuilder
# 查看 builder 详情
docker buildx inspect mybuilder
# 删除 builder
docker buildx rm mybuilder

基础构建命令

先准备一个简单的 Dockerfile:

FROM alpine:latest
CMD ["echo", "Hello from Docker"]

单平台构建(本地测试):

Terminal window
# 基础构建 - 结果加载到本地 docker 镜像
docker buildx build -t myapp:latest .
# 带多个标签
docker buildx build -t myapp:latest -t myapp:1.0 .

-t 参数给镜像打标签,. 表示使用当前目录下的 Dockerfile。

多平台构建(推送到 Registry),zhijunio 为我的 docker 用户名:

Terminal window
docker buildx build \
--platform linux/amd64,linux/arm64 \
--push \
-t docker.io/zhijunio/myapp:latest \
-t docker.io/zhijunio/myapp:1.0 \
.

--platform指定目标架构,多个平台用逗号分隔。--push表示构建完成后直接推送到 Registry(需要提前docker login)。

输出选项

选项说明限制
--load加载到本地 docker仅限单平台
--push推送到 Registry多平台必须
--output输出到目录本地调试用
仅更新缓存不生成镜像

注意 --load--push不能同时使用,多平台构建必须用--push

缓存优化

Buildx 支持多种缓存后端,合理使用可以显著提升 CI/CD 构建速度。

使用 Registry 缓存(需要提前 docker login):

Terminal window
# 导出缓存到 registry
docker buildx build \
--cache-to type=registry,ref=docker.io/zhijunio/cache:myapp \
--push \
-t docker.io/zhijunio/myapp:latest \
.
# 从 registry 导入缓存
docker buildx build \
--cache-from type=registry,ref=docker.io/zhijunio/cache:myapp \
--push \
-t docker.io/zhijunio/myapp:latest \
.
# 同时导入导出(推荐)
docker buildx build \
--cache-from type=registry,ref=docker.io/zhijunio/cache:myapp \
--cache-to type=registry,ref=docker.io/zhijunio/cache:myapp,mode=max \
--push \
-t docker.io/zhijunio/myapp:latest \
.

--cache-from 指定缓存来源,--cache-to 指定缓存导出位置。mode=max 导出更多缓存层,下次构建时能更好地复用。

使用本地缓存

Terminal window
# 导出到本地目录
docker buildx build \
--cache-to type=local,dest=./cache \
-t myapp:latest \
.
# 从本地目录导入
docker buildx build \
--cache-from type=local,src=./cache \
-t myapp:latest \
.

适合本地开发时使用,缓存保存在 ./cache 目录下。

Inline 缓存(最简单):

Terminal window
docker buildx build \
--build-arg BUILDKIT_INLINE_CACHE=1 \
--push \
-t docker.io/zhijunio/myapp:latest \
.

缓存直接内嵌在镜像层中,不需要额外配置。后续构建时会自动使用镜像中的缓存。

缓存后端类型对比

类型说明使用场景
inline缓存内嵌在镜像层中简单场景,无需额外配置
registry缓存存储在 RegistryCI/CD 共享缓存
local缓存存储到本地目录本地开发
ghaGitHub Actions 缓存服务GitHub CI/CD

多架构构建实战

构建并推送多平台镜像:

Terminal window
docker buildx build \
--platform linux/amd64,linux/arm64,linux/arm/v7 \
--push \
-t docker.io/zhijunio/myapp:latest \
-t docker.io/zhijunio/myapp:1.0 \
--cache-from type=registry,ref=docker.io/zhijunio/cache:myapp \
--cache-to type=registry,ref=docker.io/zhijunio/cache:myapp,mode=max \
.

--platform 指定三个目标架构:amd64(常规服务器)、arm64(新 Mac)、arm/v7(树莓派)。构建完成后自动推送到 Docker Hub。

验证多架构镜像:

Terminal window
docker buildx imagetools inspect docker.io/zhijunio/myapp:latest

输出显示镜像支持的架构列表:

Name: docker.io/zhijunio/myapp:latest
MediaType: application/vnd.docker.distribution.manifest.list.v2+docker
Platform: linux/amd64
Platform: linux/arm64
Platform: linux/arm/v7

拉取特定架构:

Terminal window
docker pull --platform linux/arm64 docker.io/zhijunio/myapp:latest

--platform 参数指定要拉取的架构,Docker 会自动选择匹配的镜像层。

Dockerfile 最佳实践

多阶段构建减少镜像大小

FROM --platform=$BUILDPLATFORM golang:1.21 AS builder
WORKDIR /app
COPY . .
ARG TARGETOS TARGETARCH
RUN GOOS=$TARGETOS GOARCH=$TARGETARCH go build -o app .
FROM alpine:latest
COPY --from=builder /app/app /app
ENTRYPOINT ["/app"]

$BUILDPLATFORM 是构建平台的自动变量,TARGETOSTARGETARCH 是目标平台的自动变量。这样可以在构建时自动适配不同架构。最终镜像只包含编译好的二进制文件,体积更小。

优化层缓存

FROM node:20-alpine
WORKDIR /app
# 先复制 package.json 和 package-lock.json
COPY package*.json ./
RUN npm ci
# 再复制源代码
COPY . .
RUN npm run build
EXPOSE 3000
CMD ["node", "dist/index.js"]

依赖文件不常变化,先复制可以利用缓存。源代码经常变化,放在后面。这样修改代码时,npm ci 这层可以复用缓存。

使用 .dockerignore 排除不必要文件

node_modules
npm-debug.log
.git
.gitignore
Dockerfile
.dockerignore
README.md
*.md

node_modules 不需要,因为会重新npm install.git 目录、文档文件也不需要进镜像。排除这些文件可以减小构建上下文,加快构建速度。

完整实战示例

Node.js 应用多平台构建

Terminal window
# 创建 builder(如果还没有可用的多平台 builder)
docker buildx create --name node-builder --use --bootstrap
# 构建并推送(需要先 docker login)
docker buildx build \
--platform linux/amd64,linux/arm64 \
--push \
--cache-from type=registry,ref=docker.io/zhijunio/nodeapp:cache \
--cache-to type=registry,ref=docker.io/zhijunio/nodeapp:cache,mode=max \
-t docker.io/zhijunio/nodeapp:latest \
-t docker.io/zhijunio/nodeapp:1.0 \
.

--bootstrap 参数会在创建 builder 后立即启动它。缓存配置可以加速后续构建。

Go 应用跨平台编译

FROM --platform=$BUILDPLATFORM golang:1.21 AS builder
WORKDIR /app
COPY . .
ARG TARGETOS TARGETARCH
RUN GOOS=$TARGETOS GOARCH=$TARGETARCH go build -o app .
FROM alpine:latest
COPY --from=builder /app/app /app
ENTRYPOINT ["/app"]
Terminal window
docker buildx build \
--platform linux/amd64,linux/arm64 \
--push \
-t docker.io/zhijunio/goapp:latest \
.

Java Spring Boot 应用

FROM --platform=$BUILDPLATFORM eclipse-temurin:21-jdk-alpine AS builder
WORKDIR /app
COPY mvnw* pom.xml ./
RUN ./mvnw dependency:go-offline -B
COPY src ./src
RUN ./mvnw package -DskipTests
FROM eclipse-temurin:21-jre-alpine
WORKDIR /app
COPY --from=builder /app/target/*.jar app.jar
EXPOSE 8080
ENTRYPOINT ["java", "-jar", "app.jar"]
Terminal window
docker buildx build \
--platform linux/amd64,linux/arm64 \
--push \
-t docker.io/zhijunio/spring-app:latest \
.

第一阶段用 JDK 编译打包,第二阶段用 JRE 运行。dependency:go-offline 预先下载依赖,利用缓存加速后续构建。

调试与排错

显示详细构建日志

Terminal window
docker buildx build --progress=plain .

--progress=plain 显示每个构建步骤的详细输出,方便定位问题。

查看构建器日志

Terminal window
docker logs buildx_buildkit_<builder-name>0

<builder-name> 替换为 builder 名称,如 multiarch-builder

检查多架构镜像

Terminal window
docker buildx imagetools inspect docker.io/zhijunio/myapp:latest

拉取特定架构

Terminal window
docker pull --platform linux/arm64 docker.io/zhijunio/myapp:latest

常见问题

--load 报错不支持多平台

Terminal window
# 错误用法(会失败)
docker buildx build --platform linux/amd64,linux/arm64 --load -t myapp:latest .
# 正确用法
docker buildx build --platform linux/amd64 --load -t myapp:latest .

--load 只能用于单平台构建。多平台构建需要用 --push 推送到 Registry。

构建后本地找不到镜像

Terminal window
docker buildx build --load -t myapp:latest .

使用 docker-container 驱动时,构建结果不会自动加载到本地。添加 --load 参数或者改用 --output type=docker

删除本地 builder

Terminal window
docker buildx rm mybuilder
docker container rm -f buildx_buildkit_<name>0

<name> 替换为 builder 名称。第二条命令删除 builder 对应的容器。

速查表

场景命令
本地单平台测试docker buildx build -t img:tag .
多平台 + 推送docker buildx build --platform linux/amd64,linux/arm64 --push -t repo/img:tag .
带缓存构建--cache-from type=registry,ref=repo/cache --cache-to type=registry,ref=repo/cache,mode=max
创建 builderdocker buildx create --name <name> --driver docker-container --use
验证多平台docker buildx imagetools inspect repo/img:tag
内联缓存--build-arg BUILDKIT_INLINE_CACHE=1
详细日志--progress=plain

总结

Docker Buildx 主要优势:

  • 多架构支持:一次构建,同时生成 amd64、arm64、arm/v7 等多个平台的镜像
  • 缓存优化:支持 registry、本地、inline 等多种缓存方式,显著提升 CI/CD 构建速度
  • 灵活配置:支持多种 driver 和输出方式,适应不同场景
  • 易于使用:与 docker build 命令兼容,学习成本低

对于需要在 ARM 架构(如 Apple Silicon、树莓派)上运行容器的开发者,Buildx 是必备工具。

参考资源