docker-compose.yml
に存在しているports
とexpose
のセクションですが、なんとなく理解はしていたものの今一度しっかりと見つめ直す機会があったので見返し用も兼ねて纏めました。
Dockerって何、Docker Composeって何という話はこの記事では触れていません。
目次
ports – 書式の種類
ports
のセクションには大きく分けて下記3つの書式が存在しています。
xx
形式xx:yy
形式xx:yy:zz
形式
ports – 書式による挙動の違い
ports
はホスト側のポートとコンテナ側のポートをマッピングするためのセクションですが、書式の違いによって下記の通り異なった挙動をとります。
xx
形式
この形式はコンテナ側のポート番号のみを指定する書式です。指定されたコンテナ側ポートがホスト側のランダムなポートとマッピングされます。
-(ハイフン)
を用いることでポート番号を範囲で指定することも可能です。
例)
ports:
- '3000'
- '8080'
- '3000-3010'
xx:yy
形式
この形式はホスト側のポートとコンテナ側のポートの双方を指定する書式です。xx
がホスト側ポート
、yy
がコンテナ側ポート
となり、ホスト側のxx
番ポートとコンテナ側のyy
番ポートがマッピングされます。
こちらも同様、-(ハイフン)
を用いることでポート番号を範囲で指定することも可能です。
例)
ports:
- '8080:80'
- '10443:443'
- '10001-10009:8081-8089'
xx:yy:zz
形式
この形式はホスト側のポート、コンテナ側のポート、更にホスト側ポートへの接続を許可する接続元IPを指定する書式です。xx
が ホスト側ポートへの接続を許可する接続元IP、yy
がホスト側ポート
、zz
がコンテナ側ポート
となります。ホスト側のyy
番ポートへのアクセスはIPxx
からの接続のみ許可され、コンテナ側のzz
番ポートとマッピングされます。
yy
、zz
に関してはこちらも同様、-(ハイフン)
を用いることでポート番号を範囲で指定することも可能です。
例)
ports:
- '127.0.0.1:8080:80'
- '127.0.0.1:10443:443'
- '127.0.0.1:10001-10009:8081-8089'
上記例の場合、ホスト側のポート8080
、10443
及び10001-10009
へのアクセスは127.0.0.1
からの接続のみしか許可されません。つまりリバースプロキシ等、ループバックに対してのみ開くという事になります。
ports – セキュリティに関する留意点
ports
セクションにて指定したホスト側ポートはDocker
がiptables
を操作してポートを開放します。
つまりCentOS7
を利用している場合、Docker
はfirewalld
を介さずに直接iptables
を操作しポートを開放するため、firewalld
で開放していないポートが予期せず開放されてしまい、セキュリティインシデントとなります。
例えばports
セクションにて10443:443
と記述した場合、ホスト側の10443
番ポートはfirewalld
の設定にかかわらず外部から誰でも接続可能な状態になってしまいます。これが予期した挙動であれば構いませんが、ループバックからの接続のみを想定した設定である場合127.0.0.1:10443:443
のようにホスト側ポートへの接続元IPにローカルホストを必ず指定するべきです。
expose – 書式の種類
expose
セクションの書式は下記の1種類しか存在しません。
xx
形式
expose – 挙動
expose
はコンテナ側のポートを指定します。指定されたコンテナ側のポートはホストマシンには公開されず、仮想ブリッジであるdocker0
にのみ晒されます。
晒されたコンテナ側のポートへは、リンクされたサービスからのみアクセスが可能です。
例)
expose:
- '3306'
- '8080'
余談
本来yaml
ファイルにおける文字列はクオーテーションで囲わずとも文字列と判定されますので、ポート番号の定義は'8080:80'
とせず8080:80
でも構わないのですが、上記例において全てクオーテーションで囲っているのは、Yamlパーサーがxx:yy
形式の数字を60進数として解釈してしまう場合があるためです。これはコンテナ側のポート番号に60以下を指定した際に起こる可能性があります。そのためports
セクションでは明示的に文字列を表すため、基本的にはクオテーションで囲うことが推奨されています。