Dockerの「公開」と「公開」の違いは何ですか?


517

私はDockerfilesを実験しており、ほとんどのロジックを理解していると思います。ただし、このコンテキストでのポートの「公開」と「公開」の違いはわかりません。

最初に見たすべてのチュートリアルにはEXPOSE、Dockerfileにコマンドが含まれています。

...
EXPOSE 8080
...

次に、このDockerfileからイメージを作成します。

$ docker build -t an_image - < Dockerfile

次に、イメージを実行するときに上記と同じポートを公開します。

$ docker run -d -p 8080 an_image

または使用してすべてのポートを公開する

$ docker run -d -P an_image

とにかく公開する場合、Dockerfileでポートを公開する意味は何ですか?最初にポートを公開し、後で公開する必要はありませんか?効果的には、イメージの作成時にDockerfileで使用するすべてのポートを指定し、それらを再度使用することなく、単に次のように実行します。

$ docker run -d an_image

これは可能ですか?

回答:


732

基本的に、3つのオプションがあります。

  1. どちらも指定しEXPOSEない-p
  2. 指定のみ EXPOSE
  3. 指定EXPOSEして-p

指定したどちらの場合1)EXPOSE-p、コンテナ内のサービスにのみからアクセスすることができます内側の容器そのもの。

2)EXPOSEポートの場合、コンテナー内のサービスにはDockerの外部からではなく、他のDockerコンテナーの内部からアクセスできます。したがって、これはコンテナー間の通信に適しています。

3)あなたEXPOSE-pポートの場合、コンテナー内のサービスはDockerの外部からでもどこからでもアクセスできます。

両方が分離されている理由は、次の理由からIMHOです。

  • ホストポートの選択はホストに依存しているため、Dockerfileに属していません(そうでない場合、ホストに依存します)。
  • 多くの場合、コンテナー内のサービスに他のコンテナーからアクセスできれば十分です。

ドキュメントは明示的に述べています:

このEXPOSE命令は、リンク内で使用するポートを公開します。

また、コンテナーのリンク方法についても説明します。これは、基本的に私が話し合ったコンテナー間の通信です。

PS:するが-p、しない場合EXPOSE、Dockerは暗黙的に行いEXPOSEます。これは、ポートが公開されている場合、他のDockerコンテナにも自動的に開かれるためです。したがってが-p含まれEXPOSEます。そのため、4番目のケースとして上記に記載しませんでした。


57
EXPOSEについてはあなたは正しくないと思います。他のコンテナーから、それらを公開せずにすべてのコンテナーポートにアクセスできます。やってみました。ここでの問題は、コンテナのIPアドレスが予測できないことです。リンクは、接続を有効にするためではなく、接続するコンテナを指定するため(特定のコンテナIPにリンクするため)に使用されると思います。
Jiri

7
「あなたがそれらのいずれかを指定しない場合は、」あなたと「ものは」あなたが意味することが明らかになった場合に、有用であろうEXPOSE-p三箇条書きは先例のありません。そこで少し混乱しました。
ピティコス2014

4
完全にするために、この回答は4番目の可能なケースにも対処するEXPOSE必要があります-p。を指定しなかったが、を指定した。常に-p個々のコンテナーを使用して実行する場合EXPOSEは省略してもかまいませんが、-Pまたはを使用すると便利/必要になることは理解しています--link。(そして、他の人があなたの画像をどのように使用するかわからないのでEXPOSE、公開画像で指定する必要があります。)
GrandOpener

6
ドキュメントには、「EXPOSE命令はリンク内で使用するためのポートを公開する」と記載されなくなりました。
Lorin Hochstein 2017

11
これは実質的に正しくないため、反対票を投じます。Exposeは基本的にドキュメントであり、それを使用しなくてもアクセスは制限されません。これは、誰かがアクセスを制限するためにそれに依存している場合、危険な誤解です。
mc0e 2018

167

簡潔な答え:

  • EXPOSE文書化する方法です
  • --publish(又は-p)の方法でマッピングホスト・ポートを実行するコンテナ港

その下に注意してください:

  • EXPOSEに関連していますDockerfiles文書化
  • --publishに関連していますdocker run ...実行/実行時

ポートの公開と公開

Dockerネットワーキングでは、ネットワークポートに直接関与する2つの異なるメカニズムがあります。ポートの公開と公開です。これは、デフォルトのブリッジネットワークとユーザー定義のブリッジネットワークに適用されます。

  • EXPOSEDockerfile のキーワードまたはdocker runの--exposeフラグを使用してポートを公開します。ポートの公開は、どのポートが使用されているかを文書化する方法ですが、実際にポートをマップしたり開いたりするわけではありません。ポートの公開はオプションです。

  • --publishまたは--publish-allフラグを使用してポートを公開しますdocker run。これは、コンテナーのネットワークインターフェイスで開くポートをDockerに指示します。ポートが公開されると、30000実行時にホストマシンでマッピングするポートを指定しない限り、ポートはホストマシンで利用可能な高次のポート(より大きい)にマッピングされます。(Dockerfileで)イメージをビルドするときに、ホストマシンでマッピングするポートを指定することはできません。これは、イメージを実行するホストマシンでポートが使用可能であることを保証する方法ないためです

