目次


Docker コンテナーを使用して迅速にモノのインターネット・アプリケーションを開発する

IoT アプリケーションの開発、テスト、デプロイ、更新に、コンテナー・ベースの仮想化を使用する

Comments

環境センサー、医療記録を追跡するための機器、家電、産業機器などのスマート機器が高度に接続されたネットワーク、すなわち「モノのインターネット」が急速な成長を続けています。モノのインターネットで互いに結び付けられる機器の数は、2020年までに 200 億台に達するとも予測されています。これは、PC、スマートフォン、タブレットをすべて合計した台数の 2 倍にも及びます。開発者は、いち早く IoT 向けのアプリケーションを作成するようになってきており、コンテナーを使用すると、さまざまな点でこうした開発者の役に立つ可能性があります。

コンテナーは、仮想化を実現するための軽量の手法であり、開発者はコンテナーを広範に適用することで、IoT アプリケーションの開発、テスト、デプロイ、更新を迅速に行えるようになります。Web アプリケーションおよびモバイル・アプリケーションの開発者の多くは、VirtualBox などのハイパーバイザーを利用して仮想マシン (VM) を実行することで、クロス・プラットフォーム開発から、テスティング、デプロイメントへと至るワークフローの一環として、物理ハードウェアを仮想化しています。

コンテナー・ベースの仮想化 (オペレーティング・システム・レベルの仮想化とも呼ばれます) は、非常に軽量です。各コンテナーは共有ホスト・オペレーティング・システム・カーネルをベースに、それぞれに分離したユーザー空間インスタンスとして稼働します。オペレーティング・システムは共有されるものの、個々のコンテナーはそれぞれに独立した仮想ネットワーク・インターフェースとプロセス空間、そして別個のファイル・システムを使用します。リソースの分離を実装する制御グループを使用すれば、これらのコンテナーに RAM などのシステム・リソースを割り当てることができます。ハイパーバイザー・ベースの仮想化では、各 VM がそれぞれ独自にオペレーティング・システムを実行しますが、それではシステム・リソースの使用量が増えるだけです。それに比べると、コンテナー・ベースの仮想化でコンテナーが使用するディスク・リソースとメモリー・リソースはほんのわずかです。

Docker は、Linux でのコンテナー・ベースの仮想化に使用できるオープン・プラットフォームです。Docker を使用することで、コンテナーを迅速かつ容易に作成することができます。しかも、作成したコンテナーは、プライベート・クラウドやパブリック・クラウドにでも、ローカル VM 内にでも、IoT 機器を組み込んだ物理ハードウェアにでも、場所を問わずにデプロイすることができます。IBM Cloud プラットフォーム上でコンテナー化したアプリケーションのデリバリーおよびデプロイメントを行うには、Docker と Kubernetes をベースとした IBM Containers という IBM Cloud のフィーチャーを利用できます。

IoT 開発用 Docker をセットアップする

IoT アプリケーションがターゲットとするデバイス・プラットフォームは多種多様です。そのため多くの場合、プロトタイプ化の際や開発の初期段階では、IoT プロジェクトの開発に、汎用のマイクロコントローラー・ベースの開発ボードや、Raspberry Pi などのシングルボード・コンピューター (SBC) が使用されます。

Docker for Raspberry Pi で IoT 開発用 Docker をセットアップするには、Wi-Fi 対応の Raspberry Pi (Raspberry Pi Zero W、Raspberry Pi 3 など) に、raspbian Jesse で作成されたイメージを書き込んだ microSD カードを搭載して、SSH を有効にする必要があります(Raspberry Pi のセットアップ方法については、この実践的な IoT 動画を見てください)。SSH を有効にするには、イメージを書き込んだ microSD カード上のブート・パーティションに「ssh」という名前のファイルを作成します。Mac または PC からヘッドレス・モードの Raspberry Pi に SSH でアクセスするには、以下のコマンドを使用します (デフォルトのパスワードは raspberry です)。

