マルチコンテナのセットアップでは、コンテナで実行されているサービスは、共通のネットワークを介して相互に通信します。同じ設定で、一部のコンテナは外界とも相互作用します。
この内部通信と外部通信は、Dockerの公開ポートと公開ポートでそれぞれ処理されます。
このチュートリアルでは、Dockerでのポートの処理について説明します。ポートの公開と公開の違い、それらが使用される理由、およびそれらの使用方法について説明します。
Dockerでのポートの公開と公開
Dockerでポートを処理するには、ポートを公開する方法と公開する方法の2つがあります。
ポートの公開 単に、コンテナ化されたアプリケーションがどのポートでリッスンするか、または接続を受け入れるかを他の人に知らせることを意味します。これは、外界とではなく、他のコンテナと通信するためのものです。
ポートの公開 コンテナのポートをホストのポートにマッピングするようなものです。このようにして、コンテナは外部システム、現実世界、インターネットと通信できます。
このグラフィックは、理解に役立ちます。
ご覧のとおり、SERVERコンテナのポート80がホストシステムのポート80にどのようにマッピングされていますか?このようにして、コンテナはホストシステムのパブリックIPアドレスを使用して外部と通信できます。
一方、公開されたポートには、コンテナの世界の外部から直接アクセスすることはできません。
覚えておくべきこと:
- 公開されたポートは、コンテナの世界での内部コンテナ通信に使用されます。
- 公開されたポートは、コンテナの世界以外のシステムとの通信に使用されます。
Dockerでポートを公開する
まず、ポートを公開する必要はありません。なんで?セットアップで使用するDockerイメージのほとんどは、構成で既にデフォルトのポートが公開されているためです。
たとえば、コンテナ化されたフロントエンドアプリケーションは、コンテナのIPと、MariaDBが接続を受け入れているポート(デフォルトは3306)を指定するだけで、MariaDBデータベースと通信できます。
公開は、デフォルトが使用されていない状況で役立ちます。たとえば、この場合、MariaDBがポート3306で接続を受け入れない場合は、公開して代替ポートを指定する必要があります。
ポートを公開する方法は2つあります。
-
EXPOSE
の使用 Dockerfile命令。 -
--expose
の使用 DockerCLIまたはexpose
を使用 docker-composeを入力します。
両方を深く掘り下げる時間です。
方法1:Dockerfileを介してポートを公開する
Dockerfileに簡単な命令を追加して、アプリケーションが接続を受け入れるポートを他の人に知らせることができます。
この手順について知っておくべきことは次のとおりです。-
-
EXPOSE
しません 結果のDockerイメージにレイヤーを追加します。メタデータを追加するだけです。 -
EXPOSE
文書化の方法です アプリケーションポート。それが持つ唯一の効果は、読みやすさまたはアプリケーションの理解の観点からです。
この目的のためだけに作成した単純なコンテナイメージで、exposureがどのように機能するかを確認できます。 この画像は何もしません 。
画像をプルします。
docker pull debdutdeb/expose-demo:v1
この画像は合計4つのポートを公開しています。次のコマンドを使用して、画像を一覧表示します。
docker image ls --filter=reference=debdutdeb/expose-demo:v1
SIZE
をご覧ください 列には、0バイトと表示されます。
➟ docker image ls --filter=reference=debdutdeb/expose-demo:v1
REPOSITORY TAG IMAGE ID CREATED SIZE
debdutdeb/expose-demo v1 ad3d8ffa9bfe N/A 0B
理由は単純です。この画像にはレイヤーがなく、追加されたすべての公開命令はメタデータであり、実際のレイヤーはありません。
次のコマンドを使用して、使用可能なレイヤーの数を取得することもできます。-
docker image inspect -f '{{len .RootFS.Layers}}' debdutdeb/expose-demo:v1
次のような出力が表示されます。-
➟ docker image inspect -f '{{len .RootFS.Layers}}' debdutdeb/expose-demo:v1
0
前に述べたように、公開されたポートは画像メタデータとして追加され、アプリケーションが使用しているポートを通知します。
Dockerfileを見ずに、その情報をどのように確認しますか?画像を検査する必要があります。具体的には、以下のコマンドを参照してください。任意の画像で同様のコマンドを使用して、公開されているポートを一覧表示できます。
サンプル画像をデモに使用しています。
docker image inspect -f \
'{{range $exposed, $_ := .Config.ExposedPorts}}{{printf "%s\n" $exposed}}{{end}}' \
debdutdeb/expose-demo:v1
サンプル出力:
➟ docker image inspect -f '{{range $exposed, $_ := .Config.ExposedPorts}}{{printf "%s\n" $exposed}}{{end}}' debdutdeb/expose-demo:v1
443/tcp
80/tcp
8080/tcp
9090/tcp
いくつかのポートを公開しているこの画像を、debdutdeb/noexpose-demo:v1
と比較することもできます。 画像、それはどのポートも公開していません。その画像でも同じ一連のコマンドを実行し、違いに注意してください。
方法2:CLIまたはdocker-composeを介してポートを公開する
アプリケーション開発者は、余分なEXPOSE
を含めることを躊躇することがあります Dockerfileの命令。
このような場合、他のコンテナーが(docker APIを介して)使用中のポートを簡単に検出できるようにするために、デプロイプロセスの一部として、ビルド後に複数のポートを公開できます。
命令型の方法、つまりCLIを選択するか、宣言型の方法、つまりファイルの作成を選択します。
このメソッドでは、コンテナを作成するときに、--expose
を使用するだけです。 オプション(必要に応じて何度でも)とポート番号、およびオプションで/
を使用したプロトコル 。 1つの例を次に示します。-
docker container run \
--expose 80 \
--expose 90 \
--expose 70/udp \
-d --name port-expose busybox:latest sleep 1d
busybox
を使用しています デフォルトでポートを公開しない画像。
作成ファイルを使用している場合は、配列を追加できますexpose
サービス定義で。以前のデプロイメントを次のように作成ファイルに変換できます:-
version: "3.7"
services:
PortExpose:
image: busybox
command: sleep 1d
container_name: port-expose
expose:
- 80
- 90
- 70/udp
コンテナを実行したら、前と同じように、どのポートが公開されているかを調べるためにコンテナを検査できます。コマンドは似ています。
docker container inspect -f \
'{{range $exposed, $_ := .NetworkSettings.Ports}}
{{printf "%s\n" $exposed}}{{end}}' \
port-expose
サンプル出力:-
➟ docker container inspect -f '{{range $exposed, $_ := .NetworkSettings.Ports}}{{printf "%s\n" $exposed}}{{end}}' port-expose
70/udp
80/tcp
90/tcp
Dockerでポートを公開する
ポートパブリッシングは、パブリックポートの着信接続からの要求がコンテナのポートに転送されるポート転送の同義語です。
同様に、コンテナからそのポートを介して送信される応答は、ホストのポートスペース内の指定されたポートにトラフィックを転送することによってクライアントに送信されます。
ポートを公開するには、CLIを使用する方法と、作成ファイルを使用する方法の2つがあります。どちらの方法にも、1つの長い構文と1つの短い構文があります。
方法1:Dockerコマンドを介してポートを公開する
2つの構文は次のとおりです。
-
-p [optional_host_ip]:[host_port]:[container_port]/[optional_protocol]
-
--publish target=[container_port],published=[optional_host_ip]:[host_port],protocol=[optional_protocol]
オプションのホストIPには、任意のNICに関連付けられた任意のIPアドレスを使用できます。 IPが省略されている場合、dockerはポートを使用可能なすべてのIPアドレスにバインドします。
最初のものを最もよく使用します。 2番目のものはより読みやすいです。 nginxコンテナを使用した例を見てみましょう。次のコマンドを実行します:-
docker container run --rm --name nginx \
--publish target=80,published=127.0.0.1:8081,protocol=tcp \
-d nginx
このコマンドを使用すると、ローカルホスト上のホストの8081ポートにコンテナのポート80をバインドするだけです。ここで、http:// localhost:8081にアクセスすると、nginxが実行されていることがわかります。
前のコマンドは、次のように簡単に短い形式に変換できます
docker container run --rm --name nginx \
-p 80:127.0.0.1:8081/tcp -d nginx
短いですが、読みにくいです。
-p
を使用することもできます または--publish
複数のポートを公開するために複数回。
方法2:作成ファイルを介してポートを公開する
作成ファイルを使用してポートを公開するには、ports
という名前の配列が必要です。 サービス定義で。この配列は、CLIの短い構文に似た文字列のリストにすることも、長い構文に似たオブジェクトのリストを使用することもできます。
ポートセクションの文字列の配列を含む作成ファイルを使用して以前のnginxデプロイメントを変換すると、次のようになります。-
version: "3.7"
services:
Nginx:
image: nginx
container_name: nginx
ports:
- 80:127.0.0.1:8081/tcp
オブジェクトの配列構文の使用方法も示しましょう。
version: "3.7"
services:
Nginx:
image: nginx
container_name: nginx
ports:
- target: 80
published: 127.0.0.1:8081
protocol: tcp
公開されているすべてのポートのリストを表示するには、次のようにコンテナを検査できます-
docker container inspect -f '{{range $container, $host := .NetworkSettings.Ports}}{{printf "%s -> %s\n" $container $host}}{{end}}' nginx
実行すると、次の出力が表示されます。-
➟ docker container inspect -f '{{range $container, $host := .NetworkSettings.Ports}}{{printf "%s -> %s\n" $container $host}}{{end}}' nginx
80/tcp -> [{127.0.0.1 8081}]
docker container port
を使用して、公開されたポートを一覧表示するもう1つの簡単な方法があります。 コマンド。
docker container port nginx
出力例:-
➟ docker container port nginx
80/tcp -> 127.0.0.1:8081
ポートを公開するタイミングと公開するタイミング
これは公正な質問です。公開と公開は競合他社ではありません。それぞれが異なる目的を果たします。イメージの開発者である場合は、ポートを公開して、ユーザーが接続を試行する場所をより正確に確認できるようにします。一方、画像を使用していて、それを外部で利用できるようにする必要がある場合は、必要なポートを公開することになります。
この記事がお役に立てば幸いです。ご不明な点がございましたら、下のコメント欄でお知らせください。