By Yili
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.
Add the 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)
Visit http://0.0.0.0:5000/
to confirm that the current CPU architecture is x86_64
.
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)
Visit 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.
Collaborative Cloud-Native Application Distribution across Tens of Thousands of Nodes in Minutes
First Knative Attempt: A Quick Guide to Continuous Integration and Continuous Delivery
166 posts | 30 followers
FollowAlibaba Developer - November 8, 2021
Alibaba Clouder - October 17, 2018
OpenAnolis - December 12, 2023
Alibaba Container Service - August 17, 2021
Alibaba Developer - July 9, 2021
JDP - December 17, 2021
166 posts | 30 followers
FollowProvides a control plane to allow users to manage Kubernetes clusters that run based on different infrastructure resources
Learn MoreAlibaba 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 MoreA secure image hosting platform providing containerized image lifecycle management
Learn MoreAn agile and secure serverless container instance service.
Learn MoreMore Posts by Alibaba Container Service