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.
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:
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.
Enable the experimental features in Docker Desktop by choosing Preference... > Command-Line > Enable experimental features.
docker buildx command to Docker as shown below.
$ 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.
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.
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.
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)
http://0.0.0.0:5000/ to confirm that the current CPU architecture is
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.
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)
http://0.0.0.0:5000 to confirm that the current CPU architecture is ARMv7l.
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.
Alibaba Clouder - October 17, 2018
Alibaba Clouder - September 20, 2018
Alibaba Clouder - March 6, 2020
Alibaba Clouder - November 8, 2018
Alibaba Clouder - January 26, 2019
Alibaba Clouder - February 14, 2020
A secure image hosting platform providing containerized image lifecycle managementLearn More
A high-performance container manage service that provides containerized application lifecycle managementLearn More
Alibaba Cloud Container Service for Kubernetes is a fully managed cloud container management service that supports native Kubernetes and integrates with other Alibaba Cloud products.Learn More
Elastic Container Instance (ECI) is an agile and secure serverless container instance service. You can easily run containers without managing servers. Also you only pay for the resources that have been consumed by the containers. ECI helps you focus on your business applications instead of managing infrastructure.Learn More
More Posts by Alibaba Container Service