type
status
date
slug
summary
tags
category
icon
password
チャプター 6: マルチコンテナアプリケーションの展開
目標
- 複数のコンテナイメージを使用してコンテナ化されたアプリケーションを展開する。
目的
- 複数のコンテナイメージを使用してアプリケーションをコンテナ化する際の考慮事項を説明する。
- ユーザー定義の Docker ネットワークを使用して、マルチコンテナアプリケーションを展開する。
セクション
- マルチコンテナアプリケーションに関する考慮事項
- Dockerによるマルチコンテナアプリケーションの展開
実習
- マルチコンテナアプリケーションの展開
マルチコンテナアプリケーションの考慮事項
目的
このセクションを終えた後、学生は以下のことができるようになります:
- 複数のコンテナイメージを使用してアプリケーションをコンテナ化する際の考慮事項を説明できる。
- コンテナに環境変数を注入できる。
- 「To Do List」アプリケーションのアーキテクチャを説明できる。
マルチコンテナアプリケーションでのサービス発見
コンテナのIPアドレスは動的に割り当てられるため、アプリケーションが外部サービスや他のコンテナと通信する場合、固定IPアドレスやホスト名に依存することはできません。例えば、フロントエンドコンテナはバックエンドコンテナのIPアドレスを取得する必要があり、同様にバックエンドコンテナはデータベースコンテナのIPアドレスを取得する必要があります。しかし、コンテナが再起動されると、IPアドレスは変更される可能性があります。この問題を解決するためには、動的にIPアドレスを管理し、サービス間で適切に通信できる仕組みが必要です。
DockerやKubernetesは、この問題に対応するための解決策を提供しています。具体的な解決方法は後述します。
Dockerコンテナへの環境変数の注入
環境変数を使用することで、アプリケーションの外部サービスとの接続情報をパラメータ化できます。これを行う一般的な方法として、オペレーティングシステムの環境変数を使用することが挙げられます。
Dockerには、コンテナの環境変数を操作するためのオプションがいくつかあります:
docker run
コマンドでe
オプションを使い、コンテナ起動時に環境変数を設定することができます。これにより、データベースのIPアドレスや認証情報などのパラメータをコンテナに渡すことができます。
docker inspect
コマンドで、実行中のコンテナの環境変数を確認することができます。ただし、OSから引き継がれた環境変数や、コンテナ内で定義された環境変数は表示されません。
docker exec
コマンドを使用して、実行中のコンテナにシェルコマンドを実行し、環境変数を確認することも可能です。
さらに、Dockerfile内で
ENV
命令を使って環境変数を定義することができます。例えば:複数の環境変数を定義する場合は、次のように一行にまとめて書くことが推奨されます:
DockerとKubernetesの比較
環境変数を使うことで、Docker内でのコンテナ間の情報共有は可能ですが、特に多くのコンテナを扱う場合には、手動で環境変数の同期を確認する必要があります。Kubernetesは、この問題に対応するために、サービスの発見や環境変数の管理を自動化しています。
Kubernetesでは、ポッドが特定の名前空間に関連付けられ、同じ名前空間内のサービスに対して自動的に環境変数が注入されます。これにより、各サービスのIPアドレスやポート番号を動的に環境変数として管理することができます。
サービスごとに生成される環境変数の例:
<SERVICE_NAME>_SERVICE_HOST
: サービスが提供するポッドへのIPアドレス
<SERVICE_NAME>_SERVICE_PORT
: サービスが提供するポート番号
<SERVICE_NAME>_PORT
: 外部アクセス用のサービスのアドレス、ポート、プロトコル
では、具体的な例で説明します。
例えば、KubernetesでMySQLサービスとWebアプリケーションがあるとします。
1. MySQLサービス
MySQLサービスは、
mydb
という名前でKubernetes上に展開されています。このサービスには、IPアドレス(例:10.0.0.11
)とポート番号(例:3306
)があります。2. Webアプリケーション
Webアプリケーションは、MySQLと通信してデータを取得しますが、MySQLのIPアドレスやポート番号をどこかで知っておく必要があります。Kubernetesでは、これを環境変数として自動的に管理します。
生成される環境変数
Kubernetesは
mydb
サービスに関連する以下の環境変数をWebアプリケーションのポッドに注入します:MYDB_SERVICE_HOST=10.0.0.11
mydb
サービスのIPアドレスMYDB_SERVICE_PORT=3306
mydb
サービスのポート番号MYDB_PORT=tcp://10.0.0.11:3306
外部アクセス用のアドレスとポート(プロトコル含む)
実例
たとえば、MySQLというサービスがあります。このサービスは3つのポッド(
mysql-pod-1
, mysql-pod-2
, mysql-pod-3
)によって提供されます。それぞれのポッドは個別のIPアドレスを持ちますが、サービスとしては一つのIPアドレス(例えば、10.0.0.10
)とポート(例えば、3306
)の組み合わせが提供されます。このエンドポイントを介して、クライアント(例:Webアプリケーション)はMySQLにアクセスすることができます。サービスが提供するエンドポイントは、複数のポッドへのリクエストを負荷分散し、それぞれのポッドが一貫してアクセスされる仕組みになっています。このように、サービスは複数のポッドに対して一つのエンドポイントを提供し、リクエストのトラフィックを負荷分散する役割を果たします。
Webアプリケーションでの利用
Webアプリケーションのコード内で、これらの環境変数を使ってMySQLに接続することができます:
結論
このように、Kubernetesはサービスの情報(IPやポート)を自動的に環境変数として管理し、他のサービスがその情報を利用できるようにします。これにより、IPアドレスやポートが変わっても、環境変数を使って自動的に最新の情報を取得できます。
To Do List アプリケーションの確認
このTo Do Listアプリケーションは、3つの部分に分かれています。それぞれの役割を簡単に説明します。
- プレゼンテーション層(フロントエンド):
- 画面に表示される部分で、ユーザーが見て操作する部分です。
- AngularJSという技術を使って作られています。
- ビジネス層(バックエンド):
- データを処理したり、アプリの動作を決める部分です。
- Node.jsという技術で作られています。
- データ層(データベース):
- ユーザーの情報やTo Doリストの内容を保存する部分です。
- MySQLというデータベースを使っています。
このアプリケーションには、2つのバージョンがあります:
- nodejsバージョン:アプリケーション全体が1つの単位で作られていて、開発者がシンプルに作成したものです。
- nodejs_apiバージョン:アプリの画面部分と動作部分を別々にして、それぞれ異なるコンテナで動かせるようにしたものです。
このアプリケーションのソースコード(元のプログラムのデータ)は、指定されたウェブサイトで見ることができます。
要するに、これらの情報はアプリケーションがどのように作られていて、どうやって動かすのかを理解するための基本的な説明です。


