まず前提として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を作って同一のネットワークに所属するように設定すること(っていうかあんまりデフォルトブリッジネットワークを使用しない方がいいとのこと)

てな感じかな