Docker 构建 ARM64 镜像并导出二进制文件 — 完整操作指南
📅 2026/7/11 12:09:38
👁️ 阅读次数
📝 编程学习
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#include<stdio.h>#include<stdlib.h>intmain(){printf("hello world by centOS-10\n");return0;}- 简单的 C 程序,输出一行字符串
- 使用标准库
stdio.h、stdlib.h - 编译需要
gcc和 C 标准库
已有二进制对比
| 文件 | 架构 | 链接方式 | 大小 |
|---|---|---|---|
hello | x86_64 | 动态链接 | 16KB |
hello-arm64-bin | ARM aarch64 | 静态链接 | 136KB |
3. 创建 Dockerfile
3.1 查看现有 Dockerfile
catDockerfile3.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 maintainer="jp" LABEL version="1.0" LABEL description="hello.c ARM64 构建镜像" LABEL platform="linux/arm64" # 设置工作目录 WORKDIR /app # 从构建阶段复制二进制文件 COPY --from=builder /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": "arm64"5.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|gzip>hello-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 压缩的 tar)mkdir-p/tmp/hello-rootfstarxzf /tmp/hello-oci/blobs/sha256/*.gz-C/tmp/hello-rootfs# 步骤 5:查找并复制二进制文件find/tmp/hello-rootfs-name"hello"-typef-execcp{}./hello-arm64\;chmod+x ./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&&\chmod+x ./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_BUILDKIT=1dockerbuildx 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|gzip>hello-arm64.tar.gz# 方式 2:优化 Dockerfile,使用更小的基础镜像# 将 arm64v8/debian:bookworm-slim 改为 arm64v8/alpine:3.18Q4: 提取的二进制无法运行
# 检查架构是否正确filehello-arm64# 如果是动态链接,需要目标设备有对应库# 解决:使用静态编译(Dockerfile 中已使用 -static)Q5: 如何推送到私有仓库
# 打标签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.4MB
11.2 验证镜像
$dockerimages|grephello-arm64 hello-arm64:latest 8dafc3dcbf5e 170kB hello-arm64:v1.0 783e36dfc2f428.4MB $dockerinspect hello-arm64:v1.0|grepArchitecture"Architecture":"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.tar | Docker 镜像 | arm64 | 28MB | 可通过docker load导入 |
hello-arm64-v1.0 | ELF 可执行文件 | ARM aarch64 | 586KB | 静态链接,可直接在 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
编程学习
技术分享
实战经验