Dockerポートを公開することと露出することの違いは何ですか?
公開されているポートと公開されたコンテナポートは、Dockerにおける2つの異なるが関連する概念です。公開ポートはDockerfile内で単純なメタデータとして定義されます。外部アクセスを有効にしたい場合は、コンテナが起動するときにそれらを公開する必要があります。
ポートを公開する
ポートは、イメージのDockerfile内のEXPOSE命令によって公開されます。
EXPOSE 80ポートを公開することには即座に影響はありません。その声明は、コンテナ内のアプリケーションがポート80でリッスンしていることを伝えるだけです。それはホストのネットワークインターフェースにポートをバインドするわけではありません。
画像の作成者として、EXPOSEを使ってワークロードで使用するポートをリストすることで、ユーザーがコンテナを起動するときに適切なポート転送ルールを設定するのに役立ちます。これは、非標準のポートが使用される場合に特に重要です:ウェブサーバーがポート80でリッスンすることが期待される一方で、ユーザーはカスタムソケットサーバーが使用するポートを推測することができません。
公開されたポートは、docker psを使用してコンテナをリストすると表示されます。実際にはコンテナの外部からアクセスできないにもかかわらず、PORTS列に表示されます。これにより、コンテナ内のソフトウェアがどのポートをリッスンしているかを簡単に確認できます。
コンテナを起動せずに、docker inspectを使用してイメージによって公開されたポートを確認できます。demo-imageの代わりに、あなたのイメージのタグまたはIDを置き換えてください:
docker inspect --format="{{json .Config.ExposedPorts}}" demo-image出版ポート
ポートを公開すると、コンテナの外部からアクセスできるようになります。これは、EXPOSE命令によって発見したポートにホストポートをバインドできるようにします。
ポートは、docker runコマンドのために-pフラグを使用して公開されます。
docker run -d -p 8080:80 httpd:latestこのコマンドは、あなたのDockerホストのポート8080を新しいコンテナ内の80にバインドします。これで、http://localhost:8080にアクセスしてコンテナのポートにアクセスできます。docker psを実行すると、PORTS列にこのマッピングが表示されることがわかります。公開されたコンテナポート80はホストに公開されました。
コードの
-p
フラグは、バインドするポートを指定せずに使用できます:docker run -d -p 80 httpd:latest
このバリアントは、コンテナ内のポート80をホスト上のランダムなポートにバインドします。割り当てられたポートは、docker psを実行することで確認できます。
-p は特定のネットワークインターフェイスにポートを公開することもサポートしています:
docker run -d -p 127.0.0.1:8080:80 httpd:latestここで、コンテナポート80はホストのローカルループバックアドレスのポート8080を介してのみアクセス可能です。これにより、他のデバイスからのネットワーク呼び出しからコンテナが保護されます。
全ての公開されたポートを公開する
Dockerfileに記載されたすべての公開ポートを自動的に公開するために、--publish-allフラグを使ってコンテナを起動できます。
docker run -d --publish-all httpd:latestこれは、ホスト上のランダムな空きポートをコンテナ内の各公開ポートに割り当てます。作成されたポートの割り当てを確認するには、docker ps コマンドを使用してください。これにより、いくつかの非標準ポートを開く必要のあるイメージから新しいコンテナを開始することが簡素化されます。
--publish-all と明示的な -p マッピングを組み合わせることができます。この場合、-p フラグで作成されたマッピングが --publish-all によって割り当てられたランダムポートを上書きします。
ポートを公開する必要がないとき
Dockerホストや物理ネットワーク上の他のデバイスからコンテナポートにアクセスしたい場合は、-pを使用して公開する必要があります。コンテナ間トラフィックのためには、Dockerネットワークが推奨される代替アプローチです。
ネットワークを共有するコンテナは、ポートが明示的に公開されていなくても、常に相互に通信できます。
docker network create demo-network
docker run -d --network demo-network --name web web:latest
docker run -d --network demo-network --name database database:latest
この例では、web コンテナは database コンテナでポート 3306 で実行されている MySQL サーバーに database:3306 アドレスを使って接続することができます。Docker はネットワーク内のコンテナ名のために自動的にルーティングテーブルを設定します。
ポート範囲の使用
Dockerは複数のポートを利用する必要がある場合、ポート範囲全体を公開して公開することができます。
EXPOSE 8000-8100
docker run --publish-all
docker run -p 6000-6100:8000-8100
最初の場合、--publish-allはホスト上の100のランダムポートを割り当て、それらをコンテナの範囲にマッピングします。2つ目の形式では、通常通りホスト範囲をコンテナ範囲に明示的にバインドします。非常に多くのポートを使用すると、各ポートに対してiptablesルールが作成されるため、パフォーマンスに影響を与える可能性があります。
要約
公開されているポートは、コンテナイメージ内のソフトウェアがリスンするポートを定義するメタデータの一部です。公開されているポートが存在しても、それを手動で公開しない限り、ホストのインターフェースでアクセス可能にはなりません。この意味では、動詞「公開する」は誤称であり、多くの人がそれを能動的な行動だと考えますが、実際には情報の声明です。EXPOSEはドキュメントとして扱うべきであり、-pフラグは機能するポートマッピングを作成します。
Dockerは、EXPOSE命令に基づいていくつかの追加の動作を提供します。公開されているかどうかにかかわらず、docker psを使用してコンテナの公開ポートを表示できます。また、イメージの公開ポートをランダムなホストポートに公開する--publish-allフラグもあります。
コンテナのポートは、公開されていなくても、そのコンテナのIPアドレスを通じて常にアクセス可能です。docker inspectの出力に表示されるDockerによって割り当てられたIPを使用してコンテナに到達できるデバイスは、すべてのリスニングポートを使用することができます。
ホストのネットワークインターフェースを使用してコンテナにアクセスしたい場合にのみ、ポートを公開する必要があります。Dockerネットワークを使用している場合、ポートの公開は必要ありません。同じネットワーク内のコンテナ間の通信は、関連するポートが公開されているかどうかにかかわらず、妨げられません。



