Docker (3) - expose -
まず前提として2つのnginxサーバーをDockerコンテナを使って起動する。あえてnginxの設定とかは省略するが
Server A(リバースプロキシ側)
docker run -d -p 80:80 -t server-a
Server B(バックエンド側)
docker run -d -p 8080:80 -t server-b
というようにServer AからServer Bにリバースプロキシをするように設定した場合、通常であればバックエンド側は外部からはアクセスできないはずだ。しかし
kinjouj@kinjouj-pc:/home/kinjouj:$ curl http://192.168.1.100
server b
# おい!!!
kinjouj@kinjouj-pc:/home/kinjouj:$ curl http://192.168.1.100:8080
server b
まあリバースプロキシでポート指定無しなところでアクセスできるのはそれはわかるがなんでバックエンドまで普通に外部からアクセスできるのかっていうこと
-pを使ってコンテナポートとホストポートだけをマッピングしてしまうとそれが全面公開設定になってしまう模様なので上記のようにServer B側で8080をホストでマッピングしてると外部からでも普通にアクセスできちゃうっていうらしい
でそれを解決する方法としてコンテナポートのみを開放する方法があるのでそれをやってみる
docker networkでDocker Networkを作成
docker network create --subnet 172.16.0.0/16 --attachable mynet
mynetっていう名前でDocker Networkを作成する。どうやらDockerでコンテナを作成した際に使用されるDocker Networkはおそらく最初からあるbridgeを使用するらしいのだがこのbridgeネットワークどうやらDNSによる名前解決を行わないらしい
なので新しくDocker Networkを作成して以下で作るコンテナで同一のネットワークを使用するように起動する
Server Bの起動
docker run --name server-b -d --expose=8080 --net=mynet -t server-b
--nameでコンテナに名前をつける。これはServer Aでproxy_passを指定する際にコンテナ名で指定できるようになるのでそれを利用するためにコンテナ名を指定しておく。-pではなく--exposeでコンテナポートを開放、んで--netでそのコンテナが所属するネットワークを指定
Server A側のnginx.conf
listen 80;
server_name localhost;
location / {
proxy_pass http://server-b;
proxy_redirect off;
}
上記で指定したコンテナ名をproxy_passに指定することができる。ただし同一のDocker Networkに所属してないとhost not found in upstreamって言われるので注意
Server Aを起動
docker run -p 80:80 --net=mynet -t server-a
接続できるかやってみる
kinjouj@kinjouj-pc:/home/kinjouj:$ curl http://192.168.1.100
server b
kinjouj@kinjouj-pc:/home/kinjouj:$ curl http://192.168.1.100:8080
curl: (28) Connection timed out after 1001 milliseconds
以上!長い!ややこしい!
んまあ安直に-pオプションでポートオープンにするのは止めようねっていうオチなんかなと
まとめ
安易に-pを使用しない
コンテナ間で通信するならDocker Networkを作って同一のネットワークに所属するように設定すること(っていうかあんまりデフォルトブリッジネットワークを使用しない方がいいとのこと)
てな感じかな