随着 5G 时代的临近, 低延迟网络, AI 硬件算力提升, 和智能化应用快速发展, 一个万物智联的时代必将到来. 我们需要将智能决策, 实时处理能力从云延展到边缘和 IoT 设备端. 阿里云容器服务推出了边缘容器, 支持云 - 边 - 端应用一体协同. 在 IoT 和边缘计算场景, 我们不但需要支持 X86 芯片也要提供对 ARM 架构芯片的支持. 此外随着国产 ARM CPU 的快速发展, 也需要我们在产品测提供 ARM 版本的容器产品支持. 本文将介绍一些简单的技术来加速 ARM 容器应用的开发和测试流程.
X86 环境构建 ARM 架构 Docker 镜像
今年 4 月 24 日, Docker 公司与 ARM 公司宣布合作伙伴计划, 为 Docker 的工具优化面向 ARM 平台的开发者体验. Docker 开发者可以在 x86 桌面端为 ARM 设备构建容器镜像, 并可将容器应用部署至云端, 边缘以及物联网设备. 整个容器构建流程非常简单, 无需任何交叉编译步骤.
Docker Desktop 是 macOS 和 Windows 平台的容器开发环境. Docker 会借助宿主机操作系统的虚拟化技术, 如 Windows 的 Hyper-V 和 macOS 的 HyperKit, 来运行 Docker 开发环境. 在最新的 Docker 版本中, LinuxKit 作为面向容器的操作系统, 增加了 QEMU 模拟器, 可以支持 ARM 架构 CPU. 现在可以支持 ARM/v6, ARM/v7 和 arm64 架构应用. 架构图如下:
首先安装最新 edge 版本的 Docker Desktop,Docker Engine 版本需要大于 19.03.
在 Docker Desktop 中, 选择 "Preference..."> "Command Line"> "Enable experimental features" 开启实验特性.
Docker 新增加了 docker buildx 命令
- $ docker buildx --help
- Usage: docker buildx COMMAND
- Build with BuildKit
- Management Commands:
- imagetools Commands to work on images in registry
- Commands:
- bake Build from a file
- build Start a build
- create Create a new builder instance
- inspect Inspect current builder instance
- ls List builder instances
- rm Remove a builder instance
- stop Stop builder instance
- use Set the current builder instance
- version Show buildx version information
- Run 'docker buildx COMMAND --help' for more information on a command.
我们可以查看一下当前 builder 的状态
- $ docker buildx ls
- NAME/NODE DRIVER/ENDPOINT STATUS PLATFORMS
- default * docker
- default default running Linux/amd64, Linux/arm64, Linux/ARM/v7, Linux/ARM/v6
创建一个 mybuilder 实例, 设置为默认构建器并激活 ARM 构建能力
- $ docker buildx create --name mybuilder
- mybuilder
- $ docker buildx use mybuilder
- $ docker buildx inspect --Bootstrap
- [+] Building 20.2s (1/1) FINISHED
- => [internal] booting buildkit 20.2s
- => => pulling image moby/buildkit:master 19.6s
- => => creating container buildx_buildkit_mybuilder0 0.6s
- Name: mybuilder
- Driver: docker-container
- Nodes:
- Name: mybuilder0
- Endpoint: unix:///var/run/docker.sock
- Status: running
- Platforms: Linux/amd64, Linux/arm64, Linux/ARM/v7, Linux/ARM/v6
从 GitHub 获取测试应用
- $ Git clone https://github.com/adamparco/helloworld
- $ cd helloworld
在 Docker Hub 创建一个测试 Repository
自从 Docker registry v2.3 和 Docker 1.10 开始, Docker 通过支持新的 image Media 类型 manifest list 实现了 Multi-architecture Docker 镜像功能, 支持在一个镜像中同时包含多种 CPU 体系架构的镜像层.
为测试应用构建多 CPU 体系架构镜像, 包含 x86, ARM 64 和 ARM v7 支持, 并推送到 Docker Hub
- $ docker buildx build --platform Linux/amd64,Linux/arm64,Linux/ARM/v7 -t denverdino/multiarch --push .
- .
- [+] Building 26.1s (31/31) FINISHED
- ...
- => [Linux/arm64 internal] load metadata for docker.io/library/python:3.7-alpine 2.9s
- => [Linux/ARM/v7 internal] load metadata for docker.io/library/python:3.7-alpine 3.2s
- => [Linux/amd64 internal] load metadata for docker.io/library/python:3.7-alpine 2.9s
- ...
- => exporting to image 22.8s
- => => exporting layers 1.0s
- => => exporting manifest sha256:f8739d2eb9f1b043e5d44e962c79d353261a257ffa6c8332b762b5d811d54c1a 0.0s
- => => exporting config sha256:528fc30a95957bf3c6c1bb4ea77793a2a484c0c5b87f3efad6bbc9dbc2df6a90 0.0s
- => => exporting manifest sha256:b52df7ab39acbe3ebb8b5d9e6a8069b9c916f1811b81aa84dd3b9dd9b4304536 0.0s
- => => exporting config sha256:9712542f20d1dd16c7332f664432a1b37c6254fefe7d4cb7806b74997467da07 0.0s
- => => exporting manifest sha256:698969718e9a316003a7fb4c2fe26216c95672e3e92372d25b01a6db5295e9e7 0.0s
- => => exporting config sha256:f636eaa8cec74fa574f99318cddd01b37a9e7c21708f94e11ae6575b34ca18f7 0.0s
- => => exporting manifest list sha256:3da22eea857f889ade3c85a2d41ed17db727385f78096e3dcf74ae039f164281 0.0s
- => => pushing layers 18.3s
- => => pushing manifest for docker.io/denverdino/multiarch:latest
我们可以在 Docker Hub 查看镜像信息
image.PNG
在 Mac 上面执行构建出来的镜像,
- $ docker run -p5000:5000 denverdino/multiarch
- * Serving Flask App "hello" (lazy loading)
- * Environment: production
- WARNING: Do not use the development server in a production environment.
- Use a production WSGI server instead.
- * Debug mode: off
- * Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)
访问 http://0.0.0.0:5000/ 可以看到当前 CPU 架构为 x86_64
image.PNG
登录到树莓派 (Raspbian 基于 ARMv7), 执行如下命令, 运行同样的容器镜像
- pi@raspberrypi:~ $ docker run -p5000:5000 denverdino/multiarch
- * Serving Flask App "hello" (lazy loading)
- * Environment: production
- WARNING: Do not use the development server in a production environment.
- Use a production WSGI server instead.
- * Debug mode: off
- * Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)
打开浏览器访问 raspberrypi:5000 , 可以看到当前 CPU 架构为 armv7l
image.PNG
X86 环境执行 ARM 架构 Docker 镜像
我们首先构建一个 ARMv7 版本的镜像
- docker buildx build --platform Linux/ARM/v7 -t denverdino/multiarch:armv7 --push .
- [+] Building 67.9s (13/13) FINISHED
- ...
- => => pushing layers 8.5s
- => => pushing manifest for docker.io/denverdino/multiarch:armv7
Linux 内核中 binfmt_misc 允许注册一个 "解释器", 在运行可执行文件的时候调用自定义解释器. Linux 4.8 版本在 binfmt_misc 中增加了 F flag 使内核可以在配置时加载解释器而非在运行时 Lazy load, 通过这个方法我们可以利用一个容器来注册和运行 ARM 指令集的解释器.
$ docker run --rm --privileged npmccallum/qemu-register
在 Mac 上运行如下命令, 无需任何修改就可以启动一个 ARM 镜像
- $ docker run -p5000:5000 denverdino/multiarch:armv7
- * Serving Flask App "hello" (lazy loading)
- * Environment: production
- WARNING: Do not use the development server in a production environment.
- Use a production WSGI server instead.
- * Debug mode: off
- * Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)
访问 http://0.0.0.0:5000/ , 可以看到当前 CPU 架构变成为 armv7l. 意外不意外? 惊不惊喜?:-)
image.PNG
总结
利用容器, 操作系统和虚拟化技术, 我们可以轻松在 X86 平台构建和测试 ARM 应用, 简化了多 CPU 体系架构应用的支持.
参考
- https://engineering.docker.com/2019/04/multi-arch-images/
- http://collabnix.com/building-arm-based-docker-images-on-docker-desktop-made-possible-using-buildx/
来源: http://www.jianshu.com/p/64f0da7a044d