Docker コンテナ ネットワーク - チュートリアル
Docker の素晴らしさをさらに探求する時間です。これまでに 2 つのチュートリアルがありました。1 つは非常に徹底的な紹介に焦点を当てており、テクノロジ、サービスを実行してポートを公開する方法、Dockerfiles を使用してイメージをコミットおよびビルドする方法、およびその他のいくつかのトリックについてすべて学びました。次に、init スクリプトと systemd の代わりに Supervisord を使用しました。
今日は、ネットワークについて学びます。コンテナーに接続する方法、生成されたインスタンス内からホストにアクセスする方法、そして最も重要なのは、事前にトポロジーについて何も知らなくても、あるコンテナーから別のコンテナーに接続する方法です。これは興味深いはずです。前の 2 つのガイドと同様に、順を追ってすべてを詳細に説明します。私の後。
目次
- セットアップ
- ホストからコンテナへのネットワーキング <オール>
- まとめ
セットアップ
まず、いくつかのコンテナを作成しましょう。前回のテストの画像は既にあるので、ゼロから始める必要はありません。それぞれ独自の SSH および Apache サービスを備えた 3 つのコンテナーを実行します。ネットワーク部分に集中しようとしているので、セキュリティ面は無視してください。
ここで、前回行っていないことの 1 つは、識別しやすいようにコンテナーに名前を付けることです。これは --name オプションを使用して行われます。例:
docker run -d -ti -p 22 -p 80 --name net3 image-4:latest
3 つのインスタンスの IP アドレスも見てみましょう:
[root@localhost ~]# docker inspect net1 | grep -i ipaddr
"IPアドレス":"172.17.0.5",
[root@localhost ~]# docker inspect net2 | grep -i ipaddr
"IPアドレス":"172.17.0.6",
[root@localhost ~]# docker inspect net3 | grep -i ipaddr
"IPアドレス":"172.17.0.7",
これは、テスト用の初期構成です。 3 つのコンテナーがあり、すべてが同じホストで実行されており、それらのサービスと公開されたサービス ポートがあります。これで、かなり興味深いことを始めることができます。
ホストからコンテナへのネットワーキング
これは簡単な部分であり、実を言うと、これは前の演習で既に行っています。 SSH を使用してコンテナーに接続し、telnet を使用してポートのテストを試みました。はい、netcat (nc) も正常に動作します。セキュリティ クラクションをオフにしてください。接続には 2 つの方法があります。 1 つは、以前に行ったように、IP アドレスを使用してコンテナーに直接アクセスできることです。
ssh 172.17.0.5
ホスト '172.17.0.5 (172.17.0.5)' の信頼性を確立できません。 ECDSA キー フィンガープリントは 00:4b:de:91:60:e5:22:cc:f7:89:01:19:3e:61:cb:ea です。
接続を続行しますか (はい/いいえ)?はい
警告:既知のホストのリストに '172.17.0.5' (ECDSA) が永久に追加されました。
[email protected] のパスワード:
2 つ目は、コンテナー内のサービス ポートに対応するホスト マップ ポートにもアクセスできることです。 docker ps 出力の PORTS 情報だけを見ると、次のようになります。
0.0.0.0:49162->22/tcp、0.0.0.0:49161->80/tcp net1
0.0.0.0:49163->22/tcp、0.0.0.0:49164->80/tcp net2
0.0.0.0:49165->22/tcp、0.0.0.0:49166->80/tcp net3
上記の例では、net1 という名前のコンテナーの場合、ポート 22 がホストのポート 49162 にマップされます。これは、デフォルトで 172.17.42.1/16 ネットワークが割り当てられる docker0 インターフェースを意味します。確かに、次のことがわかります:
telnet 172.17.42.1 49163
172.17.42.1 を試しています...
172.17.42.1 に接続しました。
エスケープ文字は「^]」です。
SSH-2.0-OpenSSH_6.6.1
では、なぜ 2 番目の方法を使用する必要があるのでしょうか。それは、より混乱し、覚えにくいためです。答えは、動的マッピングを使用せず、代わりに既知の特定のホスト ポートを指定する場合、コンテナ ネットワークの非常に明確なトポグラフィを作成できるということです。さらに、ホストの外部からコンテナーにアクセスできるようにする場合は、IP 転送と NAT が必要になります。通信に docker0 インターフェースを使用する場合、必要な iptables ルールの数が減り、単純になります。
これは、iptables -L コマンドを実行し、DOCKER チェーンをチェックすることで確認できます。 -p オプションを使用してコンテナを実行すると、新しいルールが自動的に追加されます。
Chain DOCKER (1 文献)
ターゲット prot opt ソース 宛先
ACCEPT tcp -- どこでも 172.17.0.5 tcp dpt:http
ACCEPT tcp -- どこでも 172.17.0.5 tcp dpt:ssh
ACCEPT tcp -- どこでも 172.17.0.6 tcp dpt:ssh
ACCEPT tcp -- どこでも 172.17.0.6 tcp dpt:http
ACCEPT tcp -- どこでも 172.17.0.7 tcp dpt:ssh
ACCEPT tcp -- どこでも 172.17.0.7 tcp dpt:http
ACCEPT tcp -- どこでも 172.17.0.8 tcp dpt:ssh
ACCEPT tcp -- どこでも 172.17.0.8 tcp dpt:http
ただし、セキュリティ上の制限がない場合は、コンテナーを起動するときにポートのマッピングを知る必要がないため、動的な方法が非常に役立ちます。 docker ps の出力を解析して、リアルタイムで情報を取得できます。ただし、サービスの場合、静的 IP アドレスと既知のポートを設定すると便利なことがよくあります。
まとめ
これは少しややこしいので、簡単に要約しましょう。どの docker ホストでも docker0 または同様の名前のブリッジが実行され、通常は /16 サブネットで実行されますが、サブネットまたはネットワークの名前を変更することもできます。その背後には、さまざまなコンテナーがあり、それぞれに独自のプライベート IP アドレスと 1 つ以上の公開ポートがあります。
これらのコンテナーとその関連ポートに接続する場合は、いくつかのオプションがあります。直接接続することもできますが、その場合はそれぞれに IP 転送、NAT、およびファイアウォール ルールが必要であり、IP アドレスを知る必要があります。
ホスト インターフェイス (docker0) とホスト ポート メソッドを使用して接続する場合は、コンテナーの実行方法を知る必要はありません。ホスト ポートからコンテナー ポートへのマッピングを知っていれば十分です。つまり、複数のホスト ノード間でコンテナーにアクセスできるようにする場合は、ホスト インターフェイス (docker0) を他のホストから見えるようにするだけで済みます。これにより、IP 転送、NAT、およびファイアウォール ルールがシンプルになります。例:
0.0.0.0:30001->22/tcp net1
0.0.0.0:30007->22/tcp net4
0.0.0.0:30008->22/tcp net5
上記の例では、3 つの異なるコンテナの SSH に接続できます。 1 対 1 のマッピング、つまり同じホスト ポートとコンテナー ポート (例:22:22) を使用する場合、1 つのサービスがリッスンしている 1 つのコンテナーのみに効果的に制限されます。これは家庭用ルーターのようなものです。 1 対 1 のマッピングを使用できるようにするには、コンテナーに異なるポートを使用する必要があります。ただし、サービスが予測可能なポートで実行されることを期待しているため、これは混乱を招きます。
上記の例では、3 つのコンテナーで SSH を使用できることがわかります。内部的には、コンテナーの観点からは常にポート 22 です。外部から見ると、ポート番号は両方ともコンテナーとサービスを識別します。これは、舞台裏で何が起こっているかを気にせずに、知っておく必要がある唯一の部分になります。
これは、コンテナーの作成時に何らかのスクリプト ロジックなどを使用してホスト ポートを動的に割り当て、その情報を使用してサービス ポートを識別することができることを意味します。したがって、ホストからコンテナへのネットワークはシンプルで洗練されたものになります。また、コンテナーのトポグラフィーを事前に知らなくても、ホストから別のホストに接続することもできます。
ネットワークをホストするコンテナ
これはもう少し興味深い作品です。コンテナーは長期間にわたって使用される場合があるため、しばらくの間稼働状態を維持する必要がある場合があります。これは、コンテナーを維持する必要があることを意味します。つまり、アップグレード、パッチ適用、ホスト ファイルの更新などです。また、Chef、Puppet、Cfengine などの構成管理ツールを使用している可能性もあるため、その部分もあります。
最初に問わなければならない大きな問題は、コンテナが外の世界と通信できるかどうかです。はい、そうです。導入ガイドでは、CentOS の更新プログラムを公式リポジトリから直接ダウンロードしたため、この部分が問題なく動作することがわかります。 docker0:
に ping を実行してみてはどうでしょうか。
2 番目の質問は、docker0 インターフェイスにアクセスして、そのホスト ポートに接続できるかどうかです。コンテナー内で、何らかの形で必要な情報が与えられたとしましょう。
telnet 172.17.42.1 49162
172.17.42.1 を試しています...
telnet:アドレス 172.17.42.1 に接続:ホストへのルートがありません
ホストで IP 転送を構成していないため、これは機能しません。さらに、必要なトラフィックを許可するファイアウォール ルールが必要になります。ここでは、少し複雑になります。iptables に慣れていない場合は、多少苦労するからです。
エコー 1> /proc/sys/net/ipv4/ip_forward
そして iptables ルール - やや緩いセット、心 (ホスト上):
iptables -t フィルター -A フォワード -d 172.17.0.0/16 \
-o docker0 -j 受け入れる
iptables -t フィルター -A フォワード -s 172.17.0.0/16 \
-i docker0 -j 受け入れる
iptables -t filter -A FORWARD -i docker0 -o docker0 -j ACCEPT
iptables -t nat -A ポストルーティング -s 172.17.0.0/16 \
! -d 172.17.0.0/16 -p tcp -j マスカレード --to-ports 1016-65535 \
iptables -t nat -A ポストルーティング -s 172.17.0.0/16
! -d 172.17.0.0/16 -p udp -j MASQUERADE --to-ports 1016-65535 \
iptables -t nat -A ポストルーティング -s 172.17.0.0/16
! -d 172.17.0.0/16 -j マスカレード
最も簡単な方法は、ファイアウォールを無効にするか、すべて許可することです。これは、systemctl stop firewalld、iptables -F、または同等のコマンドを実行することを意味します。一部のシナリオでは、追加のセキュリティが必要なため、これが不可能な場合があります。ただし、これは、説明した最初のユースケースにも関係しています。ここで、すべてのコンテナーとそれに関連するサービスに対して手動でルールを作成する必要があると想像してください。
適切なネットワーク ルールが整っていれば、ホスト ポートに接続できます。これは、他のコンテナーと通信することを効果的に意味しますが、特定の IP アドレスまたはポートには、ターゲットが別のコンテナーである必要があるものは何もありません。さらに、ホスト上の他のネットワーク デバイスやリモート ホストに接続することもできます。
コンテナ間のネットワーク
デヴィッド・ボウイの歌、アッシュ・トゥ・アッシュのように、クールではありません。これは最も有用なシナリオのようです。繰り返しますが、2 つのオプションがあります。他のコンテナーに直接接続するか、docker0 の動的にマップされたポートを使用してみることができます。ごまかします。ホストとホスト ポートをコンテナーへのゲートウェイとして使用します。さて、最初の方法は非常に簡単です。 net1 から net2 と net3 に ping を実行してみましょう。
問題なく動作します。しかし問題は、外界からの IP アドレスを知っていることです。この情報はコンテナ内から取得していません。実際、セキュリティ上の理由と、ベース コンテナーが比較的小さなイメージであることから、デフォルトで利用できる優れたネットワーク ツールはありません。 ifconfig ユーティリティも利用できません。さらに、コンテナ内で iptables を操作することもできません:
iptables-L
iptables v1.4.21:iptables テーブル `filter' を初期化できません:権限が拒否されました (root である必要があります)
おそらく、iptables またはカーネルをアップグレードする必要があります。
したがって、docker0 にアクセスしてホスト ポートに接続する 2 番目の方法は、コンテナー内からではなく、ホストのファイアウォール ルールを操作できないため、実際には実行できない可能性があります。このため、3 番目の方法について説明します。
コンテナ リンク!
これを行う適切な方法は、 --link 機能を使用することです。これが意味することは、他の既存のコンテナにリンクしながら、新しいインスタンスを生成するということです。リンク機能は、リンクされたコンテナーのホスト名と IP アドレスを環境と新しいインスタンスの /etc/hosts ファイルに挿入します。ちょっとややこしいかもしれませんので、例を挙げてみましょう:
docker run -d -ti -p 80 --name web image-4:latest
8e689d8ae3ef43eeab3bfa9cf523e1cc6658dae5fc665f8cbf889db17db46c26
ドッカーはウェブを検査します | grep -i ipaddr
"IPアドレス":"172.17.0.9",
nc -w1 -v 172.17.0.9 80
Ncat:バージョン 6.40 ( https://nmap.org/ncat )
Ncat:172.17.0.9:80 に接続されました。
実行中のコンテナーがあり、それは Web サーバーであるはずです。ここで、クライアントがアクセスできるようにしたいと考えています。地形についての事前知識がない可能性があるため、IP アドレスではなくサーバー名を使用したいと考えています。さらに、名前はネットワーク レイアウトを変更できるので便利です。実際に、クライアント コンテナーを作成して、それを Web サーバーにリンクしてみましょう:
docker run -ti --name client --link web:web image-4:latest /bin/bash
ここにあるのは次のとおりです。 source:target のリンクを作成しています。つまり、web という名前のサーバー (コンテナー) は、client という名前の新しいコンテナー内で web として表示されます。コンテナーを生成してからアタッチすると、BASH シェルで env コマンドを実行して環境を確認できます:
WEB_PORT_80_TCP_PORT=80
WEB_PORT_80_TCP=tcp://172.17.0.9:80
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
PWD=/
WEB_PORT_22_TCP_ADDR=172.17.0.9
container_uuid=558a9db0-6d1e-d9d2-b62d-a8dbfbad0b2d
WEB_PORT_22_TCP=tcp://172.17.0.9:22
SHLVL=1
HOME=/ルート
WEB_NAME=/クライアント/ウェブ
WEB_PORT_80_TCP_PROTO=tcp
WEB_PORT_80_TCP_ADDR=172.17.0.9
LESSOPEN=||/usr/bin/lesspipe.sh %s
WEB_PORT=tcp://172.17.0.9:22
_=/usr/bin/env
同じ名前のマッピングは混乱を招く可能性があるため、別のマッピングを試してみましょう:
docker run -ti --name client --link web:dedoimedo image-4:latest /bin/bash
そして、次のようになります:
必要に応じて、迅速なワーカーにする必要があるコンテナーを生成する場合は、run --rm オプションを使用してコンテナーを作成することを検討してください。短期間のタスクの場合、コンテナー ファイルをディスクに保持する必要はなく、Docker にそれらを自動的にクリーンアップさせることができます。公式ドキュメントを読む:
デフォルトでは、コンテナーのファイル システムは、コンテナーが終了した後も保持されます。これにより、デバッグが非常に簡単になり (最終状態を検査できるため)、デフォルトですべてのデータが保持されます。しかし、短期間のフォアグラウンド プロセスを実行している場合、これらのコンテナー ファイル システムは実際に山積みになる可能性があります。代わりに、Docker がコンテナーを自動的にクリーンアップし、コンテナーの終了時にファイル システムを削除するようにしたい場合は、 --rm フラグを追加できます。
docker run --rm -ti --name client --link web:dedoimedo image-4:latest /bin/bash
ホスト ファイル
リンク機能の 2 つ目の利点は、新しいコンテナーの /etc/hosts ファイルに必要な名前が自動的に入力されるため、便利です。 IPv6 エントリを削除すると、次のようになります:
[root@e1e92f6918dd /]# 猫 /etc/hosts
172.17.0.11 e1e92f6918dd
127.0.0.1 ローカルホスト
172.17.0.9 dedoimedo 8e689d8ae3ef web
その名前を使用してサーバーに接続します
また、ホスト名の解決と環境設定があるため、どこにいてもネットワークと同じようになります。本当にシンプルで、記憶に残り、最も重要なのは、スクリプト化可能です。
続きを読む
十分に楽しんでいないと思われる場合は、
Docker の高度なネットワーキング ガイド
結論
ほらね。別の恐ろしいトピックが分かりやすくなりました。問題は、Docker コンテナーを使用する際に直面する最大の課題は、このテクノロジのネットワーク部分に不可欠なものではなく、ファイアウォール ルールの構成であると私は信じています。しかし、一度コツをつかめば、それほど難しくも複雑でもありません。
コンテナを起動してポートを公開する方法、ホストからコンテナへ、コンテナからホストへ、およびコンテナからコンテナへのネットワークを実行する方法、転送をセットアップする方法、リンクを使用して生活をより簡単で予測可能なものにする方法を見てきました。全体として、それは忙しいですが、できれば実用的なガイドでした.繰り返しますが、他のトピックがあれば、遠慮なく提案してください。これで完了です。
追記この記事が気に入ったら、デドイメドに恩返しをしましょう!
乾杯。
-
Microsoft EMET v4 のレビューと広範なチュートリアル
ここまでで、Microsoft Enhanced Mitigation Experience Toolkit が Windows オペレーティング システムに最適なセキュリティ ソフトウェアであることはご存じでしょう。理由はたくさんあります。主に、セットアップがシンプルで透過的であり、ばかげた質問はありません。それは無料です。そして、それはそれがすることにおいて効果的です。あなたがばかになるのを止めるのではなく、ソフトウェアが誤動作するのを止めます。そして、それがそれを素晴らしいものにしている理由であり、これが、有料セキュリティの世界でスポットライトがほとんど当てられない理由です. 現在、
-
Windows 10 エクスプロイト保護 - チュートリアル
Windows 10 Fall Creators Update (ビルド 1709) のリリースにより、最も優れた洗練された Enhanced Mitigation Experience Toolkit (EMET) が利用できなくなったか、このオペレーティング システムにインストールできなくなりました。代わりに、これらの軽減策は Windows 10 の不可欠な部分になりました。 私は EMET の大ファンであり、すべての Windows マシンで EMET を使用しているため、Windows 10 で新しい軽減策を展開して調整する方法について、詳細で実用的かつ実際の使用ガイドを作成するこ