277
235

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

docker-compose の ports 指定まとめ

Last updated at Posted at 2019-02-23

前提

各種バージョン

$ docker.exe -v
Docker version 18.03.0-ce, build 0520e24302
$ docker-compose.exe -v
docker-compose version 1.20.1, build 5d8c71b2
$ docker-machine.exe ssh default 'docker -v'
Docker version 18.09.1, build 4c52b90
docker-compose.yml
version: '3'

ホストのIP

  • 192.168.99.100
  • 10.0.2.15
    • 172 始まりのIPは Docker が作成するので一旦無視する
docker@default:~$ ifconfig  | grep "inet addr"
          inet addr:172.19.0.1  Bcast:172.19.255.255  Mask:255.255.0.0
          inet addr:172.17.0.1  Bcast:172.17.255.255  Mask:255.255.0.0
          inet addr:10.0.2.15  Bcast:10.0.2.255  Mask:255.255.255.0
          inet addr:192.168.99.100  Bcast:192.168.99.255  Mask:255.255.255.0
          inet addr:127.0.0.1  Mask:255.0.0.0

対象プロトコル

  • IP v4
  • TCP
    • Dockerのportsでは TCPとUDP の両方を指定できるが、今回は TCP のみを対象とする。

検証方法

nginx を使用して コンテナ内にHTTP(80番port)サーバーを動かす。

docker-compose.yml
version: '3'

services:
  nginx:
    image: nginx:1.15
    ports:
      - "127.0.0.1:8080:80" # ここを変更していく

検証結果

1対1のport mapping

各ports指定の :o:, :x: は各URLへ curl でアクセスできるかの結果

"<Host IP>:<Host Port>:<Container Port>"

"127.0.0.1:8080:80"

host側のport使用状況
docker@default:~$ netstat -ant | grep -E "8080|State"
Proto Recv-Q Send-Q Local Address           Foreign Address         State
tcp        0      0 127.0.0.1:8080          0.0.0.0:*               LISTEN

"127.1.2.3:8080:80" 1

host側のport使用状況
docker@default:~$ netstat -ant | grep -E "8080|State"
Proto Recv-Q Send-Q Local Address           Foreign Address         State
tcp        0      0 127.1.2.3:8080          0.0.0.0:*               LISTEN

"192.168.99.100:8080:80"

ループバック 127.0.0.0/8 を指定した場合と違い、 192.168.99.0/24 ネットワークの他のホストからのアクセスを受け付けられるようになる。
※ Firewallなどで外からの通信が許可されている場合に限る2

host側のport使用状況
docker@default:~$ netstat -ant | grep -E "8080|State"
Proto Recv-Q Send-Q Local Address           Foreign Address         State
tcp        0      0 192.168.99.100:8080     0.0.0.0:*               LISTEN

"0.0.0.0:8080:80"

自ホスト宛の通信ならネットワーク・IPアドレスを問わず受け付けてコンテナに転送する

host側のport使用状況
docker@default:~$ netstat -ant | grep -E "8080|State"
Proto Recv-Q Send-Q Local Address           Foreign Address         State
tcp        0      0 :::8080                 :::*                    LISTEN

:x: "8.8.8.8:8080:80" 3

ホストが持っていないIPを指定するとエラーとなりコンテナを作成できない

$ docker-compose.exe up -d
Removing dockernginx_nginx_1
Recreating 0ad48208ae60_dockernginx_nginx_1 ... error

ERROR: for 0ad48208ae60_dockernginx_nginx_1  Cannot start service nginx: driver failed programming external connectivity on endpoint dockernginx_nginx_1 (ed3d7ae26be69b038d3896e637a0163449fa524a93ddfe98a5673190e7519e06): Error starting userland proxy: listen tcp 8.8.8.8:8080: bind: cannot assign requested address

ERROR: for nginx  Cannot start service nginx: driver failed programming external connectivity on endpoint dockernginx_nginx_1 (ed3d7ae26be69b038d3896e637a0163449fa524a93ddfe98a5673190e7519e06): Error starting userland proxy: listen tcp 8.8.8.8:8080: bind: cannot assign requested address
Encountered errors while bringing up the project.

"<Host Port>:<Container Port>" (<Host IP>:を省略した場合)

"8080:80"

host側のport使用状況
docker@default:~$ netstat -ant | grep -E "8080|State"
Proto Recv-Q Send-Q Local Address           Foreign Address         State
tcp        0      0 :::8080                 :::*                    LISTEN
docker-composeも0.0.0.0として認識している
$ docker-compose port nginx 80
0.0.0.0:8080

"<Container Port>" (<Host IP>:<Host Port>:を省略した場合)

"80"

  • <Host IP>: 0.0.0.0 を指定したとみなされる("<Host Port>:<Container Port>" 指定のときと同じ)
  • <Host Port>: 使用可能なポート番号(エフェメラルポート)をDockerが選択
    • コンテナを作り直した際に同一Port番号となることは保証されていない
