ARM Container Applications: Accelerating Development and Testing

By Yili

Image for post
Image for post

With the era of 5G around the corner, highly reduced network latency, improved hardware computing capability of Artificial Intelligence (AI), and rapid growth of intelligent applications, the Internet of Everything is inevitable. Therefore, we must extend the intelligent decision-making capability and the real-time processing capability from the cloud to the edge and to the Internet of Things (IoT) devices.

Alibaba Cloud Container Service already provides edge containers to integrate the cloud, edge, and devices. However, there is a need to support Advanced RISC Machine (ARM) chips as well as x86 chips in IoT and edge computing scenarios. While the home-grown ARM CPUs are rapidly developing, ARM-based containers should also get ready.

This article introduces some simple techniques to speed up the development and testing processes of ARM container applications.

Build an ARM-based Docker Image in the x86 Environment

Recently, Docker and ARM announced their partnership program for optimizing Docker tools to improve developers’ experience on the ARM platform. Docker developers build container images for ARM devices on the x86 desktop and deploy container applications onto the cloud, edge, and IoT devices. The entire container building process is very simple without cross-compilation steps.

Docker Desktop is a container development environment for macOS and Windows platforms. Docker uses the virtualization technologies in the host’s operating system, such as Hyper-V on Windows or HyperKit on MacOS, to run the Docker development environment. To support ARM CPUs, the latest Docker version adds the QEMU simulator to the container-dedicated operating system, LinuxKit. Currently, applications based on the ARM/v6, ARM/v7, and ARM64 architectures are supported. The architectural diagram is as follows:

Image for post
Image for post

Now, let’s take a look at the steps to build an ARM-based Docker Image in the x86 environment.

First, install the latest edge version of Docker Desktop. Note that the Docker Engine version must be later than version 19.03.

Image for post
Image for post

Enable the experimental features in Docker Desktop by choosing Preference… > Command-Line > Enable experimental features.

Image for post
Image for post

Add the docker buildx command to Docker as shown below.

$ docker buildx --helpUsage:  docker buildx COMMANDBuild with BuildKitManagement 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.

The following snippet shows the current status of the 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

Create a mybuilder instance as the default builder, and activate the ARM building capability.

$ 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

Obtain the test application from GitHub using the commands below.

$ git clone https://github.com/adamparco/helloworld
$ cd helloworld

Next, create a test repository in Docker Hub.

Image for post
Image for post

With the support of the new image mediaType manifest list, Docker implements the multi-architecture Docker imaging feature since Docker registry v2.3 and Docker 1.10. This feature allows one image to contain imaging layers in various CPU architectures.

Build a multi-CPU architecture image for the test application, including the support for x86, ARM64, and ARMv7, and then push it to 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

The following snapshot of Docker Hub shows the image information.

Image for post
Image for post

Run the built image on a macOS machine as shown below.

$ 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)

Visit http://0.0.0.0:5000/ to confirm that the current CPU architecture is x86_64.

Image for post
Image for post

Log on to a Raspberry Pi, which runs on ARMv7-based Raspbian, and execute the following command to run the same container image.

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)

Open a browser and visit Raspberrypi:5000 to see that the current CPU architecture is ARMv7l.

Image for post
Image for post

Run an ARM-based Docker Image in the x86 Environment

Begin with building an ARMv7 image as shown below.

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

In the Linux kernel, register an “interpreter” using binfmt_misc. Call the custom interpreter when running an executable file. In Linux 4.8, the F flag is added to Binfmt_misc to allow the kernel to load the interpreter during configuration instead of during running. This feature is known as lazy load. This helps to register and run the interpreter for the ARM instruction set by using containers.

$ docker run --rm --privileged npmccallum/qemu-register

Run the following command on a macOS machine. An ARM image starts without making any modifications.

$ 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)

Visit http://0.0.0.0:5000 to confirm that the current CPU architecture is ARMv7l.

Image for post
Image for post

Summary

The article concludes that the integration of containers, operating systems, and virtualization technologies simplifies the support for multi-CPU architecture-based applications. Such integration allows to easily build and test ARM applications on the x86 platform.

References

Original Source:

Follow me to keep abreast with the latest technology news, industry insights, and developer trends.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store