如何在x86架构下进行ARM镜像的构建与运行

这篇文章介绍一下使用QEMU进行容器化的构建和执行方式。

目录

  • QEMU是什么
  • 常见问题的场景
  • 问题再现
    • 事前准备
    • 启动容器并进入
  • 解决方法
  • 结果确认
  • 构建ARM镜像并确认


QEMU是什么

QEMU是一个通用的开源的跨平台仿真模拟器,提供user和system两种模式。其模拟的作用可是可以模拟在特定的体系结构下的应用的执行或者构建,比如在x86的体系结构的操作系统上运行ARM的应用。

常见问题的场景

在ARM体系结构的硬件环境中安装Docker,然后构建并运行ARM的镜像自然非常简单,但是如果没有ARM环境,只有x86的机器又想做这件事情,这时QEMU也就有了用武之地,比如用友的技术中台似乎就是通过QEMU来模拟ARM硬件进行模拟。

如何在x86架构下进行ARM镜像的构建与运行_第1张图片


问题再现

事前准备

  • 获取ARM格式的Alpine镜像

执行命令:docker pull arm64v8/alpine:3.12.1

liumiaocn:~ liumiao$ docker images |grep arm64v8/alpine
arm64v8/alpine                                                       3.12.1                          2e77e061c27f        6 days ago          5.32MB
liumiaocn:~ liumiao$ 

启动容器并进入

  • 启动容器并进入

执行命令:docker run --rm -it arm64v8/alpine:3.12.1 sh

可以看到在x86的机器上执行时出现了如下错误信息:

liumiaocn:~ liumiao$ uname -m
x86_64
liumiaocn:~ liumiao$ docker run --rm -it arm64v8/alpine:3.12.1 sh
standard_init_linux.go:211: exec user process caused "no such file or directory"
liumiaocn:~ liumiao$ 

有的时候提示现象不同,其实主要原因就在于体系架构不同所导致的

解决方法

可以根据需要到QEMU上下载对应的可执行文件进行执行,还有一种最为简单的方式就是使用容器的方式执行,使用如下命令,可使得当前机器可以直接直接模拟相应的体系结构

执行命令:docker run --rm --privileged multiarch/qemu-user-static --reset --persistent yes

liumiaocn:~ liumiao$ docker run --rm --privileged multiarch/qemu-user-static --reset --persistent yes
Setting /usr/bin/qemu-alpha-static as binfmt interpreter for alpha
Setting /usr/bin/qemu-arm-static as binfmt interpreter for arm
Setting /usr/bin/qemu-armeb-static as binfmt interpreter for armeb
Setting /usr/bin/qemu-sparc-static as binfmt interpreter for sparc
Setting /usr/bin/qemu-sparc32plus-static as binfmt interpreter for sparc32plus
Setting /usr/bin/qemu-sparc64-static as binfmt interpreter for sparc64
Setting /usr/bin/qemu-ppc-static as binfmt interpreter for ppc
Setting /usr/bin/qemu-ppc64-static as binfmt interpreter for ppc64
Setting /usr/bin/qemu-ppc64le-static as binfmt interpreter for ppc64le
Setting /usr/bin/qemu-m68k-static as binfmt interpreter for m68k
Setting /usr/bin/qemu-mips-static as binfmt interpreter for mips
Setting /usr/bin/qemu-mipsel-static as binfmt interpreter for mipsel
Setting /usr/bin/qemu-mipsn32-static as binfmt interpreter for mipsn32
Setting /usr/bin/qemu-mipsn32el-static as binfmt interpreter for mipsn32el
Setting /usr/bin/qemu-mips64-static as binfmt interpreter for mips64
Setting /usr/bin/qemu-mips64el-static as binfmt interpreter for mips64el
Setting /usr/bin/qemu-sh4-static as binfmt interpreter for sh4
Setting /usr/bin/qemu-sh4eb-static as binfmt interpreter for sh4eb
Setting /usr/bin/qemu-s390x-static as binfmt interpreter for s390x
Setting /usr/bin/qemu-aarch64-static as binfmt interpreter for aarch64
Setting /usr/bin/qemu-aarch64_be-static as binfmt interpreter for aarch64_be
Setting /usr/bin/qemu-hppa-static as binfmt interpreter for hppa
Setting /usr/bin/qemu-riscv32-static as binfmt interpreter for riscv32
Setting /usr/bin/qemu-riscv64-static as binfmt interpreter for riscv64
Setting /usr/bin/qemu-xtensa-static as binfmt interpreter for xtensa
Setting /usr/bin/qemu-xtensaeb-static as binfmt interpreter for xtensaeb
Setting /usr/bin/qemu-microblaze-static as binfmt interpreter for microblaze
Setting /usr/bin/qemu-microblazeel-static as binfmt interpreter for microblazeel
Setting /usr/bin/qemu-or1k-static as binfmt interpreter for or1k
liumiaocn:~ liumiao$ 

结果确认

然后再次使用同样命令即可发现可进入ARM格式的容器中,使用uname命令也可以确认到其体系结构为ARM格式(aarch64)

liumiaocn:~ liumiao$ docker run --rm -it arm64v8/alpine:3.12.1 sh
liumiaocn:~ liumiao$ docker run --rm -it arm64v8/alpine:3.12.1 sh
/ # uname -m
aarch64
/ # date
Wed Oct 28 11:42:38 UTC 2020
/ # 