ssh pi@raspberrypi.local

Docker をインストールするには、raspbian コマンド・ラインから以下のスクリプトを実行します。

$ curl -sSL get.docker.com |sh

アクセス権限の問題を避けるために、docker グループにデフォルト・ユーザー (pi) を追加してから、ユーザーを pi に切り替えて (su) 変更を適用するか、Raspberry Pi をリブートすることをお勧めします。

$ sudo usermod -aG docker pi
$ su pi

Docker が Raspberry Pi にインストールされたら、docker ps コマンドを実行することで、Docker が実行中であることを確認できます。

$ docker ps

CONTAINER ID  IMAGE  COMMAND  CREATED  STATUS  PORTS  NAMES

コンテナー、イメージ、レジストリーの操作

各 Docker コンテナー内では、1 つ以上のプロセスが実行されます。Docker コンテナーは、以下の要素を指定するイメージから起動されます。

  • コンテナー内で実行されるアプリケーションの構成情報
  • ライブラリーや共有バイナリー・ファイルなどの依存関係

Docker は、ユニオン・ファイル・システムを利用して、イメージを一連のレイヤーとして保管します。レイヤーはビルド・プロセスでキャッシュに入れられるため、派生イメージを迅速かつ効率的にビルドすることができます。

このレイヤー式アプローチは、Docker イメージのサイズが小さく、移植可能であることも意味します。したがって、イメージをパブリック・レジストリーまたはプライベート・レジストリーに公開して共有するのも簡単です。Docker イメージ・リポジトリーの最大のレジストリーとしては、Docker Hub が挙げられます。ここに記載されているリポジトリーの数は 100,000 を超え、数えきれないほどのプライベート・リポジトリーがホストされています。IBM Cloud プラットフォームを使用しているとしたら、そこから Docker Hub のパブリック・イメージをプルできるだけでなく、プライベート・イメージ・リポジトリーをホストして、組織内でプライベート・イメージを共有することもできます。

よく使われているオープンソースのフレームワークやサービスを使用している場合、Docker Hub を調べれば、あらかじめビルドされたイメージがおそらく見つかるはずです。これらのイメージの多くは、該当するプロジェクトに関連付けられたオープンソース・コミュニティーによって保守されています。Docker Hub Web インターフェースには、少数の公式リポジトリーのリストがあり、既知のセキュリティー上の脆弱性を Docker チームがテスト済みのイメージを格納したリポジトリーを精選したリストになっています。

信頼できるソースからのものであっても、古い Docker イメージは使用しないようにしてください。古いイメージの多くは、アーカイブとテストだけを目的として提供されています。古いイメージがまだ保守対象となっている場合には、Docker Hub でサポートされているというタグが付いています。パブリック・レジストリーに含まれるイメージの大半は、コミュニティーからコントリビュートされたものであり、ドキュメントが十分でなかったり、保守が十分に行われていなかったりする可能性があります。判断がつかない場合は、公式イメージのいずれかをベースとして使用して、独自のイメージを作成してください。

以下のステップに従うことで、イメージを作成することができます。

  1. レジストリーからベース・イメージをプルします。
  2. 一連のコマンドを対話形式で実行します。
  3. その結果を新しいイメージとしてコミットします。

例えば、Docker がインストールされた Raspberry Pi 上で以下にリストするコマンドを実行すると、Docker Hub から最新の ARM ベースの Alpine Linux イメージがプルされ、そのイメージからコンテナーが起動されます。これによって、Git をコンテナーにインストールするコマンドが実行されて、作成されたコンテナーの ID がリストされます。

リスト 1. イメージを作成する
$ docker pull armhf/alpine:latest
$ docker run -t -i armhf/alpine apk add --no-cache git
$ docker ps –l

このコンテナー (cb23e345fde0) を新しいイメージとして (demo/git という名前で) 保存するには、次のコマンドを実行します。$ docker commit cb23e345fde0 demo/git

