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

📅 2026/7/11 12:09:38 👁️ 阅读次数 📝 编程学习
Docker 构建 ARM64 镜像并导出二进制文件 — 完整操作指南

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

基于hello.c源码,使用 Docker 交叉编译生成 ARM64 平台可执行文件


目录

  1. 环境信息
  2. 源码分析
  3. 创建 Dockerfile
  4. 构建 ARM64 镜像
  5. 验证镜像
  6. 导出镜像
  7. 从镜像中提取二进制文件
  8. 验证提取的二进制文件
  9. 完整流程图
  10. 常见问题

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.hstdlib.h
  • 编译需要gcc和 C 标准库

已有二进制对比

文件架构链接方式大小
hellox86_64动态链接16KB
hello-arm64-binARM aarch64静态链接136KB

3. 创建 Dockerfile

3.1 查看现有 Dockerfile

catDockerfile

3.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 120MB

5.2 查看镜像架构

# 检查镜像架构dockerinspect hello-arm64:v1.0|grepArchitecture# 预期输出:# "Architecture": "arm64"

5.3 运行测试

# 直接运行(QEMU binfmt 会自动处理 ARM64 二进制)dockerrun--rmhello-arm64:v1.0# 预期输出:# hello world by centOS-10

5.4 进入容器查看

# 交互式进入容器dockerrun--rm-ithello-arm64:v1.0bash# 在容器内查看二进制信息filehello# 输出:hello: ELF 64-bit LSB executable, ARM aarch64...# 退出容器exit

6. 导出镜像

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.tar

6.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.gz

6.3 验证导出内容

# 查看 tar 包结构tartf hello-arm64.tar|head-20# 预期输出(OCI 格式):# blobs/# blobs/sha256/# blobs/sha256/xxxxx...# index.json# manifest.json# oci-layout

7. 从镜像中提取二进制文件

7.1 方式一:使用 docker cp(推荐)

# 创建临时容器(不启动)dockercreate--namehello-tmp hello-arm64:v1.0# 从容器中拷贝二进制文件dockercphello-tmp:/app/hello ./hello-arm64# 清理临时容器dockerrmhello-tmp# 验证文件ls-lhhello-arm64

7.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-rootfs

7.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-layout

8. 验证提取的二进制文件

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, stripped

8.2 检查文件大小

# 查看文件信息ls-lhhello-arm64# 预期输出:# -rwxr-xr-x 1 jp jp 136K 7月 10 14:35 hello-arm64

8.3 在 ARM64 设备上运行

# 直接在 ARM64 设备上运行./hello-arm64# 预期输出:# hello world by centOS-10

8.4 在 x86 主机上使用 QEMU 测试

# 使用 QEMU 运行(如果 binfmt 未注册)qemu-aarch64-static ./hello-arm64# 预期输出:# hello world by centOS-10

9. 完整流程图

┌─────────────────────────────────────────────────────────────────┐ │ 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-pyes

Q2: 构建速度慢

# 原因: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.18

Q4: 提取的二进制无法运行

# 检查架构是否正确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.0

11. 实际执行记录

以下为在 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-10

11.3 导出镜像

$dockersave-ohello-arm64-v1.0.tar hello-arm64:v1.0 $ls-lhhello-arm64-v1.0.tar -rw-------1jp jp 28M71011:42 hello-arm64-v1.0.tar

11.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 586K71011:41 ./hello-arm64-v1.0

11.5 测试运行

$ qemu-aarch64-static ./hello-arm64-v1.0 hello world by centOS-10

11.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