ARM架构Docker镜像构建-基础知识
介绍ARM版本的Docker镜像的构建,包括ARM机器上Docker的安装,在ARM机器上构建镜像,及在amd64机器上使⽤buildx交叉构建arm版本镜像。
前⾔
现在很多地⽅都对服务的国产化适配有所要求,⼀般的国产化平台都提供arm版本的linux云环境供我们进⾏服务部署,因此需要构建arm版本的镜像。
测试机信息
CPU FT-1500A 4核 arm64
内存8G
OS麒麟V10
包管理器apt
ARM机器上安装Docker
Docker⽀持如下系统及架构
国产系统依据安装包的格式选择对应的参考系统即可,如麒麟v10基于ubuntu,可以按进⾏安装。
查看系统信息
geostar@geostar-ft1500a:~$ cat /proc/version
Linux version 4.4.131-20200515.kylin.desktop-generic (YHKYLIN-OS@Kylin) (gcc version 5.5.0 20171010 (Ubuntu/Linaro 5.5.0-12ubuntu1~16.04) ) #kylin SMP Fri May 15 11:29:10 CST 2020
这⾥可以看到系统是基于ubuntu16.04 的,所以我们添加ubuntu16.04(xenial)的软件源
添加软件源
参考:
mirrors.tuna.tsinghua.edu/help/ubuntu/
mirrors.tuna.tsinghua.edu/ubuntu-ports/
添加清华镜像软件源(arm架构)
# 默认注释了源码镜像以提⾼ apt update 速度,如有需要可⾃⾏取消注释
一生去守候deb mirrors.tuna.tsinghua.edu/ubuntu-ports/ xenial main restricted universe multiverse
# deb-src mirrors.tuna.tsinghua.edu/ubuntu-ports/ xenial main restricted universe multiverse
deb mirrors.tuna.tsinghua.edu/ubuntu-ports/ xenial-updates main restricted universe multiverse
# deb-src mirrors.tuna.tsinghua.edu/ubuntu-ports/ xenial-updates main restricted universe multiverse
deb mirrors.tuna.tsinghua.edu/ubuntu-ports/ xenial-backports main restricted universe multiverse
# deb-src mirrors.tuna.tsinghua.edu/ubuntu-ports/ xenial-backports main restricted universe multiverse
deb mirrors.tuna.tsinghua.edu/ubuntu-ports/ xenial-security main restricted universe multiverse
# deb-src mirrors.tuna.tsinghua.edu/ubuntu-ports/ xenial-security main restricted universe multiverse
更新:
sudo apt-get install apt-transport-https
sudo apt-get clean
sudo apt-get update
安装Docker
# 卸载旧版本docker
sudo apt-get remove docker docker-engine docker.io containerd runc
sudo apt-get update
sudo apt-get install \
apt-transport-https \
ca-certificates \
curl \
gnupg-agent \
software-properties-common
刘真君
curl -fsSL download.docker/linux/ubuntu/gpg | sudo apt-key add -
# 确认key添加成功(查:9DC8 5822 9FC7 DD38 854A  E2D8 8D81 803C 0EBF CD88)
sudo apt-key fingerprint 0EBFCD88
编辑 /etc/apt/source.list,添加docker软件源(arm64 xenial),并保存
girlsgeneration# docs.docker/engine/install/ubuntu/
deb [arch=arm64] download.docker/linux/ubuntu xenial stable
安装 docker
sudo apt-get update
# 安装Docker
sudo apt-get install docker-ce docker-ce-cli containerd.io
# 安装成功,查看版本
docker --version
Docker version 19.03.12, build 48a6621
在Dockerhub上查已有的arm镜像
实际上很多镜像都有构建arm版本,对于直接使⽤的镜像,或者作为Dockerfile中FROM的镜像,如果有对应的arm版本,则可以直接使⽤,省略构建过程。以为例,在dockerhub上可以看到
在具体的tag中也可以看到版本的镜像是否⽀持arm架构
但需要使⽤的镜像不是我们⾃⼰编译的时候,可以通过这种⽅式来确认该镜像是否有对应的arm版本。
ARM版本镜像构建(⾮ARM机器上执⾏)
参考:
隋俊波电视剧
-
-
构建ARM镜像的两种⽅式
对于构建镜像的ARM版本,有如下两种⽅式:
1. 在ARM机器上使⽤ docker build 进⾏构建;
2. 在X86/AMD64 的机器上使⽤ docker buildx 进⾏交叉构建;
实际测试中发现第⼀种⽅式在某些情况下会有问题,建议采⽤结合采⽤这⼆种⽅式;
关于第⼆种构建⽅式,可先阅读进⾏了解,以下简要介绍使⽤buildx交叉构建的⽅式;
视频dj⚠ 注意:
1. 交叉构建和交叉运⾏的⽅式会有⼀些⽆法预知的问题,建议简单的构建步骤(如只是下载解压对应架构的⽂件)可考虑在x86下
交叉构建,复杂的(如需要编译的)则直接在arm机器上进⾏构建;
2. 实际测试发现,使⽤在x86平台下运⾏arm版本的镜像时,执⾏简单的命令可以成功(如arch),执⾏某些复杂的程序时(如启
动java虚拟机),会⽆响应,所以镜像的验证⼯作应尽量放置到arm机器上进⾏;
上⾯第⼆点按如下⽅式测试:
1. docker run --rm --platform=linux/arm64 openjdk:8u212-jre-alpine arch 可正常输出;
2. docker run --rm --platform=linux/arm64 openjdk:8u212-jre-alpine java -version 则会卡住,且需要使⽤docker stop停⽌容器才可以退出
容器;
启⽤试验性功能
参考:docs.docker/engine/reference/commandline/cli/#experimental-features
注意:buildx 仅⽀持 docker19.03 及以上docker版本
如需使⽤ buildx,需要开启docker的实验功能后,才可以使⽤,开启⽅式:
编辑 /etc/docker/daemon.json
添加:
{
"experimental":true
}
编辑 ~/.docker/config.json 添加:
"experimental":"enabled"
重启Docker使⽣效:
sudo systemctl daemon-reload
sudo systemctl restart docker
确认是否开启:
数码宝贝4主题曲docker version -f’{{.Server.Experimental}}’
如果输出true,则表⽰开启成功
使⽤buildx构建
buildx 的详细使⽤可参考:
创建 buildx 构建器
使⽤ docker buildx ls 命令查看现有的构建器
docker buildx ls
创建并构建器:
# 下⾯的创建命令任选⼀条符合情况的即可
# 1. 不指定任何参数创建
docker buildx create --use --name multiarch-builder
# 2. 如创建后使⽤docker buildx ls 发现构建起没有arm架构⽀持,可使⽤--platform明确指定要⽀持的构建类型,如以下命令
docker buildx create --platform linux/arm64,linux/arm/v7,linux/arm/v6 --name multiarch-builder
# 3. 如需在buildx访问私有registry,可使⽤host模式,并⼿动指定配置⽂件,避免buildx时⽆法访问本地的registry主机
docker buildx create --platform linux/amd64,linux/arm64,linux/arm/v7,linux/arm/v6  --driver-opt network=host --config=/Users/hanlyjiang/.docker/l --use --name multiarch-builder
# github/moby/buildkit/blob/master/l.md
# registry configures a new Docker register used for cache import or output.
[registry."star"]
mirrors = ["star"]
http = true
insecure = true
启⽤构建器
# 初始化并激活
docker buildx inspect multiarch-builder --bootstrap
确认成功
# 使⽤ docker buildx ls 查看
docker buildx ls
修改Dockerfile
对 Dockerfile 的修改,⼤致需要进⾏如下操作:
1. 确认基础镜像(FROM)是否有arm版本,如果有,则可以不⽤改动,如果没有,则需要寻替代镜像,如没有替代镜像,则可能需
要⾃⾏编译;
2. 确认dockerfile的各个步骤中是否有依赖CPU架构的,如果有,则需要替换成arm架构的,如在构建jitis的镜像时,Dockerfile中有添
加⼀个amd64架构的软件
ADD github/just-containers/s6-overlay/releases/download/v1.21.4.0/ /tmp/
此时需要替换为下⾯的地址(注意amd64替换成了aarch64,当然,需要先确认下载地址中有⽆对应架构的gz包,不能简单做字符替换):ADD github/just-containers/s6-overlay/releases/download/v1.21.4.0/ /tmp/
当然,我们需要确认该软件有此架构的归档包,如果没有,则需要考虑从源码构建;
提⽰:
怎么确定⼀个可执⾏⽂件/so库的对应的执⾏架构? 可以通过 file {可执⾏⽂件路径} 来查看,
如下⾯时macOS上执⾏file命令的输⼊,可以发现macOS上的git程序可以兼容两种架构-x86_64&arm64e:
file$(which git)
/
usr/bin/git: Mach-O universal binary with 2 architectures: [x86_64:Mach-O 64-bit executable x86_64][arm64e:Mach-O 64-bit executable arm64e] /usr/bin/git (for architecture x86_64): Mach-O 64-bit executable x86_64
/usr/bin/git (for architecture arm64e): Mach-O 64-bit executable arm64e
下⾯的命令则对⼀个so⽂件执⾏了file,可以看到其中的架构信息 ARM aarch64:
file /lib/aarch64-linux-gnu/libpthread-2.23.so
/lib/aarch64-linux-gnu/libpthread-2.23.so: ELF 64-bit LSB shared object, ARM aarch64, version 1 (GNU/Linux), dynamically linked, interpreter /lib/ld-li nux-aarch64.so.1, BuildID[sha1]=880365ebb22114e4c10108b73243144d5fa315dc, for GNU/Linux 3.7.0, not stripped
docker buildx 构建arm64镜像的命令
使⽤ --platform来指定架构,使⽤ --push 或 --load 来指定构建完毕后的动作。
docker buildx build --platform=linux/arm64,linux/amd64 -t xxxx:tag . --push
提⽰:当指定多个架构时,只能使⽤ --push 推送到远程仓库,⽆法 --load,推送成功后再通过 docker pull --platform 来拉取指定架构的镜像
检查构建成果
1. 通过 docker buildx imagetools inspect 命令查看镜像信息,看是否有对应的arm架构信息;
2. 实际运⾏镜像,确认运⾏正常;(在arm机器上执⾏)
提⽰:如运⾏时输出 exec format error 类似错误,则表⽰镜像中部分可执⾏⽂件架构不匹配。
在x86上运⾏arm镜像
可参考 ,简要描述如下: