host.docker.internalとは?

ローカル開発環境かどうかの判定

普段Railsを使って開発していると、環境の判定はRails.envで行うことができる。ローカル開発環境ではもちろん

1
2
3
irb(main):001:0> Rails.env
=> "development"
irb(main):002:0>

となる。

また、Rails.env == "development"としなくても

1
2
3
4
irb(main):002:0> Rails.env.development?
=> true
irb(main):003:0> Rails.env.production?
=> false

このように判定してくれるメソッドがある。

ところが、そうでないWebアプリケーションフレームワークもあるようで(ほんとにその機能がないかは定かではない)、ローカル開発環境かどうかの判定に

1
if 'host.docker.internal' in os.environ['S3_URL']:

という条件分岐を利用しているコードに出会った。

察しのいい方はわかると思いますが、S3にアクセスする際に、ローカルで稼働しているMinIOコンテナにアクセスすべきか、S3にアクセスすべきかの条件分岐のif文です。

この条件文が正しく動作せず苦労しました。

host.docker.internalについて

host.docker.internalというドメインが初見だったので調べてみると、Docker Desktop for xxで利用できる、コンテナから参照する場合のhostを指すドメインだということです。わたしの環境はDocker Desktop for Macを利用しているので利用できるはずです。

参考: コンテナからホスト上のサービスに対して接続したい

なるほど、であれば、コンテナからアクセスする際にhost.docker.internal:9000にアクセスすれば、コンテナからMinIOへアクセスできるはずですね。

host.docker.internalを利用する

先程のコードのようにS3_URLをhttp://host.docker.internal:9000とし、アプリケーションからファイルをPUTしてみました。

すると、正しくファイルをPUTできました。

host.docker.internalにアクセスできない場合

いろいろ調べてみるとhost.docker.internalというドメインにアクセスできないケースがあるようです。

その場合の対処法としては、docker-compose.ymlにextra_hostsの設定を行います。

extra_hosts

extra_hostsの説明は以下にありました。

https://docs.docker.jp/compose/compose-file/#extra-hosts

/etc/hostsに対してホストのマッピングを追加することができるようです。

対処法の例としては、hosts.docker.internalにアクセスするコンテナに対して

1
2
extra_hosts:
- "host.docker.internal:host-gateway"

を追加してくださいとのことです。host-gatewayはホストのアドレスになるようですね。

/etc/hostsの確認

extra_hostsを設定した状態でコンテナの/etc/hostsファイルを確認します

1
2
3
4
5
6
7
8
9
10
$ docker compose run --rm app /bin/bash
bash-4.2# 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
192.168.65.2 host.docker.internal
172.18.0.6 af51d5a15783

host.docker.internalのレコードが追加されていました。

まとめ

コンテナからホストにアクセスする際にはhost.docker.internalというドメインでアクセスできる。

host.docker.internalでアクセスできない場合は、extra_hostsを利用して明示的に/etc/hostsファイルにレコードを追加する。

参考図書