from:Dockerコンテナーネットワーキング

2019年10月の更新:上記のテキストはドキュメントに含まれなくなりましたが、アーカイブされたバージョンはこちらです:docs.docker.com/v17.09/engine/userguide/networking/#exposing-and-publishing-ports

たぶん、現在のドキュメントは以下のとおりです:

公開されたポート

デフォルトでは、コンテナを作成するとき、コンテナはポートを外部に公開しません。Dockerの外部のサービス、またはコンテナーのネットワークに接続されていないDockerコンテナーがポートを使用できるようにするには、--publishor -pフラグを使用します。これにより、コンテナーポートをDockerホストのポートにマップするファイアウォールルールが作成されます。

そしてここで見つけることができます:docs.docker.com/config/containers/container-networking/#published-ports

また、

EXPOSE

...このEXPOSE命令は実際にはポートを公開していません。これは、イメージを作成する人とコンテナを実行する人との間の一種のドキュメントとして機能し、ポートの公開が予定されています。

from:Dockerfileリファレンス






EXPOSE/ --publishが定義されていない場合のサービスアクセス:

@Goloローデンの答えのことが記載されている::

「これらのいずれも指定しない場合、コンテナー内のサービスは、コンテナー自体の中以外からはアクセスできません。」

たぶんそれは答えが書かれていた時にそうであったが、今あなたが使用していない場合でも、と思われるEXPOSE--publishhostおよび他のcontainers同一ネットワークのあなたは、そのコンテナの内側に始めることができるサービスにアクセスすることができます。

これをテストする方法:

以下を使用しましたDockerfile。基本的に、私はubuntuから始めて、小さなWebサーバーをインストールします。

FROM ubuntu
RUN apt-get update && apt-get install -y mini-httpd

I build「testexpose」となどの画像runを使用して新しいコンテナ:

docker run --rm -it testexpose bash

コンテナ内で、次のインスタンスをいくつか起動しますmini-httpd

root@fb8f7dd1322d:/# mini_httpd -p 80
root@fb8f7dd1322d:/# mini_httpd -p 8080
root@fb8f7dd1322d:/# mini_httpd -p 8090

その後curl、ホストまたは他のコンテナからを使用して、のホームページを取得できますmini-httpd


16
これが正解です。受け入れられた答えは以前のバージョンに基づいているようです。
ルークW

curlに使用したホストポートは何ですか?
ブレインストーム

コンテナーのIP(など172.17.0.2)と言及しているすべてのポートを使用しました。Mac / Windows用のDockerを使用している場合、ネットワークは異なります。docker0橋はありません。
tgogos

「-P」フラグを使用してすべてのEXPOSEdポートを公開するとき、ホストで使用されているポートを確認するにはどうすればよいですか?
sixty4bit


9

公式ドキュメントリファレンスをご覧くださいhttps : //docs.docker.com/engine/reference/builder/#expose

EXPOSEあなたは、コンテナが動作しているときの画像ビルド時に公開する(コンテナ)プライベートとパブリック(ホスト)ポートを定義することを可能にする場合は、あなたがしてコンテナを実行します-P

$ docker help run
...
  -P, --publish-all                    Publish all exposed ports to random ports
...

パブリックポートとプロトコルはオプションです。パブリックポートが指定されていない場合、Dockerfileで指定されたコンテナーポートを公開するために、Dockerによってホスト上でランダムなポートが選択されます。

ホストごとに1つのコンテナーしか制限しないため、パブリックポートを指定しないことをお勧めします(2番目のコンテナーは既に使用されているポートをスローします)。

-pin docker runを使用して、公開されたコンテナーポートが接続可能なパブリックポートを制御できます。

とにかく、EXPOSE-Pdocker runで)を使用しない場合-p、ポートは公開されません。

常に使用-pするdocker run場合は必要ありませんが、コマンドEXPOSEを使用EXPOSEするdocker run方が簡単EXPOSEな場合があります。ホストでどのポートが公開されるかを気にしない場合、または1つのコンテナーのみがロードされることが確実な場合に役立ちます。


これは正しいです。DockerfileにEXPOSE portNumberがある場合は、-Pを指定してdocker runを呼び出すことを忘れないでください。
KunYu Tsai

6

DockerfileのEXPOSEキーワードまたはdocker runの--exposeフラグを使用してポートを公開します。ポートの公開は、どのポートが使用されているかを文書化する方法ですが、実際にポートをマップしたり開いたりするわけではありません。ポートの公開はオプションです。

ソース:github commit


3

ほとんどの人はネットワークでdocker composeを使用しています。ドキュメントの状態:

Dockerネットワーク機能は、ネットワーク内のポートを公開する必要のないネットワークの作成をサポートします。詳細については、この機能の概要を参照してください)。

つまり、コンテナー間の通信にネットワークを使用する場合、ポートの公開について心配する必要はありません。


-5

EXPOSEは、ローカルポートコンテナーポートをマップするために使用されます。

EXPOSE 8090

ローカルホストのポート8090をコンテナのポート8090にマッピングします

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.