#
ドキュメント

Document

自分のための備忘録です。

ブリッジネットワークに外部から接続

Ref.

Docker ポート関連コマンド/命令

EXPOSE

EXPOSE 命令だけは、実際にはポートを 公開publish しません。これは、どのポートを公開する意図なのかという、イメージの作者とコンテナ実行者の両者に対し、ある種のドキュメントとして機能します。コンテナの実行時に実際にポートを公開するには、 docker run で -p フラグを使い、公開用のポートと割り当てる( マップmap する)ポートを指定します

-- https://docs.docker.jp/engine/reference/builder.html#expose

EXPOSE命令はホスト側のポートを開けません。
ホスト側のポートを開けるには、docker runならp/Pオプションで明示的に指定します。
(ホスト側で既に稼働しているポート番号をホスト側のポート番号に指定することはできません。)

httpdの例を記載します。

ホストのポート8000番を開けます。
コンテナはポート80番でリッスンすることがhttpd:latestEXPOSEで明記されています[^port][port2]。

$ sudo docker run -p '8000:80' httpd:latest

[^port2]:-p xx:xxのホスト側ポート番号に既に使用されているポート番号を指定することはできません。例えばホストでWebサーバが80番で起動している場合に-p 80:80を指定してコンテナを起動するとポートのpublishに失敗します。

docker run

Pオプション

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

対応するホスト側のポートはDockerが自動で割り当てます。

pオプション

-p, --publish list Publish a container's port(s) to the host -- docker run --help

docker compose

Dockerfileでportsプロパティを指定します。

version: '3'

services:
  app:
    image: httpd:latest
    volumes:
      - ./html:/var/www/html
    ports:
      - "8000:80"

例:httpd

httpd:latestEXPOSE80が指定されています。
203.0.113.100でコンテナを公開する場合の動作を確かめます。

$ docker run -d httpd:latest

上記コマンドではhttp://203.0.113.100にアクセスできません[^curl]。
以下のとおりホストのポート番号80が閉じていることがわかります。

$ nmap 127.0.0.1 -Pn -p 80
...
PORT   STATE  SERVICE
80/tcp closed http
...

[^curl]: コンテナ内では、httpdがポート80番でリッスンしています。docker execでコンテナにログインして$ curl -v 127.0.0.1でHTMLドキュメントを取得できます。

http://203.0.113.100にアクセスできるようにするには-pオプションを使ってpublishする必要があります。
ホストのポート80番をコンテナのポート80番に対応させてpublishします。

$ docker run -d -p '80:80' httpd:latest

ホストでポート番号80の状態を確認します。
ホストのポート番号80が開いています。

$ nmap 127.0.0.1 -Pn -p 80
...
PORT   STATE SERVICE
80/tcp open  http
...

ポート公開(publish)

docker runp/Pオプション、docker composeportsプロパティでホストのポートをpublishすると、Dockerデーモンによってiptablesが変更されます。

publishしない場合のiptables

$ docker run -d httpd:latest
$ iptables -L
....
Chain DOCKER (3 references)
target     prot opt source               destination
...

publishする場合のiptables

$ docker run -d -p '80:80' httpd:latest
$ iptables -L -n
...
Chain DOCKER (4 references)
target     prot opt source               destination
ACCEPT     tcp  --  0.0.0.0/0            172.18.0.2           tcp dpt:80
...

Dockerはネットワーク172.18.0.280番をオープンします。 ホスト80番をオープンするわけではありません。

$ docker run -d --net sample2 -p 80 --name web-httpd httpd
  • pオプションがxx:xxではなくxxと単独でしていされた場合はコンテナのポート番号を表します
  • Dockerはiptablesでネットワークsample280番を開けます^expose
  • ホストのポート番号を開くわけではありません

ホストのポート番号は以下のように調べることができます。

$  docker port web-httpd 80
0.0.0.0:49157
:::49157
$ iptables -L -n
Chain DOCKER (4 references)
...
target     prot opt source               destination
ACCEPT     tcp  --  0.0.0.0/0            172.18.0.2           tcp dpt:80
ACCEPT     tcp  --  0.0.0.0/0            172.19.0.2           tcp dpt:80
...

49157を開けるわけではありません。

代替ポート番号

https://www.fe-siken.com/kakomon/01_aki/q34.html

ホスト側ポート番号(doker port)

$ docker port {{container}} {{port}}

コンテナのポート番号がホストのどのポート番号に割り当てられているかを確認します。