可以看到此处为UTC的时间,主要用来跟后面CST的中国时区的时间进行对比

构建ARM镜像并确认

liumiaocn:~ liumiao$ docker run --rm -it arm64v8/alpine:3.12.1 sh
/ # uname -m
aarch64
/ # date
Wed Oct 28 11:42:38 UTC 2020
/ # 
  • 构建ARM镜像
    使用如下Dockerfile构建ARM镜像
liumiaocn:armimage liumiao$ cat Dockerfile 
FROM arm64v8/alpine:3.12.1
RUN set -x \
    && sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/' /etc/apk/repositories \
    && echo 'http://mirrors.aliyun.com/alpine/edge/testing' >> /etc/apk/repositories \
    && apk update \
    && addgroup -g 101 -S nginx \
    && adduser -S -D -H -u 101 -h /var/cache/nginx -s /sbin/nologin -G nginx -g nginx nginx \
    && apk add --no-cache --allow-untrusted tzdata \
    && ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime \
    && echo "Asia/Shanghai" > /etc/timezone \
    && /bin/rm -rf /tmp/* /var/cache/apk/*
liumiaocn:armimage liumiao$ 

使用docker build在x86机器上构建此ARM镜像

liumiaocn:armimage liumiao$ docker build -t myarmimage .
Sending build context to Docker daemon   2.56kB
Step 1/2 : FROM arm64v8/alpine:3.12.1
 ---> 2e77e061c27f
Step 2/2 : RUN set -x     && sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/' /etc/apk/repositories     && echo 'http://mirrors.aliyun.com/alpine/edge/testing' >> /etc/apk/repositories     && apk update     && addgroup -g 101 -S nginx     && adduser -S -D -H -u 101 -h /var/cache/nginx -s /sbin/nologin -G nginx -g nginx nginx     && apk add --no-cache --allow-untrusted tzdata     && ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime     && echo "Asia/Shanghai" > /etc/timezone     && /bin/rm -rf /tmp/* /var/cache/apk/*
 ---> Running in ffb20ef332b9
+ sed -i s/dl-cdn.alpinelinux.org/mirrors.aliyun.com/ /etc/apk/repositories
+ echo http://mirrors.aliyun.com/alpine/edge/testing
+ apk update
fetch http://mirrors.aliyun.com/alpine/v3.12/main/aarch64/APKINDEX.tar.gz
fetch http://mirrors.aliyun.com/alpine/v3.12/community/aarch64/APKINDEX.tar.gz
fetch http://mirrors.aliyun.com/alpine/edge/testing/aarch64/APKINDEX.tar.gz
v3.12.1-8-ge053f6efb7 [http://mirrors.aliyun.com/alpine/v3.12/main]
v3.12.1-5-g0954f48dc3 [http://mirrors.aliyun.com/alpine/v3.12/community]
v20200917-2860-gaeb4459434 [http://mirrors.aliyun.com/alpine/edge/testing]
OK: 16530 distinct packages available
+ addgroup -g 101 -S nginx
+ adduser -S -D -H -u 101 -h /var/cache/nginx -s /sbin/nologin -G nginx -g nginx nginx
+ apk add --no-cache --allow-untrusted tzdata
fetch http://mirrors.aliyun.com/alpine/v3.12/main/aarch64/APKINDEX.tar.gz
fetch http://mirrors.aliyun.com/alpine/v3.12/community/aarch64/APKINDEX.tar.gz
fetch http://mirrors.aliyun.com/alpine/edge/testing/aarch64/APKINDEX.tar.gz
(1/1) Installing tzdata (2020c-r0)
Executing busybox-1.31.1-r19.trigger
OK: 9 MiB in 15 packages
+ ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
+ echo Asia/Shanghai
+ /bin/rm -rf '/tmp/*' /var/cache/apk/APKINDEX.3a1aa0e6.tar.gz /var/cache/apk/APKINDEX.792faddc.tar.gz /var/cache/apk/APKINDEX.f46ee61c.tar.gz
Removing intermediate container ffb20ef332b9
 ---> 181684f5ebfc
Successfully built 181684f5ebfc
Successfully tagged myarmimage:latest
liumiaocn:armimage liumiao$ 
  • 在x86机器上运行ARM格式的镜像并确认结果
liumiaocn:armimage liumiao$ docker images |grep myarmimage
myarmimage                                                           latest                          181684f5ebfc        9 seconds ago       6.12MB
liumiaocn:armimage liumiao$ 
liumiaocn:armimage liumiao$ docker run --rm -it myarmimage sh
/ # uname -a
Linux 2bcff8eaae37 4.9.184-linuxkit #1 SMP Tue Jul 2 22:58:16 UTC 2019 aarch64 Linux
/ # uname -m
aarch64
/ # date
Wed Oct 28 19:46:04 CST 2020
/ # exit
liumiaocn:armimage liumiao$ 

可以看到此ARM镜像已经成功构建完成,并且运行起来之后新的容器中的时区已经按照Dockerfile中设定的那样改为中国时区CST不再是UTC,说明是可以正常运行的。

你可能感兴趣的:(容器化,Docker,ARM镜像,QEMU)