Buildx创建多平台Docker镜像
要从一个 Dockerfile 生成支持 多个平台(如 x86_64 和 ARM64)的镜像文件,你可以使用 Docker 的 Buildx 工具,它是官方提供的多平台构建解决方案。
前提条件:Docker 版本 >= 20.10
启用了 BuildKit(默认已开启):
XML/HTML代码
- export DOCKER_BUILDKIT=1
- 或者
- export DOCKER_CLI_EXPERIMENTAL=enabled
验证是否开启:
XML/HTML代码
- docker buildx version
步骤:构建多平台镜像
1. 创建 buildx builder 实例(只需一次):
XML/HTML代码
- docker buildx create --name multi-builder --use
- docker buildx inspect --bootstrap
如果你已经有 builder,可以跳过。
2. 构建并导出镜像文件(例如 .tar):
方法一:构建并导出为 .tar 文件(本地导出,适合离线使用)
XML/HTML代码
- docker buildx build \
- --platform linux/arm64 \
- --output type=docker,dest=multi-platform-image.tar \
- -t myimage:latest \
- -f Dockerfile .
输出类型为 docker 只支持 单平台导出,所以多平台导出推荐使用 type=oci 或 type=image:
XML/HTML代码
- docker buildx build \
- --platform linux/amd64,linux/arm64 \
- --output "type=oci,dest=multi-platform.oci" \
- -t myimage:latest \
- -f Dockerfile .
3. 或者直接推送到 Docker Hub(支持多平台)
登录 Docker Hub
使用以下命令登录 Docker Hub:
XML/HTML代码
- docker login
镜像名称必须以你的用户名开头
Docker Hub 上的免费仓库命名规则:用户名/仓库名
你的镜像名是 aaa/myimage:latest,必须保证:
你在 Docker Hub 上的用户名是 aaa
仓库名为 myimage,必须已创建或首次推送时自动创建(公共仓库)
否则你没有权限推送这个镜像。
XML/HTML代码
- docker login
- docker buildx build \
- --platform linux/amd64,linux/arm64 \
- -t yourname/myimage:latest \
- --push \
- -f Dockerfile .
验证
推送完成后可以通过以下方式验证镜像
XML/HTML代码
- docker pull aaa/myimage:latest
常见平台标识
XML/HTML代码
- 平台名称 描述
- linux/amd64 64-bit x86 平台
- linux/arm64 64-bit ARM(如树莓派4)
- linux/arm/v7 32-bit ARM
- linux/386 32-bit x86
验证镜像架构
如果你已经导出 .oci 文件:
XML/HTML代码
- tar -tvf multi-platform.oci
如果你推送到了仓库,可以用 Docker Hub 或 Skopeo 来查看:
XML/HTML代码
- skopeo inspect docker://yourname/myimage:latest
小提示
如果你想单独构建某个平台的镜像为 .tar 文件:
XML/HTML代码
- docker buildx build \
- --platform linux/arm64 \
- --output type=docker,dest=arm64-image.tar \
- -t myimage:arm64 \
- .
加快构建速度:推荐使用 --cache-to 和 --cache-from。
自己DIY的一键生成&推送脚本
XML/HTML代码
- #!/bin/bash
- set -e
- # ============ 可选平台 =============
- PLATFORM_LIST=(
- "linux/amd64 (x86_64)"
- "linux/arm64 (ARMv8)"
- "linux/arm/v7 (ARMv7 32-bit)"
- )
- PLATFORM_KEYS=(
- "linux/amd64"
- "linux/arm64"
- "linux/arm/v7"
- )
- # ============ 默认变量 =============
- IMAGE_NAME="myimage"
- IMAGE_TAG="latest"
- DOCKERFILE="Dockerfile"
- TAR_NAME="image.tar"
- BUILD_MODE="local"
- PLATFORMS=""
- # ============ 平台选择菜单 ============
- select_platforms() {
- while true; do
- echo ""
- echo "请选择要构建的平台(可多选,用空格分隔,例如 1 2):"
- for i in "${!PLATFORM_LIST[@]}"; do
- echo "$((i+1)). ${PLATFORM_LIST[$i]}"
- done
- read -p "选择平台: " PLATFORM_SELECTION
- SELECTED_PLATFORMS=()
- for index in $PLATFORM_SELECTION; do
- if [[ $index -ge 1 && $index -le ${#PLATFORM_KEYS[@]} ]]; then
- SELECTED_PLATFORMS+=("${PLATFORM_KEYS[$((index-1))]}")
- else
- echo "⚠️ 无效平台编号: $index"
- exit 1
- fi
- done
- PLATFORMS=$(IFS=','; echo "${SELECTED_PLATFORMS[*]}")
- break
- done
- }
- # ============ 构建模式菜单 ============
- select_build_mode() {
- echo ""
- echo "请选择构建模式:"
- echo "1. 本地构建并导入镜像(不推送)"
- echo "2. 构建并导出为 tar 文件(仅支持单平台)"
- echo "3. 构建并推送到远程仓库"
- while true; do
- read -p "输入选项 [1-3]: " MODE
- case $MODE in
- 1) BUILD_MODE="local"; break;;
- 2)
- BUILD_MODE="export"
- if [[ "$PLATFORMS" == *,* ]]; then
- echo "❌ 导出模式只支持单平台。请重新选择一个平台。"
- select_platforms
- fi
- read -p "导出 tar 文件名(默认: $TAR_NAME): " INPUT_TAR
- [[ -n "$INPUT_TAR" ]] && TAR_NAME="$INPUT_TAR"
- break;;
- 3) BUILD_MODE="push"; break;;
- *) echo "❌ 无效选项,请输入 1 ~ 3";;
- esac
- done
- }
- # ============ 输入镜像信息 ============
- input_image_info() {
- read -p "镜像名称(默认: $IMAGE_NAME): " INPUT_NAME
- [[ -n "$INPUT_NAME" ]] && IMAGE_NAME="$INPUT_NAME"
- read -p "镜像标签(默认: $IMAGE_TAG): " INPUT_TAG
- [[ -n "$INPUT_TAG" ]] && IMAGE_TAG="$INPUT_TAG"
- read -p "Dockerfile 路径(默认: $DOCKERFILE): " INPUT_DF
- [[ -n "$INPUT_DF" ]] && DOCKERFILE="$INPUT_DF"
- # 自动修复 Dockerfile 路径
- if [[ -d "$DOCKERFILE" ]]; then
- if [[ -f "$DOCKERFILE/Dockerfile" ]]; then
- echo "⚠️ 检测到你输入的是目录,自动使用: $DOCKERFILE/Dockerfile"
- DOCKERFILE="$DOCKERFILE/Dockerfile"
- else
- echo "❌ 无法在目录中找到 Dockerfile: $DOCKERFILE/Dockerfile"
- exit 1
- fi
- elif [[ ! -f "$DOCKERFILE" ]]; then
- echo "❌ 指定的 Dockerfile 文件不存在: $DOCKERFILE"
- exit 1
- fi
- }
- # ============ 初始化 builder ============
- init_builder() {
- if ! docker buildx inspect multi-builder &>/dev/null; then
- echo "???? 创建 buildx builder..."
- docker buildx create --name multi-builder --use
- docker buildx inspect --bootstrap
- else
- docker buildx use multi-builder
- fi
- }
- # ============ 执行构建 ============
- run_build() {
- echo ""
- echo "???? 构建平台: $PLATFORMS"
- echo "???? Dockerfile: $DOCKERFILE"
- echo "???? 镜像: $IMAGE_NAME:$IMAGE_TAG"
- if [[ "$BUILD_MODE" == "push" ]]; then
- docker buildx build --platform "$PLATFORMS" -t "$IMAGE_NAME:$IMAGE_TAG" -f "$DOCKERFILE" . --push
- elif [[ "$BUILD_MODE" == "export" ]]; then
- docker buildx build --platform "$PLATFORMS" -t "$IMAGE_NAME:$IMAGE_TAG" -f "$DOCKERFILE" . \
- --output "type=docker,dest=$TAR_NAME"
- echo "✅ 导出完成: $TAR_NAME (平台: $PLATFORMS)"
- else
- docker buildx build --platform "$PLATFORMS" -t "$IMAGE_NAME:$IMAGE_TAG" -f "$DOCKERFILE" . --load
- fi
- echo "✅ 构建完成。"
- }
- # ============ 主程序 ============
- echo "=== 多平台 Docker 构建工具 ==="
- select_platforms
- select_build_mode
- input_image_info
- init_builder
- run_build