これは、なにをしたくて書いたもの?
Docker Desktopには、host.docker.internal
というホスト側のIPアドレスを参照する仕組みがあるようです。
Docker Desktopを使っていないので全然知らなかったのですが、Docker Engine(使っているのはLinux版)でもひと手間加えると使えるようなので、
ちょっと試してみることにしました。
コンテナからホスト側のを参照できるhost.docker.internal
Windows版のhost.docker.internal
の説明を見てみます。
host.docker.internal
はホストの内部IPアドレスを解決する特別な名前です。Docker Desktop for Windows以外の本番環境では機能しないとも
書かれています。
We recommend that you connect to the special DNS name host.docker.internal which resolves to the internal IP address used by the host. This is for development purpose and will not work in a production environment outside of Docker Desktop for Windows.
macOS版とLinux版ではどうなのでしょう。書かれていることは、ほぼ同じです。
とはいえ、Linux版のDocker Desktopは最近出てきたばかりのものですが。
The Magic of Docker Desktop is Now Available on Linux | Docker
[速報]「Docker Desktop for Linux」が登場、WindowsやMac版と同じ機能や操作を提供、Raspberry Pi OSにも対応 - Publickey
LinuxでDocker Engineしか使っていない自分は、host.docker.internal
の存在をまったく知りませんでした。
ところで、リリースノートを見ていると、Docker Engineでも20.10.0からhost.docker.internal
が使えるようになったみたいです。
Docker Engine release notes / 20.10.0
Support host.docker.internal in dockerd on Linux moby/moby#40007
Docker Engine release notes / 20.10.0 / Networking
というわけで、ちょっと試してみます。
環境
今回の環境は、こちら。
$ docker version Client: Docker Engine - Community Version: 20.10.16 API version: 1.41 Go version: go1.17.10 Git commit: aa7e414 Built: Thu May 12 09:17:23 2022 OS/Arch: linux/amd64 Context: default Experimental: true Server: Docker Engine - Community Engine: Version: 20.10.16 API version: 1.41 (minimum version 1.12) Go version: go1.17.10 Git commit: f756502 Built: Thu May 12 09:15:28 2022 OS/Arch: linux/amd64 Experimental: false containerd: Version: 1.6.4 GitCommit: 212e8b6fa2f44b9c21b2798135fc6fb7c53efc16 runc: Version: 1.1.1 GitCommit: v1.1.1-0-g52de29d docker-init: Version: 0.19.0 GitCommit: de40ad0
Docker Composeも。
$ docker compose version Docker Compose version v2.5.1
host.docker.internalを使ってみる
まずは、ホスト側の準備をします。
ドキュメントに習って、Python組み込みのWebサーバーを使いましょう。
ファイルの作成とWebサーバーの起動。
$ echo 'from host' > message.txt $ python3 -m http.server
確認。
$ curl localhost:8000/message.txt from host
このWebサーバーに、コンテナ側からアクセスしたい、という話です。
コンテナを起動。
$ docker container run -it --rm ubuntu:20.04 bash root@6b4790b61308:/#
curl
をインストール。
# apt update && apt install -y curl
ホスト側へアクセスを試みます。
# curl host.docker.internal:8000/message.txt curl: (6) Could not resolve host: host.docker.internal
ホスト名が解決できない、と言われました。
/etc/hosts
にも、確かに登録されていませんね。
# cat /etc/hosts 127.0.0.1 localhost ::1 localhost ip6-localhost ip6-loopback fe00::0 ip6-localnet ff00::0 ip6-mcastprefix ff02::1 ip6-allnodes ff02::2 ip6-allrouters 172.17.0.2 6b4790b61308
リリースノートに載っていたPull Requestを見てみると、--add-host=host.docker.internal:host-gateway
というオプションが必要なようです。
というわけで、コンテナを1度終了して
$ docker container run -it --rm --add-host=host.docker.internal:host-gateway ubuntu:20.04 bash root@90f41cf6f930:/#
curl
をインストール。
# apt update && apt install -y curl
今度は、host.docker.internal
でホスト側にアクセスできるようになります。
# curl host.docker.internal:8000/message.txt from host
/etc/hosts
にも、host.docker.internal
が増えています。
# cat /etc/hosts 127.0.0.1 localhost ::1 localhost ip6-localhost ip6-loopback fe00::0 ip6-localnet ff00::0 ip6-mcastprefix ff02::1 ip6-allnodes ff02::2 ip6-allrouters 172.17.0.1 host.docker.internal 172.17.0.2 90f41cf6f930
確認できましたね。
ホストのIPアドレスは、Docker Daemonに--host-gateway-ip
オプションを使うことで明示的な指定もできるようです。
--add-host=host.docker.internal:host-gateway
をデフォルトで付与するように設定できないのかな?とも思いましたが、現時点では
そのような話にはなっていないみたいですね。
Docker Composeでhost.docker.internalを使う
最後に、host.docker.internal
をDocker Composeでも使ってみましょう。
Docker Composeの場合は、extra_hosts
を使います。
extra_hosts
は、コンテナにホスト名のマッピングを追加する設定です(Linuxなら/etc/hosts
を利用)。
extra_hosts adds hostname mappings to the container network interface configuration (/etc/hosts for Linux). Values MUST set hostname and IP address for additional hosts in the form of HOSTNAME:IP.
Compose specification / Services top-level element / extra_hosts
サンプルとして、こんな定義で作成。
compose.yaml
services: infinispan1: image: infinispan/server:13.0.10.Final extra_hosts: - "host.docker.internal:host-gateway" infinispan2: image: infinispan/server:13.0.10.Final extra_hosts: - "host.docker.internal:host-gateway"
起動して
$ docker compose up
確認。
$ docker compose exec infinispan1 bash -c 'cat /etc/hosts | grep host.docker.internal' 172.17.0.1 host.docker.internal $ docker compose exec infinispan2 bash -c 'cat /etc/hosts | grep host.docker.internal' 172.17.0.1 host.docker.internal
host.docker.internal
を使った確認自体は、省略します。
また、compose.yaml
からextra_hosts
、host.docker.internal:host-gateway
の定義を削除すると、当然ですがhost.docker.internal
は
/etc/hosts
に登録されなくなります。
これで、今回の確認はOKとしましょう。
まとめ
host.docker.internal
を使って、コンテナからホスト側のサービスにアクセスしてみました。
使い方には注意した方がいい気がしますが、知っておくとそれはそれで便利なのかな、と。