在x86_64机器上构建arm64镜像

目录

有几种办法可以打包出arm64的镜像

  • 直接在arm机器上执行编译和打包
  • 通过qemu模拟arm环境
  • 利用docker提供的buildx(需要启用试验性特性)

我没有arm的机器~,所以我主要试了一下下面两种方式。

借助qemu-user-static镜像打包

文档:https://github.com/multiarch/qemu-user-static

开启arm平台支持:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
$ docker run --rm --privileged multiarch/qemu-user-static:register --reset

$ docker build --rm -t "test/integration/ubuntu" -<<EOF
FROM multiarch/qemu-user-static:x86_64-aarch64 as qemu
FROM arm64v8/ubuntu
COPY --from=qemu /usr/bin/qemu-aarch64-static /usr/bin
EOF

$ docker run --rm -t "test/integration/ubuntu" uname -m
aarch64

在运行qemu-user-static:register镜像的时候,就通过内核中的binfmt_misc机制注入了哪些可执行文件可以被识别。

注意:需要将qemu-aarch64-static文件 copy 到/usr/bin目录。

binfmt_misc是Linux内核说提供的一种扩展机制, 使得更多类型的文件得以成为"可执行"文件.Linux内核本身支持ELF、a.out、脚本(也就是上面所说的第一行#!指定解释器的方式)这集中"可执行文件".但它还提供了一个称为binfmt_misc的内核模块, 通过这个模块可以动态注册一些"可执行文件格式",注册之后我们就可以直接"执行"这个程序文件了.

通过buildx打包支持多架构的镜像

文档:https://docs.docker.com/buildx/working-with-buildx/

首先需要开启这个实验性的功能,怎么开启看这里:https://github.com/docker/cli/blob/master/experimental/README.md

  • docker cloent: 在~/.docker/config.json 加入``写入"experimental":"enabled"
  • dcoker daemon: 启动参数上加上–experimental或者/etc/docker/daemon.json写入 "experimental": true

进行初始化:

1
2
3
docker buildx create --name builderx
docker buildx use builderx
docker buildx inspect --bootstrap #这一步会从外网拉取`moby/buildkit`镜像,貌似还改不了

接下来你就可以通过如下命令去构建多种架构的镜像:

1
docker buildx build --platform linux/amd64,linux/arm64 -f Dockerfile -t silenceper/reverse-proxy .  --push

--push参数表示构建完成之后,并push到镜像仓库当中。

因为镜像仓库支持一个仓库上传多种架构,并且会根据构建平台pull相匹配架构的镜像,所以我们可以在一个Dockerfile,并且通过一个命令打包镜像并push。

这里用到的Dockerfile在这里:https://github.com/silenceper/reverse-proxy/blob/master/Dockerfile

通过docker的多阶段构建将编译和打包放在一起了,隔离了环境的差异。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
FROM golang:alpine as builder
ADD . /go/src/github.com/silenceper/reverse-proxy/
RUN cd /go/src/github.com/silenceper/reverse-proxy/ \
  && go get -v \
  && CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o app .

FROM alpine
MAINTAINER silenceper <silenceper@gmail.com>
COPY --from=builder /go/src/github.com/silenceper/reverse-proxy/app /bin/app
ENTRYPOINT ["/bin/app"]
EXPOSE 80

总结

最方便的肯定是直接通过buildx进行打包和编译,但是我的环境没法访问外网,又没法拉取外网的镜像,所以最终还是选择使用qemu-user-static打包出来了。

参考


关注公众号,获取最新文章推送