Kubernetesでの名前空間の使い方を整理します。名前空間の分け方は、目的や環境に応じて選ぶことが重要です。主に次の2つのアプローチがあります。
1. 環境ごとに名前空間を分ける(本番、テスト、開発など)
この方法は、アプリケーションの異なる環境(開発、テスト、本番)を分けるために使います。これにより、各環境ごとにリソースを分離でき、環境間での干渉を防ぐことができます。
例:
dev
名前空間: 開発環境用のリソース。
test
名前空間: テスト環境用のリソース。
prod
名前空間: 本番環境用のリソース。
これにより、例えばテスト用のデータベースと本番用のデータベースをそれぞれ管理できるようになります。
利点:
- 環境ごとのリソースを明確に分けて管理できる。
- 開発中の環境に影響を与えることなく、本番環境を安定的に運用できる。
2. アプリケーションの層ごとに名前空間を分ける(プレゼンテーション層、ビジネス層、データ層)
この方法は、アプリケーションの異なる層(プレゼンテーション層、ビジネス層、データ層)を名前空間で分けて、それぞれを独立して管理するアプローチです。
例:
presentation
名前空間: プレゼンテーション層(フロントエンド)に関連するリソース(例: AngularJSのアプリケーション)。
business
名前空間: ビジネス層(バックエンド)に関連するリソース(例: Node.jsのAPI)。
database
名前空間: データベースに関連するリソース(例: MySQL、PostgreSQL)。
利点:
- 各層を独立して管理できる。
- 各層間でリソースの制限やアクセス制御を設定しやすい。
- それぞれの層が異なる名前空間に配置されているので、セキュリティやパフォーマンスの設定がしやすい。
どちらを選ぶべきか?
- 環境ごとに分ける場合: 異なる環境(開発、テスト、本番)を完全に分離したい場合に適しています。例えば、開発と本番で異なる設定やリソース(データベースの設定、CPU制限など)がある場合に有効です。
- 層ごとに分ける場合: アプリケーションの層ごとにリソースやアクセス権限を分離して管理したい場合に適しています。プレゼンテーション層、ビジネス層、データ層を独立して管理することで、各層を個別にスケールしたり、異なるポリシーを適用したりできます。
結論
最も適切な方法は、環境ごとに名前空間を分けるとアプリケーション層ごとに名前空間を分けるの両方を組み合わせることです。例えば、以下のように名前空間を構成できます。
dev-presentation
,dev-business
,dev-database
(開発環境の層ごとの名前空間)
prod-presentation
,prod-business
,prod-database
(本番環境の層ごとの名前空間)
このように、環境ごとに分けつつ、層ごとにリソースを整理することで、柔軟な運用が可能になります。
名前空間には複数のサービスを配置することができます。そして、各サービスには、通常複数のポッド(POD)が関連付けられます。
詳しく説明します:
1. 名前空間(Namespace)
Kubernetesでは、名前空間はリソース(ポッドやサービス、ConfigMapなど)をグループ化するための仕組みです。名前空間を使うことで、リソースを管理しやすく、異なる環境(開発、テスト、本番)を分けることもできます。
2. サービス(Service)
サービスは、特定のポッド群に対する抽象化されたアクセス方法を提供します。サービスは、名前空間内の複数のポッドにトラフィックを振り分け、負荷分散やアクセスの管理を行います。
- 例えば、
database
というサービスがあるとします。このサービスは、データベースのポッド群(例えば、MySQLのポッド)にトラフィックをルーティングします。
- サービスは、ポッドに関連付けられたIPアドレスとポート番号を自動的に提供します。サービスのIPアドレスは変更されることがありますが、サービス名は常に一定です。
3. ポッド(POD)
ポッドはKubernetesで最小の実行単位です。ポッドは、1つ以上のコンテナをホストし、これらのコンテナは同じネットワークやストレージを共有します。
- サービスはポッドの集合に対してトラフィックを振り分けます。例えば、
database
というサービスが複数のポッド(MySQLのインスタンス)にトラフィックを分配することになります。
例:
名前空間に複数のサービス
- 名前空間:
dev
(開発環境) - サービス:
frontend-service
(フロントエンド) - サービス:
api-service
(API) - サービス:
database-service
(データベース)
各サービスには複数のポッド
frontend-service
には、例えば3つのポッド(フロントエンドアプリケーション)があります。
api-service
には、例えば5つのポッド(バックエンドAPI)があり、トラフィックを均等に処理します。
database-service
には、例えば3つのポッド(MySQL)があり、データベースへのリクエストを処理します。
まとめ:
- 名前空間は、リソースをグループ化するための単位です。
- サービスは、複数のポッドを抽象化し、アクセスを管理します。
- ポッドは実際にコンテナを実行する最小単位です。
この仕組みによって、名前空間ごとにリソースを整理し、複数のサービスとポッドを効率的に管理することができます。
1. なぜDockerコンテナ同士が通信するのは難しいのでしょうか?
選択肢:
a. Dockerのデフォルトネットワーキングではコンテナ間に接続性がないため。
b. コンテナ同士の通信を有効にするためには、コンテナのファイアウォールを常に無効にする必要がある。
c. コンテナは動的なIPアドレスとホスト名を使用しているため、1つのコンテナが別のコンテナのIPアドレスを信頼性をもって見つけるのは、明示的な設定なしでは難しい。
d. コンテナ同士が接続するためには、VPNクライアントとサーバーが必要である。
解説
2. マルチコンテナアーキテクチャを使用する際の利点はどれか?(3つ選んでください)
選択肢:
a. それぞれのコンテナに単一のアプリケーションやサービスだけを含めることで、デプロイ、メンテナンス、管理が簡素化される。
b. 使用するコンテナが多ければ多いほど、パフォーマンスが向上する。
c. 複数のコンテナを使用することで、アプリケーションの各層を独立してスケールでき、リソースの節約につながる。
d. 単一の目的のみを提供するコンテナでは、監視、トラブルシューティング、デバッグが簡素化される。
e. 複数のコンテナを使用するアプリケーションは、単一コンテナ内で構築されたアプリケーションよりも欠陥が少ないことが多い。
解説
3. Kubernetesはどのようにして環境変数を使用したサービスディスカバリーの問題を解決しますか?
選択肢:
a. Kubernetesは、すべての環境変数をすべてのポッドに自動的に伝播させ、必要な環境変数をコンテナが利用できるようにする。
b. コントローラーは、ポッド間で環境変数を共有する役割を担う。
c. Kubernetesは、すべての環境変数のリストを保持し、ポッドが必要に応じてそれをリクエストできるようにする。
d. Kubernetesは、指定された名前空間内のすべてのサービスの環境変数を自動的にすべてのポッドに注入する。
解説
ユーザー定義Dockerネットワーク
問題点
スタンドアロンコンテナ同士はIPアドレスを使って通信できますが、コンテナが再起動するとそのIPアドレスが変更される可能性があり、これが原因でコンテナ間の通信が切断されることがあります。
- ユーザー定義Dockerネットワーク:
- これは、コンテナ同士の通信を管理するためのネットワークです。ユーザーがネットワークを明示的に作成し、コンテナをそのネットワークに接続することで、コンテナ間の通信が可能になります。
- 特に、コンテナ名をホスト名として使用して通信できるという特徴があります。これにより、コンテナが再起動してもIPアドレスが変わることなく、名前で通信できるようになります。
- Dockerサービス:
- サービスは、複数のコンテナを管理してスケーリングを可能にする仕組みです。特に、Docker Swarmモードで使われ、複数のコンテナインスタンス(レプリカ)を管理します。
- サービス内のコンテナは自動的に同じネットワークに接続され、サービス名やコンテナ名を使って互いに通信できます。
機能/違い | ユーザー定義Dockerネットワーク | Dockerサービス |
目的 | コンテナ間の通信管理 | 複数コンテナの管理・スケーリング |
スケーラビリティ | スケーリング機能はなし | 自動スケーリング機能あり |
ネットワークの設定 | ユーザーが手動でネットワークを作成・管理 | サービス作成時に自動的にネットワークが設定 |
通信の管理 | コンテナ名で通信 | サービス名で通信 |
使われるシナリオ | 単純なコンテナ間通信 | 高可用性や負荷分散を求めるサービス管理 |
このように、ユーザー定義Dockerネットワークは、コンテナ間の通信に焦点を当てたもの、Dockerサービスは、コンテナの管理やスケーリングに焦点を当てたものです。それぞれのユースケースに応じて使い分けることが重要です。
解決方法
Dockerはこの問題を解決するために、ユーザー定義ブリッジネットワークを提供しています。これにより、複数のコンテナがコンテナ名を使って通信することができ、再起動時でも名前は変わらず安定した通信が保証されます。
- ユーザー定義のブリッジネットワークでは、すべてのコンテナがDockerホストの内蔵DNSサーバーによって管理される統一的なDNSレコードにアクセスできます。
- これにより、他のコンテナは静的なコンテナ名を使って通信することができ、IPアドレスが変更されても通信が途切れることはありません。
メリット
- コンテナ名を使った通信: IPアドレスが変更されても、コンテナ名を使うことで通信が維持される。
- サービスディスカバリ: ユーザー定義ネットワーク内のコンテナ間で、サービスを簡単に発見・接続できる。
Dockerネットワークの管理
基本コマンド
Dockerネットワークの管理には、
docker network
コマンドを使用します。以下は主なコマンドです。- 利用可能なネットワークのリスト
出力例:
- ネットワークの詳細情報を確認
出力例:
- 新しいネットワークの作成
- ネットワークの削除
サービスディスカバリとユーザー定義ネットワーク
ユーザー定義ブリッジネットワークの利点
同じユーザー定義ブリッジネットワークに接続されたコンテナ同士は、コンテナ名を使ってお互いに通信できます。これにより、IPアドレスの変動に依存せず、通信が安定します。
- コンテナ名を解決: 例えば、
web_container
はdb_container
を解決することができ、逆も同様です。
- ポートの公開: コンテナは同じブリッジネットワーク内では全てのポートを他のコンテナに公開しますが、外部ネットワークへのポート公開は明示的な設定が必要です。
ユーザー定義Dockerネットワークについて
1. ネットワークの作成
ユーザー定義のDockerネットワークを作成すると、同じネットワークに接続されたコンテナ同士が名前で通信できるようになります。このネットワークは、コンテナ間の通信をより簡単にするために使われます。
例:
このコマンドで、
A
という名前のユーザー定義ネットワークを作成します。2. コンテナの接続
作成したネットワークにコンテナを接続するには、コンテナを起動する際に
--network
オプションを使います。例えば、コンテナBをネットワークAに接続する場合:
同様に、コンテナCをネットワークAに接続する場合:
3. コンテナ同士の通信
コンテナBとコンテナCが同じネットワークAに接続されている場合、これらはお互いをコンテナ名で簡単に認識し、通信することができます。
例えば、コンテナB内からコンテナCに対して、以下のように名前でアクセスできます:
このように、コンテナ名
C
が自動的にIPアドレスに解決され、通信が行われます。これにより、コンテナ同士は固定のIPアドレスを気にせず、名前で簡単に通信できます。4. ネットワークの管理
- ユーザー定義ネットワーク内のコンテナは、DNSを使ってお互いの名前を解決できるので、コンテナが再起動してもIPアドレスが変わることはなく、名前での通信が常に可能です。
- ネットワークを変更したり、新しいネットワークを作成したりすることも簡単です。
まとめ
ユーザー定義Dockerネットワークを使用すると、同じネットワークに接続されたコンテナは名前を使って簡単に互いに通信できるようになります。ネットワークを作成してコンテナを接続するだけで、面倒なIPアドレス設定やルーティング設定をせずにサービスの相互接続が可能です。
これで、ユーザー定義Dockerネットワークの基本的な使い方がよりわかりやすくなったと思います!
手順例
1. ネットワークの確認
まず、Dockerネットワークを確認します。
2. MySQLコンテナをバックグラウンドで実行
次に、MySQLコンテナを実行し、
do285-bridge
ネットワークに接続します。3. Webコンテナをバックグラウンドで実行
同様に、Webサーバーコンテナを実行し、
do285-bridge
ネットワークに接続します。4. Webコンテナ内でMySQLに接続
Webコンテナ内でインタラクティブなシェルを開き、MySQLに接続してデータベースを確認します。
実行結果例:
この結果から、
db_container
のホスト名が正しく解決され、IPアドレスが動的に取得されていることが確認できます。参考文献
- Dockerのネットワークに関する詳細な情報は、公式ドキュメントの「Networking Overview」セクションを参照してください。
以上が、Dockerを使用した複数コンテナのアプリケーションのデプロイに関する詳細な手順と説明です。ユーザー定義ネットワークを活用することで、コンテナ間の通信を安定させ、サービスディスカバリを簡素化できます。
- 作者:みなみ
- 链接:https://tangly1024.com/資格勉強/149d7ae8-88e2-80ab-a027-d9ab1796fd8c
- 声明:本文采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处。
相关文章