コンテナ作成の都度port番号は変わる
$ docker-compose up -d --force-recreate; docker-compose port nginx 80
Recreating dockernginx_nginx_1 ... done
0.0.0.0:32777
$ docker-compose up -d --force-recreate; docker-compose port nginx 80
Recreating dockernginx_nginx_1 ... done
0.0.0.0:32778
$ docker-compose up -d --force-recreate; docker-compose port nginx 80
Recreating dockernginx_nginx_1 ... done
0.0.0.0:32779
$ docker-compose up -d --force-recreate; docker-compose port nginx 80
Recreating dockernginx_nginx_1 ... done
0.0.0.0:32780

範囲(Range)指定

"8080-8082:80-82"

範囲内のIPの数が同じなら <Host Port><Container Port> が1対1対応する

  • 0.0.0.0:8080->80
  • 0.0.0.0:8081->81
  • 0.0.0.0:8082->82
$ docker-compose ps
       Name                 Command          State                                Ports
---------------------------------------------------------------------------------------------------------------------
dockernginx_nginx_1   nginx -g daemon off;   Up      0.0.0.0:8080->80/tcp, 0.0.0.0:8081->81/tcp, 0.0.0.0:8082->82/tcp

"8080-8082:80"<Host Port> 側だけ範囲指定)

<Host Port> 側の範囲(8080, 8081, 8082)から使用可能なportをdockerが選択する。
<Host IP>:<Host Port>: を省略した "<Container Port>" 指定の動きに近い4

$ docker-compose up -d --force-recreate; docker-compose port nginx 80
Creating network "dockernginx_default" with the default driver
Creating dockernginx_nginx_1 ... done
0.0.0.0:8081
$ docker-compose up -d --force-recreate; docker-compose port nginx 80
Recreating dockernginx_nginx_1 ... done
0.0.0.0:8082
$ docker-compose up -d --force-recreate; docker-compose port nginx 80
Recreating dockernginx_nginx_1 ... done
0.0.0.0:8080
$ docker-compose up -d --force-recreate; docker-compose port nginx 80
Recreating dockernginx_nginx_1 ... done
0.0.0.0:8081
$ docker-compose up -d --force-recreate; docker-compose port nginx 80
Recreating dockernginx_nginx_1 ... done
0.0.0.0:8082

いつ使うか?(<Host Port> 側だけ範囲指定できることの嬉しさ)

--scale オプションを指定して、(1種類のServiceで)2つ以上のコンテナを作成するとき。

portを1対1(例: "8080:80")で指定しているときに --scale オプションを使用して2つ以上のコンテナを作成するとport重複によって1つしかコンテナを作成できない

1対1指定したときはscaleオプションで2つ以上のコンテナを作成できない
$ docker-compose up -d --scale nginx=2
Creating network "dockernginx_default" with the default driver
The "nginx" service specifies a port on the host. If multiple containers for this service are created on a single host, the port will clash.
Creating dockernginx_nginx_1 ... error
Creating dockernginx_nginx_2 ... done

ERROR: for dockernginx_nginx_1  Cannot start service nginx: driver failed programming external connectivity on endpoint dockernginx_nginx_1 (8f55e9f086d4beea21daf076a731d998f6ec8440df4b28c99fb4f1a97272164d): Bind for 0.0.0.0:8080 failed: port is already allocated

ERROR: for nginx  Cannot start service nginx: driver failed programming external connectivity on endpoint dockernginx_nginx_1 (8f55e9f086d4beea21daf076a731d998f6ec8440df4b28c99fb4f1a97272164d): Bind for 0.0.0.0:8080 failed: port is already allocated
Encountered errors while bringing up the project.
$ docker-compose ps
       Name                 Command           State            Ports
----------------------------------------------------------------------------
dockernginx_nginx_1   nginx -g daemon off;   Exit 128
dockernginx_nginx_2   nginx -g daemon off;   Up         0.0.0.0:8080->80/tcp

<Host Port> 側を範囲指定(例: "8080-8082:80")しておけば --scale オプションを使用して2つ以上のコンテナを作成してもport重複が発生せずコンテナの作成が成功する。

portを範囲指定していればscaleオプションで2つ以上のコンテナを作成できる
$ docker-compose up -d --scale nginx=3
Creating network "dockernginx_default" with the default driver
The "nginx" service specifies a port on the host. If multiple containers for this service are created on a single host, the port will clash.
Creating dockernginx_nginx_1 ... done
Creating dockernginx_nginx_2 ... done
Creating dockernginx_nginx_3 ... done
$ docker-compose ps
       Name                 Command          State          Ports
-------------------------------------------------------------------------
dockernginx_nginx_1   nginx -g daemon off;   Up      0.0.0.0:8081->80/tcp
dockernginx_nginx_2   nginx -g daemon off;   Up      0.0.0.0:8082->80/tcp
dockernginx_nginx_3   nginx -g daemon off;   Up      0.0.0.0:8080->80/tcp

※ コンテナの番号とport番号の順序は一致するとは限らないらしい

  • 1 -> 8081
  • 2 -> 8082
  • 3 -> 8080

