taketiyo.log

Web Engineering 🛠 & Body Building 💪

【Docker Compose】ports / expose、書式別の挙動まとめ【version 3】

Programming

  / /

docker-compose.ymlに存在しているportsexposeのセクションですが、なんとなく理解はしていたものの今一度しっかりと見つめ直す機会があったので見返し用も兼ねて纏めました。

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ホスト側ポートへの接続を許可する接続元IPyyホスト側ポートzzコンテナ側ポートとなります。ホスト側のyy番ポートへのアクセスはIPxxからの接続のみ許可され、コンテナ側のzz番ポートとマッピングされます。
yyzzに関してはこちらも同様、-(ハイフン)を用いることでポート番号を範囲で指定することも可能です。
 
例)

ports:
  - '127.0.0.1:8080:80'
  - '127.0.0.1:10443:443'
  - '127.0.0.1:10001-10009:8081-8089'

上記例の場合、ホスト側のポート808010443及び10001-10009へのアクセスは127.0.0.1からの接続のみしか許可されません。つまりリバースプロキシ等、ループバックに対してのみ開くという事になります。

 

ports – セキュリティに関する留意点

portsセクションにて指定したホスト側ポートはDockeriptablesを操作してポートを開放します。
つまりCentOS7を利用している場合、Dockerfirewalldを介さずに直接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セクションでは明示的に文字列を表すため、基本的にはクオテーションで囲うことが推奨されています。