如何在x86物理架构上搭建交叉编译ARM容器运行平台环境

原理:简单的理解其实就是在x86平台上生成ARM平台的可执行代码。
为什么要这么做?
答:目的平台上不允许或不能够安装我们所需要的编译器,而我们又需要这个编译器的某些特征;有时是因为目的平台上的资源贫乏,无法运行我们所需要编译器;有时又是因为目的平台还没有建立,连操作系统都没有,根本谈不上运行什么编译器。
受限于平台的环境和性能就产生了交叉编译主要方式两种:虚拟机或者编译器

QEMU:是一个主机上的虚拟机监视器,通过动态二进制转换来模拟CPU,提供一系列的硬件模型,使用guest os让自己和硬件直接接触,其实是和QEMU模拟出来的硬件打交道,QEMU再把这些指令翻译给真正硬件进行操作。

运行模式
QEMU提供多种运行模式:
User-mode emulation: 这种模式下QEMU上仅进运行一个linux或其他系统程序,由和主机不同的指令集来编译运行。这种模式一般用于交叉编译及交叉调试使用。

System emulation: 这种模式QEMU模拟一个完整的操作系统,包括外设。可用来实现一台物理主机模拟提供多个虚拟主机。QEMU也支持多种guest OS:Linux,windows,BSD等。支持多种指令集 x86,MIPS,ARMv8,PowerCP,SPARC,MicroBlaze等等。

KVM Hosting: 这种模式下QEMU处理包括KVM镜像的启停和移植,也涉及到硬件的模拟,guest的程序运行由KVM请求调用QEMU来实现。

Xen Hosting:这种模式下QEMU仅参与硬件模拟,guest的运行完全对QEMU不可见。

其中User-mode emulation就是用来做交叉编译用的。

实验环境:Ubuntu18.04
首先,安装qemu-user安装包,并更新qemu-arm的状态:

apt-get update && apt-get install -y --no-install-recommends qemu-user-static binfmt-support
update-binfmts --enable qemu-arm
update-binfmts --display qemu-arm
sudo chmod a+x /usr/bin/qemu-*

查看qemu-arm的版本:

qemu-arm-static -version

下载arm架构的容器(在dockerhub可以找到各种非x86架构的镜像):

docker pull docker.io/arm64v8/ubuntu:16.04
docker run -itd --privileged --name ubuntu -v /usr/bin/qemu-aarch64-static:/usr/bin/qemu-aarch64-static docker.io/arm64v8/ubuntu:16.04 /bin/bash

最后进入容器访问:

docker exec -it ubuntu /bin/bash

完事

在编写dockerfile的时候想执行RUN的话需将qemu拷贝到容器中,例如:

FROM docker.io/arm64v8/ubuntu:16.04
COPY ./qemu-aarch64-static /usr/bin
RUN apt-get update && apt-get install nginx
EXPOSE 80

注意:如果内核无法“理解”ARM ELF 文件,需要binfmt_misc 了,确定内核开启了 binfmt_misc,就可以手动添加:

mount binfmt_misc -t binfmt_misc /proc/sys/fs/binfmt_misc
echo ':arm:M::\x7fELF\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x28\x00:\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff:/usr/bin/qemu-arm-static:' > /proc/sys/fs/binfmt_misc/register

如果在获取镜像的时候提示:no matching manifest for linux/amd64 in the manifest list entries的话,那么需要手动修改 ~/.docker/config.json 文件,添加 {“experimental”:“enabled”}为 docker-cli 开启 docker manifest 命令功能。
例如:

$ docker manifest inspect python:3.6.5
{
    
    
   "schemaVersion": 2,
   "mediaType": "application/vnd.docker.distribution.manifest.list.v2+json",
   "manifests": [
      {
    
    
         "mediaType": "application/vnd.docker.distribution.manifest.v2+json",
         "size": 2007,
         "digest": "sha256:ebfe81b95c56a242a94001b0385f9c14b8972512e773a112adf87a30ed8e774f",
         "platform": {
    
    
            "architecture": "amd64",
            "os": "linux"
         }
      },
      ...
   ]
}

python:3.6.5 镜像有完整 manifests 描述了镜像支持的平台信息,因此在不同平台直接执行 docker pull python:3.6.5 就会自动根据平台架构获取不同的镜像。

帮助文档:
https://juejin.im/entry/5bc35c5ce51d450e5c47b96d
https://blog.csdn.net/sunSHINEEzy/article/details/80015638
https://www.tomczhen.com/2018/05/13/cross-platform-build-docker-image/

猜你喜欢

转载自blog.csdn.net/ZhanBiaoChina/article/details/105586510