PC または Mac 上で Docker を実行している場合、IBM Container Extensions ツールを使用して Docker コマンドをローカルで実行するには、docker コマンドを ice --local に変更してください。例えば、Ubuntu 16.04 をプルするには次のコマンドを使用します。

$ ice --local pull ubuntu:16.04

アプリケーション環境を構築するために 2 つ以上のコマンドを実行する必要がある場合は、Dockerfile を作成することをお勧めします。Dockerfile とは、イメージを作成するための一連の命令を指定したテキスト・ファイルです。以下のコード・リストに記載する Dockerfile は、Nginx Web サーバーを実行するためのベース・イメージを作成します。

リスト 2. Nginx Web サーバーを実行するためのベース・イメージを作成する Dockerfile
FROM armhf/alpine:latest
RUN apk update && apk add nginx
RUN mkdir -p /var/www/html
RUN chown -R nginx:www-data /var/lib/nginx 
EXPOSE 80 443
WORKDIR /etc/nginx
CMD ["nginx"]

各 Dockerfile ファイルの最初の命令は、ベース・イメージを指定する FROM 命令です。Dockerfile に指定された以降の命令は、それぞれ 1 つのレイヤーとして保管されます。

  • RUN 命令は、apt-get コマンドなどの Linux コマンドを実行します。
  • ADD および COPY 命令は、アプリケーション・ファイルをコンテナーに追加します。
  • EXPOSE 命令は、ポートを開きます。
  • ENV 命令は、環境変数を構成します。

最後に、各 Dockerfile に含まれる WORKDIRENTRYPOINT、または CMD 命令が、コンテナーの起動時にアプリケーションを実行する場所と方法を指定します。

Docker コンテナーの実行に伴うオーバーヘッドはほんのわずかなので、アプリケーションを一連のサービスに分割し、それぞれのサービスを個別のコンテナーで実行することができます。それぞれのコンテナーは、サービスを実行するときに、名前でサービスと関連付けることができます。例えば、アプリケーションを、Node.js アプリケーションを実行するコンテナーと、そのコンテナーに関連付けられた、Redis キー・バリュー型ストアを実行する別のコンテナーに分割するといった具合です。

コンテナーを使用して一貫性のある IoT 開発環境を維持する

IoT デバイスを対象に開発された組み込みアプリケーションは、後からカスタム・プロトタイプ開発ボードで実行するためにアップグレードできます。そして最終的には、本番の機器上で実行できるようにアップグレードします。マイクロコントローラーやシステム・オン・チップ (SoC) デバイスには広範な種類があり、場合によってはデバイス・ドライバー要件が適合しないこともあるため、最初は Raspberry Pi などの市販のハードウェアを使用し、後日、使用できる可能性のあるマイクロコントローラーまたは SoC デバイスを評価するという方法も考えられます (利用できるさまざまな IoT ハードウェアについては、私が developerWorks 記事として書いた、このリンク先の IoT ハードウェア・ガイドを参照してください)。それぞれのデバイス、あるいはデバイスのリビジョンによっても、そのデバイスを対象としたフラッシュ、モニタリング、通信に使用する開発ツールキットのバージョンおよび構成の要件は異なります。

コンテナーを使用すれば、各デバイスのリビジョンに有効であることがわかっている開発環境を取り込んで、その環境を開発チームで共有することができます。例えば、チームが複数のタイプの Arduino 対応開発ボードを扱っているとしたら、ベースラインの開発イメージとして、Arduino コマンド・ライン・ツールキットとシリアル通信用のダム端末エミュレーション・プログラムを含めたイメージを作成します。その Arduino 開発用ベース・イメージを使用すれば、特定のカスタム・ドライバが必要な各開発ボードに応じて新しいイメージのバリエーションを作成することができます。

