概要
dockerコンテナ内からlocalhostにアクセスしようとすると、アクセス先はコンテナ内になってしまいますよね。
でも、コンテナの外にあるホストOS上に他のサービスが立ち上がっていて、そのサービスにアクセスしたい場合って、きっとありますよね?(*´﹃`*)
(いつか図を書こう)
そんなときの対策。
結論
良さそうな方法は2つあるかなと思っています。
- container 内から
host.docker.internalにアクセスする (※ リモートサーバでは使えない) - localhostのIPアドレスをコンテナのネットワークに設定
それぞれ見ていきましょう。
1. container 内から host.docker.internal にアクセスする
host.docker.internal を使うと、 localhost へのアクセスとなるようです。動作検証してみます。
まず localhost 側で適当なサービスを起動します。
python3 -m http.server 80
ここに、 docker コンテナ内からアクセスしてみましょう。ローカルマシンの MacOS 上では以下のような結果が確認できました。
# curl host.docker.internal
<!DOCTYPE HTML>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Directory listing for /</title>
</head>
<body>
<h1>Directory listing for /</h1>
<hr>
<ul>
<li><a href=".env">.env</a></li>
<li><a href=".env.sample">.env.sample</a></li>
<li><a href=".gitignore">.gitignore</a></li>
<li><a href="docker-compose.yml">docker-compose.yml</a></li>
<li><a href="Dockerfile">Dockerfile</a></li>
<li><a href="requirements.txt">requirements.txt</a></li>
</ul>
<hr>
</body>
</html>
確かにいけますね。
ただ、これは本番環境用ではないと docker の公式ドキュメントに書かれているので、あくまでも実験環境用ですね。
Docker Desktop for Mac などの外では使えないようです。実際、リモートの EC2 上では確認できませんでしたし、おそらくリモートの Ubuntu サーバ上などでも使えないと思われます。
2. localhostのIPアドレスをコンテナのネットワークに設定
こっちは本番でも使えるかな、と思います。
次のコマンドで、HOST_IP_ADDRESSという環境変数にlocalhostのIPアドレスを設定できました。
$ export HOST_IP_ADDRESS=`ip -4 a show ens5 | 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"`
※ens5は、AWS EC2上においてlocalhostのIPアドレスを指す名前でした。
環境によってこの名前は異なるので、自身で$ ip aコマンドを打ってみて、どんな名前のブロックにlocalhostのIPアドレスがあるかを事前に確認してみましょう(^ワ^*)
たとえば、私のwsl2で実行してみたところ、ens5ではなくeth0でした。
2-1. このコマンドはどうやって生まれたか
2-1-1. 最初 (ifconfigコマンドを利用)
最初はこの記事に書かれている方法でlocalhostの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"`
172.000.000.255
2-1-2. 最終系 (ipコマンドを利用)
しかし、ifconfigコマンドは非推奨という次のような記事を見かけたので、
今度は、次の記事に書かれていた$ ip -4 a show ens4というコマンドを流用させていただきました。
スペースをちょっと書き換えて次のように修正したら、期待通りの動きになりました。
$ ip -4 a show ens5 | 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"
172.000.000.255
(正規表現あんまりわかってないので、偶然の産物です)
感想
元の記事からほんのちょっとしか書き換えてないけど、とはいえ、これだけのために結構時間を食ったので、記事にしておくことにしました(。ŏ﹏ŏ)
参考資料
--add-host
docker compose は使っていなくて、あくまでも docker 単体であれば、--add-host というオプションを使う方法もあるらしい。以下の記事で解説されていました。
色々な方法
自分は試していないけれども、以下の記事に色々な方法が書かれている。