如何在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/

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章