Docker 构建 ARM64 镜像并导出二进制文件 — 完整操作指南

发布时间:2026/7/11 12:04:28
Docker 构建 ARM64 镜像并导出二进制文件 — 完整操作指南 Docker 构建 ARM64 镜像并导出二进制文件 — 完整操作指南基于hello.c源码使用 Docker 交叉编译生成 ARM64 平台可执行文件目录环境信息源码分析创建 Dockerfile构建 ARM64 镜像验证镜像导出镜像从镜像中提取二进制文件验证提取的二进制文件完整流程图常见问题1. 环境信息项目值宿主机系统CentOS Stream 10 (x86_64)Docker 版本已安装QEMU 版本7.2.0 (已注册 binfmt)工作目录/home/jp/下载/prj_test当前文件prj_test/ ├── hello.c # 源码 (109 bytes) ├── hello # x86_64 编译产物 (16KB) ├── Dockerfile # 已有 Dockerfile └── ...2. 源码分析// hello.c#includestdio.h#includestdlib.hintmain(){printf(hello world by centOS-10\n);return0;}简单的 C 程序输出一行字符串使用标准库stdio.h、stdlib.h编译需要gcc和 C 标准库已有二进制对比文件架构链接方式大小hellox86_64动态链接16KBhello-arm64-binARM aarch64静态链接136KB3. 创建 Dockerfile3.1 查看现有 DockerfilecatDockerfile3.2 创建新的 ARM64 构建 Dockerfile# Dockerfile.arm64 # # 阶段 1使用 ARM64 基础镜像进行交叉编译 # FROM arm64v8/gcc:12 AS builder # 安装依赖如有需要 RUN apt-get update \ apt-get install -y --no-install-recommends \ libc6-dev \ rm -rf /var/lib/apt/lists/* # 设置工作目录 WORKDIR /build # 复制源码 COPY hello.c . # 编译静态链接方便在任何 ARM64 设备运行 RUN gcc -static -O2 -o hello hello.c \ strip hello \ echo 编译完成 \ file hello # # 阶段 2最小化运行镜像 # FROM arm64v8/debian:bookworm-slim # 安装运行时依赖 RUN apt-get update \ apt-get install -y --no-install-recommends \ libc6 \ rm -rf /var/lib/apt/lists/* # 设置元数据 LABEL maintainerjp LABEL version1.0 LABEL descriptionhello.c ARM64 构建镜像 LABEL platformlinux/arm64 # 设置工作目录 WORKDIR /app # 从构建阶段复制二进制文件 COPY --frombuilder /build/hello . # 设置可执行权限 RUN chmod x hello # 默认运行 CMD [./hello]4. 构建 ARM64 镜像4.1 方式一使用 docker buildx推荐# 注册 QEMU 多架构支持如果还没有dockerrun--rm--privilegedmultiarch/qemu-user-static--reset-pyes# 构建 ARM64 镜像dockerbuildx build\--platformlinux/arm64\-thello-arm64:v1.0\-fDockerfile.arm64\--load\.4.2 方式二使用 docker build传统方式# 直接构建QEMU binfmt 已注册会自动使用 QEMU 编译dockerbuild\-thello-arm64:v1.0\-fDockerfile.arm64\.4.3 构建过程详解构建流程 ┌─────────────────────────────────────────────────────────────┐ │ 1. docker buildx build --platform linux/arm64 │ │ │ │ 2. 拉取 arm64v8/gcc:12 基础镜像 │ │ └── 自动通过 QEMU 模拟 ARM64 环境 │ │ │ │ 3. 在 QEMU 模拟的 ARM64 环境中执行 │ │ ├── apt-get update apt-get install │ │ ├── gcc -static -o hello hello.c ← ARM64 交叉编译 │ │ └── strip hello │ │ │ │ 4. 拉取 arm64v8/debian:bookworm-slim │ │ │ │ 5. 复制编译产物到运行镜像 │ │ │ │ 6. 标记镜像hello-arm64:v1.0 │ └─────────────────────────────────────────────────────────────┘5. 验证镜像5.1 查看镜像# 列出镜像dockerimages|grephello# 预期输出# hello-arm64 v1.0 abc123456789 10 seconds ago 120MB5.2 查看镜像架构# 检查镜像架构dockerinspect hello-arm64:v1.0|grepArchitecture# 预期输出# Architecture: arm645.3 运行测试# 直接运行QEMU binfmt 会自动处理 ARM64 二进制dockerrun--rmhello-arm64:v1.0# 预期输出# hello world by centOS-105.4 进入容器查看# 交互式进入容器dockerrun--rm-ithello-arm64:v1.0bash# 在容器内查看二进制信息filehello# 输出hello: ELF 64-bit LSB executable, ARM aarch64...# 退出容器exit6. 导出镜像6.1 导出为 tar 文件# 导出镜像为 tar 文件dockersave-ohello-arm64.tar hello-arm64:v1.0# 查看导出文件ls-lhhello-arm64.tar# 预期输出# -rw------- 1 jp jp 120M 7月 10 14:30 hello-arm64.tar6.2 压缩导出可选减小体积# 导出并压缩dockersave hello-arm64:v1.0|gziphello-arm64.tar.gz# 查看压缩后大小ls-lhhello-arm64.tar.gz# 预期输出# -rw-r--r-- 1 jp jp 50M 7月 10 14:32 hello-arm64.tar.gz6.3 验证导出内容# 查看 tar 包结构tartf hello-arm64.tar|head-20# 预期输出OCI 格式# blobs/# blobs/sha256/# blobs/sha256/xxxxx...# index.json# manifest.json# oci-layout7. 从镜像中提取二进制文件7.1 方式一使用 docker cp推荐# 创建临时容器不启动dockercreate--namehello-tmp hello-arm64:v1.0# 从容器中拷贝二进制文件dockercphello-tmp:/app/hello ./hello-arm64# 清理临时容器dockerrmhello-tmp# 验证文件ls-lhhello-arm647.2 方式二从 tar 包手动提取# 步骤 1解压 OCI 镜像mkdir-p/tmp/hello-ocitarxf hello-arm64.tar-C/tmp/hello-oci# 步骤 2查看 manifest 获取层信息cat/tmp/hello-oci/manifest.json|python3-mjson.tool# 步骤 3找到层文件通常是 blobs/sha256/ 下的 .gz 文件ls-la/tmp/hello-oci/blobs/sha256/# 步骤 4解压层文件层是 gzip 压缩的 tarmkdir-p/tmp/hello-rootfstarxzf /tmp/hello-oci/blobs/sha256/*.gz-C/tmp/hello-rootfs# 步骤 5查找并复制二进制文件find/tmp/hello-rootfs-namehello-typef-execcp{}./hello-arm64\;chmodx ./hello-arm64# 步骤 6清理临时文件rm-rf/tmp/hello-oci /tmp/hello-rootfs7.3 方式三一行命令提取# 一行命令完成提取tarxf hello-arm64.tar-C/tmp\tarxzf /tmp/blobs/sha256/*.gz-C/tmp\cp/tmp/app/hello ./hello-arm64\chmodx ./hello-arm64\rm-rf/tmp/blobs /tmp/index.json /tmp/manifest.json /tmp/oci-layout8. 验证提取的二进制文件8.1 检查文件架构# 检查二进制架构filehello-arm64# 预期输出# hello-arm64: ELF 64-bit LSB executable, ARM aarch64, version 1 (SYSV),# statically linked, BuildID[sha1]xxx, for GNU/Linux 3.2.0, stripped8.2 检查文件大小# 查看文件信息ls-lhhello-arm64# 预期输出# -rwxr-xr-x 1 jp jp 136K 7月 10 14:35 hello-arm648.3 在 ARM64 设备上运行# 直接在 ARM64 设备上运行./hello-arm64# 预期输出# hello world by centOS-108.4 在 x86 主机上使用 QEMU 测试# 使用 QEMU 运行如果 binfmt 未注册qemu-aarch64-static ./hello-arm64# 预期输出# hello world by centOS-109. 完整流程图┌─────────────────────────────────────────────────────────────────┐ │ Docker 构建 ARM64 镜像流程 │ ├─────────────────────────────────────────────────────────────────┤ │ │ │ ┌──────────┐ ┌──────────────┐ ┌──────────────┐ │ │ │ hello.c │───│ Dockerfile │───│ Docker Image │ │ │ │ (源码) │ │ (构建配置) │ │ (ARM64) │ │ │ └──────────┘ └──────────────┘ └──────┬───────┘ │ │ │ │ │ ┌────────────────────┼────────────────┐ │ │ │ │ │ │ │ ▼ ▼ ▼ │ │ ┌──────────────┐ ┌──────────────┐ ┌────────┐ │ │ │ docker save │ │ docker cp │ │ docker │ │ │ │ 导出为 tar │ │ 提取二进制 │ │ run │ │ │ └──────┬───────┘ └──────┬───────┘ └────────┘ │ │ │ │ │ │ ▼ ▼ │ │ ┌──────────────┐ ┌──────────────┐ │ │ │ hello-arm64 │ │ hello-arm64 │ │ │ │ .tar │ │ (二进制文件) │ │ │ └──────────────┘ └──────────────┘ │ │ │ │ │ ▼ │ │ ┌──────────────┐ │ │ │ tar 解压 │ │ │ │ 提取二进制 │ │ │ └──────┬───────┘ │ │ │ │ │ ▼ │ │ ┌──────────────┐ │ │ │ hello-arm64 │ │ │ │ (可执行文件) │ │ │ └──────────────┘ │ │ │ └─────────────────────────────────────────────────────────────────┘10. 常见问题Q1: 构建时提示 “exec format error”# 原因QEMU binfmt 未注册# 解决注册 QEMU 多架构支持dockerrun--rm--privilegedmultiarch/qemu-user-static--reset-pyesQ2: 构建速度慢# 原因QEMU 模拟 ARM64 效率较低# 解决使用 BuildKit 缓存DOCKER_BUILDKIT1dockerbuildx build\--platformlinux/arm64\-thello-arm64:v1.0\-fDockerfile.arm64\--load\.# 或使用远程 builder需要配置dockerbuildx create--namemybuilder--driverdocker-container--usedockerbuildx build--platformlinux/arm64-thello-arm64:v1.0--load.Q3: 导出的 tar 包太大# 方式 1压缩导出dockersave hello-arm64:v1.0|gziphello-arm64.tar.gz# 方式 2优化 Dockerfile使用更小的基础镜像# 将 arm64v8/debian:bookworm-slim 改为 arm64v8/alpine:3.18Q4: 提取的二进制无法运行# 检查架构是否正确filehello-arm64# 如果是动态链接需要目标设备有对应库# 解决使用静态编译Dockerfile 中已使用 -staticQ5: 如何推送到私有仓库# 打标签dockertag hello-arm64:v1.0 your-registry.com/hello-arm64:v1.0# 推送dockerpush your-registry.com/hello-arm64:v1.0# 其他设备拉取dockerpull your-registry.com/hello-arm64:v1.011. 实际执行记录以下为在 CentOS Stream 10 (x86_64) 上的实际操作记录11.1 构建镜像$dockerbuildx build--platformlinux/arm64-thello-arm64:v1.0-fDockerfile.arm64--load.构建结果编译阶段gcc -static -O2 -o hello hello.c成功二进制验证hello: ELF 64-bit LSB executable, ARM aarch64, version 1 (GNU/Linux), statically linked, stripped镜像大小28.4MB11.2 验证镜像$dockerimages|grephello-arm64 hello-arm64:latest 8dafc3dcbf5e 170kB hello-arm64:v1.0 783e36dfc2f428.4MB $dockerinspect hello-arm64:v1.0|grepArchitectureArchitecture:arm64$dockerrun--rmhello-arm64:v1.0 hello world by centOS-1011.3 导出镜像$dockersave-ohello-arm64-v1.0.tar hello-arm64:v1.0 $ls-lhhello-arm64-v1.0.tar -rw-------1jp jp 28M7月1011:42 hello-arm64-v1.0.tar11.4 提取二进制文件$dockercreate--namehello-tmp hello-arm64:v1.0 $dockercphello-tmp:/app/hello ./hello-arm64-v1.0 $dockerrmhello-tmp $file./hello-arm64-v1.0 ./hello-arm64-v1.0: ELF64-bit LSB executable, ARM aarch64, version1(GNU/Linux), statically linked,forGNU/Linux3.7.0, stripped $ls-lh./hello-arm64-v1.0 -rwxr-xr-x1jp jp 586K7月1011:41 ./hello-arm64-v1.011.5 测试运行$ qemu-aarch64-static ./hello-arm64-v1.0 hello world by centOS-1011.6 产出文件清单文件类型架构大小说明hello-arm64-v1.0.tarDocker 镜像arm6428MB可通过docker load导入hello-arm64-v1.0ELF 可执行文件ARM aarch64586KB静态链接可直接在 ARM64 设备运行附录快速命令参考# 构建 dockerbuildx build--platformlinux/arm64-thello-arm64:v1.0-fDockerfile.arm64--load.# 运行 dockerrun--rmhello-arm64:v1.0# 导出 dockersave-ohello-arm64.tar hello-arm64:v1.0# 提取二进制方式一 dockercreate--nametmp hello-arm64:v1.0dockercptmp:/app/hello ./hello-arm64dockerrmtmp# 提取二进制方式二 tarxf hello-arm64.tar-C/tmptarxzf /tmp/blobs/sha256/*.gz-C/tmpcp/tmp/app/hello ./hello-arm64# 验证 filehello-arm64 ./hello-arm64