Ebook連載:『5分x10回で学ぶ 開発者のためのDocker コンテナ入門』第8章 –ユーザ定義ネットワーク上のマルチコンテナアプリケーション #docker #DX #Mirantis
この記事は1年以上前に投稿されました。情報が古い可能性がありますので、ご注意ください。
コンテナ化はDXの第一歩に最適な取り組みです。本シリーズでは10回にわたってMirantis社が発行するEbook「Learn Containers 5 Minutes at a Time An introductory guide for developers」 (Eric Gregory著)を翻訳・編集し、チャプターごとにCL LABで公開しています。本稿はその第8章です。皆さまのクラウドネイティブジャーニーやアプリケーションのモダナイズの一助になれば幸いです。
- 第1章 コンテナとは?
- 第2章 コンテナの作成・調査・削除
- 第3章 Dockerfile でのコンテナイメージのビルド
- 第4章 イメージレジストリ
- 第5章 ボリュームと永続的なストレージ
- 第6章 コンテナネットワークとコンテナのポートの開設
- 第7章 コンテナ化アプリの実行
- 第8章 ユーザ定義ネットワーク上のマルチコンテナアプリケーション
- 第9章 Docker Compose
- 第10章 Webアプリをコンテナサービスとして構築する
第8章: ユーザ定義ネットワーク上のマルチコンテナアプリケーション
前章では、オープンソースの Wiki プラットフォームである Mediawiki の Web アプリを単一のコンテナ構成で実行し、永続ボリュームとコンテナのポートをホストマシンに公開しました。その結果、Wiki の環境が整い、情報の書き換え・追加・削除ができるようになりました。
しかし多くの場合、クラウドネイティブのデプロイメントは、複数のコンテナに分散したアプリケーションで構成されています。しかし、コンテナ化された単一アプリケーションの構成部分をどのように接続すればよいのでしょうか?この章では、ユーザ定義のネットワーク上にマルチコンテナ構成で Mediawiki をデプロイし、コンテナ同士が通信できるようにする方法を学びます。
コンテナがデフォルトの bridge ネットワークに存在する場合、理論的には DNS(Domain Name System)を介して互いのコンテナ名で通信できるはずですが、そうではありません。コンテナ化されたアプリケーションは、データをやり取りするために、互いの特定のIPアドレスを知る必要があります。
これは、デフォルトの bridge ネットワークに意図的に制限が加えられていることを示しています。なぜそのようなことをするのでしょうか?標準の設定で使用されるdocker0 bridgeは、互いに関連性がなく通信する必要のない Docker コンテナが集まり通信が混雑しがちです。これは分離を前提としたシステムにおいて、セキュリティリスクとなり得ます。そのためデフォルトの bridge では、Docker はコンテナが安全に通信するために、DNS を無効にしています。
DNS が必要なコンテナのグループがある場合、デフォルトの bridge を使用する代わりに、独自のユーザ定義ネットワークに配置することができます。これはコンテナが通信するための唯一の方法ではありませんが、Docker が推奨する方法です。なぜなら、これは正確な範囲で分離したレイヤーを作成するからです。次のコマンドでユーザ定義のネットワークを作成することができます。
% docker network create
このコマンドに -d または --driver の引数を加えると、新しいネットワークのモデルとして、Bridge /Overlay /ユーザによって追加されたカスタムドライバのオプションを指定できます。
- Bridge ネットワークは同じ Docker デーモンのホスト上にあるネットワーク内のコンテナを、他のネットワークから分離しながら、互いに通信できるようにします。
- Overlay ネットワークは、複数の Docker デーモンのホストに分散しているネットワーク内のコンテナを、他のネットワークから分離しつつ相互に通信可能にするドライバです。このドライバは、コンテナオーケストレータである Docker Swarm で使用されています。
- カスタムドライバを使用することで、独自のネットワークルールを設定することができます。
デフォルトのドライバはbridge ドライバなので、ドライバを指定しなければ、Docker は bridge ネットワークを作成します。この章では、bridge ドライバを使用します。
コンテナリンクについて
デフォルトの bridge ドライバで名前によるコンテナ間の通信を行うもう1つの方法は、コンテナリンクです。--link の 引数を使用してコンテナ間のリンクを手動で作成します。 これはかつてのコンテナ接続の標準的な手法であり、今でもイメージのドキュメントに使われているのを多く目にすることができます。しかし、Docker はこれをレガシーオプションとみなしています。つまり、Dockerはこれを推奨しておらず将来的に無効になる可能性があります。リンクはユーザ定義ネットワークに取って代わりました。 |
最初に、新しくユーザ定義ネットワークを作成しましょう。bridge ドライバを明示的に指定し、新しいネットワークに wiki-net という名前を付けて、一目でその役割が分かるようにします。
% docker network create -d bridge wiki-net
新しい Mediawiki の実装は2つのコンテナに分割しましょう。
- アプリケーションのコンテナ
- MySQL のデータベースのコンテナ
前章で、SQLite データベースを使用した Mediawiki の単一のコンテナ構成は、実際の本番環境よりもむしろ開発環境に最も適していると説明しました。しかし、それはなぜでしょうか?なぜ、わざわざマルチコンテナ構成にするのでしょうか?その答えを出すには、データベースのオプションの長所と短所を考えてみる必要があります。
- SQLite は軽量でポータブル、そしてアプリの中に簡単に組み込めるように設計されています。主にローカルデータ保存のためのツールです。詳しくは次のURLを確認してください。
https://www.sqlite.org/index.html - MySQL は、データベースを提供するために独自のコンテナが必要で、フットプリントが比較的大きく、アプリに直接埋め込むのではなく、多くの同時リクエストを処理できるように設計されています。詳しくは次のURLを確認してください。
https://www.mysql.com/
SQLiteは簡単にセットアップすることができ、シンプルでかつ迅速に実行できるので、開発環境には最適です。しかし、多くのユーザからの同時的な問い合わせが持続的に増え続けるような、大規模でスケーラブルなデータセットには向いていません。このユースケースを実現するにはMySQLの方が適しています。
このように SQLite と MySQL のどちらのデータベースが「優れている」「劣っている」ということはなく、目的が違うので比較対象にすらなりません。これらの異なる目的が、そのまま私たちが採用するコンテナの構成につながっています。 これは単純に思われ忘れがちですが、クラウドネイティブ開発において重要なことです。解決策は、問題やコンテクストによって決定されるべきです。
コンテナ化した MySQL データベースを作成しましょう。
docker run --name wiki-mysql --network=wiki-net -v wiki-data:/var/lib/mysql -d -e MYSQL_ROOT_PASSWORD=root mysql
かなり長い docker run コマンドなので、順を追って説明します。
- コンテナの名前を wiki-mysql にする
- --network の引数を使って、コンテナを新しい wiki-net ネットワークに割り当てる
- 前章の演習と同じく、wiki-data ボリュームをマウントしている。(もし前章で作成したボリュームを削除してる場合、再作成する必要がある。)永続的なデータを保存できるように、wiki-data ボリュームを MySQL コンテナのディレクトリに割り当てる。
- 6章で説明したように、デタッチドモードで実行する。
- -e の引数で環境変数を指定する。今回は、データベースの root ユーザのパスワードを指定する。本番環境では決して "root "のようなパスワードを使ってはいけないが、ここでは再現性のために使っていることに注意。
- MySQL公式 Docker Hub イメージを基盤に構築する。
デフォルトの bridgeで nginx コンテナを起動し、その IP アドレスを wiki-net 上の MySQL コンテナが使用する IP アドレスと比較すると、興味深いことが分かります。
% docker run --name nginx-test -d nginx 675eeead7df8d23fbb388826c58403223fd64cf21b9d44917 dfb38091d1b6e7f % docker inspect --format='{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' nginx-test 172.17.0.2 % docker inspect --format='{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' wiki-mysql 172.19.0.2
IP アドレスの 2組目に違いがあるのがわかります。wiki-net 上のコンテナは 172.19… の範囲にアドレスを持つことになります。
nginx-test コンテナが起動している場合は削除してください。余計なコンテナが起動していないことを docker container ls で確認し、 wiki-mysql コンテナだけが表示されている状態にしてください。
wiki アプリケーション本体を立ち上げてみましょう。
% docker run --name wiki-app --network=wiki-net -v wiki-data:/wiki-data -p 8000:80 -d mediawiki
データベースと同じネットワーク上でアプリケーションを実行します。アプリケーションが設定データに使用するボリュームをマウントしているため、localhost:8000 をブラウザから開くと、前回と同じセットアップ画面が表示されるはずです。
前章と同じように Connect to database 画面に進み、今度は "MariaDB, MySQL, or compatible" を選択します。
"Database host" のテキストボックスには、データベースコンテナの名前 wiki-mysql を入力するだけです。これらのコンテナが再起動された場合、将来のインスタンスが異なるIPアドレスを持つとしても、設定されたとおりに相互に稼働することができるようになります。
"Database name" には、任意の名前を指定します。"table prefix" には何も入力する必要はありません。データベースパスワードには、データベースコンテナを作成したときに環境変数で設定したパスワード、ユーザー名と同じ "root" を入力します。
次の画面で、"Continue" をクリックします。
管理者情報を最終確認し、インストール作業を行います。
前章のように、生成された LocalSettings.php ファイルをダウンロードして、wiki アプリのベースディレクトリに置く必要があります。ファイルをディレクトリに置く手順についての詳しい情報が必要な場合、前章の演習を見直してください。更新されたコンテナをイメージにコミットして、新しいコンテナを開始します。
% docker commit wiki-app wiki-app % docker container stop wiki-app % docker container rm wiki-app % docker run --name wiki-app --network=wiki-net -v wiki-data:/wiki-data -p 8000:80 -d wiki-app
これで、Docker のベストプラクティスに従って、本番環境で使用でき、ユーザ定義のネットワーク上で動作するデータベースを備えたマルチコンテナアプリケーションが完成しました。
このアプリケーションを繰り返しデプロイしたり、大規模にデプロイしたりする場合は、もう少し手動での設定を少なくした方が良さそうです。次の章では、マルチコンテナアプリケーションのデプロイを効率化する方法について学びます。
※Docker Enterprise事業は2019年11月14日にMirantis社によって買収されました。
当時のDocker Enterprise製品は、現在は下記のように名称変更されています。
- 「Docker Engine」→「Mirantis Container Runtime (MCR)」
- 「エンタープライズ版Docker」→「Mirantis Kubernetes Engine (MKE)」
- 「Docker Trusted Registry」→「Mirantis Secure Registry (MSR)」
Mirantis製品に関するお問い合わせはこちら。
Mirantisについて
Mirantisは、Fortune 1000 企業の 2/3 以上にコンテナやマルチクラウドの導入を加速させ、データセンター運用のストレスを取り除く支援をしています。日本では、クリエーションラインと提携し、Kubernetes、OpenStack、その他のオープンクラウドテクノロジーを、現地語でのサポートやサービスとともに提供しています。Mirantis Kubernetes Engine(旧Docker Enterprise)および関連製品を含む、深い技術的専門知識とベンダーにとらわれない柔軟なプラットフォームが、お客様から選ばれています。
詳細は www.mirantis.com でご確認ください。