Docker のレイヤー構造のファイル・システムであれば、こうした状況で効率的に空間を使用することができます。それは、新しいイメージが作成されたときに、固有のレイヤーだけが保管されるためです。docker history コマンドを実行すると、以下のようにイメージを構成するさまざまなレイヤーのリストが表示されます。このリストには、各レイヤーを作成した命令と、レイヤーのサイズも含まれます。

IMAGE           CREATED         CREATED BY              
7483ffb80dd6    5 minutes ago   apk add --no-cache git

レイヤーはキャッシュに入れられるため、イメージのバリエーションをすぐに試すことができるというわけです。例えば、ドライバーや開発ツールに更新を適用しなければならないことがありますが、更新後に問題が発生したとしても、レイヤーはキャッシュに入れられているため、前のバージョンのイメージに簡単にロールバックして別の方法を試すことができます。

開発環境に対して行った変更が成功したら、新しいイメージをプライベート・チームのレジストリーにプッシュすることで、その変更をチームの残りのメンバーに迅速に伝えることができます。更新されたイメージを各チーム・メンバーがプルするときには、レイヤーのほとんどがキャッシュに入れられていることになっています。そのため、新しいイメージが稼働中になるまでにかかる時間は、通常、わずか数秒から数分です。この間に、Docker が命令をひと通り実行して新しいレイヤーを作成します。VM イメージのスナップショットをプッシュまたはプルしたり、イメージのバリエーションごとにゼロからイメージ全体を作成したりする場合と比べ、レイヤーはストレージ・スペースを節約するだけでなく、さらに重要なこととして開発者の時間も節約するのです。

コンテナーを IoT 機器にデプロイする

Docker で作成したアプリケーションの魅力は、イメージをビルドした後、ほぼどこにでもリリースして実行できることです。IoT 機器が Linux を実行していれば、その機器に直接コンテナーをデプロイできる場合もあります。このような IoT 機器では一般にシステム・リソースが限られているものですが、Docker コンテナーのランタイム・オーバーヘッドはほとんどゼロに近いため、コンテナーをデプロイするのは不可能なことではありません。さらに、例えばアプリケーションの異なるバージョンを比較するために並べて実行したいとしたら、IoT 機器上で複数のコンテナーを実行することもできます。

Docker には、カーネルの名前空間と制御グループをサポートする最近の Linux カーネルが必要であるため、使用したいと思う IoT 機器にふさわしいベース・イメージがまだ利用できない場合もあります。しかし IoT 機器に適した SoC の小売価格は下がり続けているので (例えば、C.H.I.P. 開発ボードは 9 ドルです)、さらに多くの Linux 対応の IoT 機器が開発されることが見込まれます。そうなれば、これらのプラットフォームをターゲットとした Linux ディストリビューションの選択肢の幅も広がっていくことでしょう。

Docker Hub には、ARM アーキテクチャーをベースとした SBC (Single Board Computer) 愛好家に人気のある Raspberry Pi、Orange Pi、BeagleBone Black などに対応する ARM ベース・イメージがいくつもあります。DockerHub にある arm32v7 イメージ、arm32v6 イメージ、および非推奨となった armhf イメージは、DockerHub のマルチアーキテクチャー・サポートの一環として ARM アーキテクチャー用にビルドされた公式イメージです。DockerHub 上の resin 組織も、resin.io および resinOS で使用するように意図されたサード・パーティー・ベースのイメージを提供しています。

IoT 開発者は、機器が接続されたネットワークを常に最新の状態に維持するとともに、低帯域幅で信頼性も低い可能性があるワイヤレス接続で実行するという課題に直面します。さらに、IoT 機器の多くが収集する、機密性の高い極めて個人的なデータのセキュリティーを維持する方法も考えなければなりません。Docker コンテナーが IoT セキュリティーに役立つ理由は、ユーザー名前空間を使用した隔離 (Docker 1.10 で導入) をサポートすること、そして Docker シークレット (Docker 1.13 から有効) を使用して、デバイス間やデバイスとアップストリームのクラウド・サービス間で認証とセキュア通信に使用するキーまたはアクセス・トークンを保管および暗号化できることにあります。