ちなみに、範囲の長さより少ないscale数を指定することも可能5

$ docker-compose up -d --scale nginx=2
Creating network "dockernginx_default" with the default driver
The "nginx" service specifies a port on the host. If multiple containers for this service are created on a single host, the port will clash.
Creating dockernginx_nginx_1 ... done
Creating dockernginx_nginx_2 ... done
$ docker-compose ps
       Name                 Command          State          Ports
-------------------------------------------------------------------------
dockernginx_nginx_1   nginx -g daemon off;   Up      0.0.0.0:8082->80/tcp
dockernginx_nginx_2   nginx -g daemon off;   Up      0.0.0.0:8081->80/tcp

:x: "8080:80-82"

コンテナ側の範囲の長さの方が多い指定は許されない

$ docker-compose up -d
The Compose file '.\docker-compose.yml' is invalid because:
services.nginx.ports is invalid: Port ranges don't match in length

:x: "8080-8082:80-89"

同上。

$ docker-compose up -d
The Compose file '.\docker-compose.yml' is invalid because:
services.nginx.ports is invalid: Port ranges don't match in length

:x: "8080-8089:80-82"

<Host Port><Container Port> の範囲の長さが異なる場合も許されない

$ docker-compose up -d
The Compose file '.\docker-compose.yml' is invalid because:
services.nginx.ports is invalid: Port ranges don't match in length

"80-82"

"<Container Port>" (<Host IP>:<Host Port>:を省略した場合) と同じく、コンテナ側の 80, 81, 82 をホスト側の空きportに適当に割り当てる

$ docker-compose up -d --force-recreate; docker-compose ps
Creating network "dockernginx_default" with the default driver
Creating dockernginx_nginx_1 ... done
       Name                 Command          State                                  Ports
------------------------------------------------------------------------------------------------------------------------
dockernginx_nginx_1   nginx -g daemon off;   Up      0.0.0.0:32814->80/tcp, 0.0.0.0:32813->81/tcp, 0.0.0.0:32812->82/tcp
$ docker-compose up -d --force-recreate; docker-compose ps
Recreating dockernginx_nginx_1 ... done
       Name                 Command          State                                  Ports
------------------------------------------------------------------------------------------------------------------------
dockernginx_nginx_1   nginx -g daemon off;   Up      0.0.0.0:32817->80/tcp, 0.0.0.0:32816->81/tcp, 0.0.0.0:32815->82/tcp
$ docker-compose up -d --force-recreate; docker-compose ps
Recreating dockernginx_nginx_1 ... done
       Name                 Command          State                                  Ports
------------------------------------------------------------------------------------------------------------------------
dockernginx_nginx_1   nginx -g daemon off;   Up      0.0.0.0:32820->80/tcp, 0.0.0.0:32819->81/tcp, 0.0.0.0:32818->82/tcp
$ docker-compose up -d --force-recreate; docker-compose ps
Recreating dockernginx_nginx_1 ... done
       Name                 Command          State                                  Ports
------------------------------------------------------------------------------------------------------------------------
dockernginx_nginx_1   nginx -g daemon off;   Up      0.0.0.0:32823->80/tcp, 0.0.0.0:32822->81/tcp, 0.0.0.0:32821->82/tcp

"80-80" (範囲の始まりと終わりが同じ番号)

"80" 指定と同じ。

:x: "127.0.0.1-5:8080:80"

<Host IP> 部分に範囲指定はできない

$ docker-compose up -d
The Compose file '.\docker-compose.yml' is invalid because:
services.nginx.ports is invalid: Invalid port "127.0.0.1-5:8080:80", should be [[remote_ip:]remote_port[-remote_port]:]port[/protocol]

:x: "127.0.0.1-5:8080-8085:80"

同上

$ docker-compose up -d
The Compose file '.\docker-compose.yml' is invalid because:
services.nginx.ports is invalid: Invalid port "127.0.0.1-5:8080-8085:80", should be [[remote_ip:]remote_port[-remote_port]:]port[/protocol]

参考ページ

  1. 127始まり(第一オクテットが127)のIP(例: 127.1.2.3)も 127.0.0.1 にように使える。port番号で区別しなくて良いので便利。 2 3 4 5

  2. Windows(Docker Desktop for Windows) の場合、Windowsのファイアウォール設定上では vpnkit を許可すると別ホストからのアクセスが可能となる。Linuxの場合、Dockerはiptablesの設定を書き換えるため意図しない公開に注意(参考: Dockerでマストドンやってたら、遮断したはずのポートが丸見えだった件 | Divide et impera

  3. 8.8.8.8 はGoogleの所有するIPアドレス。Google Public DNS として公開されている。

  4. "80" 指定は(Boot2Docker の TinyCoreLinuxの場合) "32768-60999:80" 指定と同じだと考えらられる

  5. 逆に、port範囲の長さより多いscale数を指定したら、port重複でコンテナは(一部)作成されない
    この場合、使われないport番号が生じる(どれが使われないかは不定)。

277
235
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
277
235

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?