問題点
Docker
で起動したコンテナ内からホストOS(ローカルPC)内のプロセスと通信する際に、
localhost
と指定しがちだけど localhost
だとコンテナ内を指してしまい、
意図した通りに通信することができない。
例えば、ホストOS上で 80ポートで Listen
している Nginx
が起動していて、
コンテナ内のプログラムから http://localhost:80
でアクセスしても接続できない。
これは通常のプロセスだけじゃなく、docker で複数のコンテナを起動して、
コンテナ同士で通信する場合も同じように接続できない。
解決方法
その1:ホストOSのIPアドレスを指定する
ホストOSのIPアドレスが 192.168.11.1
だとして、http://192.168.11.1:80
でアクセスするようにする。
その2:dockerコマンドの引数で指定する
Dockerで/etc/hostsファイルが操作出来ない対策 で紹介されているように
docker run
コマンドの引数(--add-host=[]
)でホスト名とIPアドレスの紐付けをコンテナに認識させ、
アクセスするときにそのホスト名を使用する。
docker run --add-host=local_dev:192.168.11.1 ・・・
で起動したときに、http://local_dev:80
でアクセスする
その3:docker-compose.yml
で指定する
docker run
の --add-host=[]
と同じことが docker-compose.yml
の extra_hosts
でもできる
extra_hosts:
- "local_dev:192.168.11.1"
その4:docker-compose.yml
で指定 + 環境変数を使う
DHCPなどでIPアドレスが変わる可能性がある場合、変わるたびに docker-compose.yml
を変更する必要があるので
自IPアドレスを環境変数に入れるとその手間が省ける。
以下のコマンドを .bashrc
か .bash_profile
に記述し、
export LOCAL_HOST_IP=`ifconfig en0 | grep inet | grep -v inet6 | sed -E "s/inet ([0-9]{1,3}.[0-9]{1,3}.[0-9].{1,3}.[0-9]{1,3}) .*$/\1/" | tr -d "\t"`
docker-compose.yml
を以下のように変更する。
extra_hosts:
- "local_dev:$LOCAL_HOST_IP"
ただし、このコマンドはMacでしか確認してしてなくて、他のOSではどのようにやれば良いかは確認していない。
その5:host.docker.internal
を使う (2019/09/16追記、2022/05/12編集)
Docker Desktop for Mac や Docker Desktop for Windows、Docker Desktop for Linux (2022/05/10 release ) でしか使えませんが、ゲストOS内からDNS名に host.docker.internal
を指定するとホストOSにアクセスできる。
- Networking features in Docker Desktop for Mac
- Networking features in Docker Desktop for Windows
- Networking features in Docker Desktop for Linux
その6:gateway.docker.internal
を使う(2022/02/13追記)
「その5」で紹介した host.docker.internal
は開発用途らしく、こっちの方が良さそう。
と、Dockerの公式に載っていた。
使っているDockerのバージョンにもよるかも。
まとめ
個人的には「その6 その5 その4」がよいかなと思うけど、
使う環境によって、できること・できないことあるので、
その時々でベストなものを選択してもらえたらよいかなと思う。