ARMコンテナアプリケーションの開発・テストプロセスを高速化する方法


この記事では、ARMコンテナアプリケーションの開発・テストプロセスを高速化するための簡単なテクニックを紹介しています。

5Gの時代が目前に迫り、ネットワークのレイテンシーが高度に削減され、人工知能(AI)のハードウェアコンピューティング能力が向上し、インテリジェントなアプリケーションが急速に成長する中、「Internet of Everything」の実現は避けられません。そのため、インテリジェントな意思決定能力とリアルタイム処理能力を、クラウドからエッジ、そしてIoT(Internet of Things)デバイスにまで拡張する必要があります。

Alibaba Cloud Container Serviceは、クラウド、エッジ、デバイスを統合するためのエッジコンテナをすでに提供しています。しかし、IoTやエッジコンピューティングのシナリオでは、x86チップだけでなく、ARM(Advanced RISC Machine)チップもサポートする必要があります。自作のARM CPUが急速に発展している中、ARMベースのコンテナも準備をしなければなりません。

この記事では、ARMコンテナアプリケーションの開発・テストプロセスを高速化するための簡単なテクニックを紹介します。

ARMベースのDockerイメージをx86環境で構築する

先日、Docker社とARM社は、Dockerツールを最適化してARMプラットフォームでの開発者の体験を向上させるためのパートナーシッププログラムを発表しました。Dockerの開発者は、x86デスクトップ上でARMデバイス用のコンテナイメージを構築し、コンテナアプリケーションをクラウド、エッジ、IoTデバイス上に展開します。コンテナ構築のプロセス全体は、クロスコンパイルの手順がなく非常にシンプルです。

Docker Desktopは、macOSおよびWindowsプラットフォーム向けのコンテナ開発環境です。Dockerは、WindowsのHyper-VやMacOSのHyperKitなど、ホストのOSに搭載されている仮想化技術を利用して、Dockerの開発環境を実行します。ARM CPUをサポートするために、最新のDockerバージョンでは、コンテナ専用OSであるLinuxKitにQEMUシミュレータを追加しています。現在、ARM/v6、ARM/v7、ARM64の各アーキテクチャをベースにしたアプリケーションに対応しています。アーキテクチャ図は以下の通りです。

それでは、x86環境でARMベースのDocker Imageを構築する手順をご紹介します。

まず、Docker Desktopの最新エッジバージョンをインストールします。なお、Docker Engineのバージョンは、バージョン19.03以降である必要があります。

[設定...]> [コマンドライン]> [実験機能を有効にする]を選択して、Dockerデスクトップで実験機能を有効にします。

以下のように、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.

次のスニペットは、ビルダーの現在の状態を示しています。

$ 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にテスト用のリポジトリを作成します。

新しいイメージmediaTypeマニフェストリストのサポートにより、DockerはDocker registry v2.3およびDocker 1.10からマルチアーキテクチャーのDockerイメージング機能を実装しています。この機能により、1つのイメージに様々なCPUアーキテクチャのイメージング層を含めることができます。

テストアプリケーション用に、x86、ARM64、ARMv7への対応を含むマルチCPUアーキテクチャイメージを構築し、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のスナップショットには、イメージ情報が表示されています。

ビルドしたイメージを、以下のようにmacOSマシンで実行します。

$ 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であることを確認してください。

ARMv7ベースのRaspbianで動作するRaspberry Piにログオンし、以下のコマンドを実行して同じコンテナイメージを実行します。

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であることがわかります。

ARMベースのDockerイメージをx86環境で実行する

以下のように、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_miscF flagが追加され,実行時ではなく設定時にカーネルがインタープリタをロードすることができるようになりました.この機能はレイジーロードと呼ばれています。これにより、コンテナを利用してARM命令セット用のインタープリタを登録・実行することができます。

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

macOSマシンで以下のコマンドを実行します。何も手を加えずに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であることを確認してください。

概要

本稿では、コンテナ、オペレーティングシステム、仮想化技術の統合により、マルチCPUアーキテクチャベースのアプリケーションのサポートが簡素化されると結論づけています。このような統合により、x86プラットフォーム上でARMアプリケーションを簡単に構築し、テストすることができます。

参考文献

本ブログは英語版からの翻訳です。オリジナルはこちらからご確認いただけます。一部機械翻訳を使用しております。翻訳の間違いがありましたら、ご指摘いただけると幸いです。

アリババクラウドは日本に2つのデータセンターを有し、世界で60を超えるアベラビリティーゾーンを有するアジア太平洋地域No.1(2019ガートナー)のクラウドインフラ事業者です。
アリババクラウドの詳細は、こちらからご覧ください。
アリババクラウドジャパン公式ページ