状況
- Docker for Macを使っている(Docker version 1.13.0)
- ホストOSのローカル環境でRails製のAPIサーバーを動かしている(以下、APIサーバーと呼ぶ)
- Dockerコンテナ内で別のRailsアプリが動いており、このRailsアプリからホストOSで動いているAPIサーバーのAPIにアクセスしたい(以下、コンテナAと呼ぶ)
- コンテナAからAPIサーバーにcurlでアクセスできれば良いので、curlでアクセスできるようにしたい
- | エンドポイント |
---|---|
APIサーバー | http://localhost:3000/items/ |
コンテナAのRailsアプリ | ホストOSでは http://localhost:3001/ (コンテナ内では http://localhost:3000/ ) |
何も考えずにコンテナAからcurlでAPIのエンドポイントにアクセスすると、当然ですがコンテナAのRailsアプリのコンテンツが返されます。
$ curl http://localhost:3000/items/
じゃあどうすれば良いのか?
解決方法
ホストOSのAPIサーバーにアクセスするには、ホストOSのIPアドレスを指定する必要があります。
しかし、コンテナA内でlocalhostと指定するとコンテナA自身を指定することになります。
それではどのIPアドレスを指定するかというと、ホストOS側で独自のIPアドレスを設定する必要があります。
独自IPアドレスの設定方法
ホストOSにて
ifconfigコマンドを使います。
ifconfigはネットワーク・インタフェースの参照・設定・起動・停止などを行うコマンドです。
以下のようにlo0に対してipの設定を行います。
ところでlo0とは
lo0はloopback(ループバック)のことです。
ループバックアドレス
同じコンピュータ内部のプログラム間で通信したい場合に利用されるのがループバックアドレスです。ループバックアドレスとしては127.0.0.1というIPアドレスが使われます。この127.0.0.1と同じ意味で、localhostというホスト名も利用されます。このアドレスを利用した場合、パケットはネットワークには流れません。
ホストOSにて$ ifconfig lo0
とするとinet 127.0.0.1 netmask 0xff000000
とあるように、ここで127.0.0.1(localhost)が設定されていることがわかります。
ここから設定
話を戻して、ここから設定に入ります。
こちらの「I want to connect from a container to a service on the host」を参考にし、独自のIPアドレスを設定します。
$ sudo ifconfig lo0 alias 10.200.10.1/24
ifconfigで確認します。
$ ifconfig lo0
lo0: flags=8049<UP,LOOPBACK,RUNNING,MULTICAST> mtu 16384
options=3<RXCSUM,TXCSUM>
inet6 ::1 prefixlen 128
inet 127.0.0.1 netmask 0xff000000
inet6 fe80::1%lo0 prefixlen 64 scopeid 0x1
inet 10.200.10.1 netmask 0xffffff00 <-- ここの行が追加された -->
nd6 options=1<PERFORMNUD>
以下の設定が追加されていればOKです。
inet 10.200.10.1 netmask 0xffffff00
コンテナAにて
以下のようにcurlを実行するとAPIにアクセスできるはずです。
$ curl http://10.200.10.1:3000/items/
これで、コンテナAからホストOSのAPIサーバーにアクセスできるようになりました。
※ちなみにここで設定した独自IPアドレスの設定は、Macを再起動するとリセットされるので、再起動時は毎回手で設定し直す必要があります。さすがに面倒くさいので、Macの起動時に自動的に設定する方法を探すとログインフックという仕組みがありましたので、設定しておくと便利だと思います(MacOSXのログインフック設定)。
補足(独自のドメインを設定している場合)
ホストOSのlocalhostに対して、/etc/hostsで独自のドメインを設定している場合です。
例えば、localhostにlocal-hoge.comというホスト名でアクセスできるように設定しているとします。
コンテナAにて以下のコマンドを実行すると、
$ curl http://local-hoge.com/items/
curl: (6) Couldn't resolve host 'local-hoge.com'
となりホストの解決ができません。
そこでコンテナAの/etc/hostsに以下のような設定を追加するとホストの解決ができるようになり、アクセスできるようになります。
$ vi /etc/hosts
(以下を追記)
10.200.10.1 local-hoge.com
またはコンテナ起動時(docker run時)に以下のようにオプションを指定すると追加できます。
--add-host=local-hoge.com
Docker Composeを使っているなら、docker-compose.ymlに以下のように指定すると追加できます。
extra_hosts:
- local-hoge.com