このような更新の問題に対して Docker が提供しているソリューションは、最新バージョンのアプリケーション・イメージに対し、プル・リクエストを発行する機器が、完全なイメージではなく、イメージの差分だけを送信するというものです。差分ベースの更新であれば、更新が完了するまでの時間が大幅に短くなります。つまり、機器が接続状態を維持しなければならない時間が短くなるため、障害が発生する可能性も低くなります。したがって、低帯域幅ネットワークに対する要求も低減されます。その結果、更新をより頻繁に適用することが可能になります。

IoT 機器の中には、物理的なボタンや小さいタッチ画面で限られたユーザー操作しかできないものもありますが、現世代の多くの IoT 機器でのユーザー操作の主な手段は、モバイル・アプリケーションを使用します。自動化されたテスティング、継続的インテグレーション、そしてモバイル・アプリケーションのデリバリーを迅速化するために、Docker コンテナーが使用されるケースが増えているのは当然のことでしょう。

IoT 機器をクラウドに統合する

アプリケーションをスマート機器やモバイル端末にデプロイすることは、モノのインターネットの開発シナリオの一部でしかありません。IoT デバイスおよびゲートウェイで実行されるコンテナー内でエッジ・アナリティクスを実行する場合もありますが、現世代の IoT デバイスの多くは、センサー・データとイベントをさらに処理するためにクラウド・サービスへのパブリッシュも行います。

クラウド・サービスにコンテナーが採用されることは珍しくありません。コンテナーは一時的にしか存続しません。したがって、実行中のデータベース・コンテナーに含まれるファイル・システムに書き込まれたデータは、一時データと見なされます。つまり、コンテナーがシャットダウンされると、データが失われるということです。コンテナーを使用する場合、ステートレスなクラウド・アプリケーションを開発する良い習慣を身に付けざるを得なくなるという一面もあります。永続化させるデータは、データ・ボリュームを使用して保管しなければなりません。データ・ボリュームはコンテナーのシャットダウン後も永続化されるため、複数のコンテナーで共有することができます。

接続された機器の数が増加するのに伴い、IoT を対象としたクラウド・ベースのアプリケーションは、生成されるデータの量に対処するよう拡大しなければならなくなります。幸い、Docker を中心に作成されるオーケストレーション・ツールのエコシステムは成長しており、Docker Machine、Swarm、Compose といったツールを利用して、スケーラブルなクラウド・アプリケーションを開発することができます。これらのツールは、EC2 Container Services、Microsoft Azure、IBM Cloud などの数々のクラウド・プラットフォームで利用できます。IBM Cloud でも現在、ロード・バランシングおよびフェイルオーバーのために一連のコンテナーを実行できるようになっています。

まとめ

モノのインターネットのアプリケーションに見込まれる需要を満たすために開発者に必要となるのは、スマート機器上、またはモバイル端末上、あるいはクラウド内で実行される IoT アプリケーションおよびサービスを迅速に開発するためのツールとプラクティスを導入することです。アプリケーションをどこにでもリリースして幅広い種類のデバイス上で実行できること、ランタイムのオーバーヘッドが最小限であること、自動化がサポートされること、レイヤー構造のファイル・システムによって軽量の移植可能なイメージを迅速にビルドできることから、Docker コンテナーは IoT 開発者にとって欠かせないツールとなります。


ダウンロード可能なリソース


関連トピック


コメント

コメントを登録するにはサインインあるいは登録してください。

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=60
Zone=Internet of Things, Cloud computing, Mobile development
ArticleID=1014619
ArticleTitle=Docker コンテナーを使用して迅速にモノのインターネット・アプリケーションを開発する
publish-date=02062018