はじめに
開発を行う際、自身のPCに色々(e.g. Java, Docker, Redis, etc...)起動するかと思います。
その中でも、ローカルに起動したDockerコンテナから、同ホスト上に Dockerを使わず 起動したもアプリケーションにアクセスしたくなりました。
OSがCentOSやUbuntuであれば、
- Docker コンテナ内からホストのIPアドレスを知る
- Windows + VirtualBox + Docker で動作しているコンテナからホスト OS へのアクセス
から分かるアドレスへアクセスできるのですが、どうもMac
だとうまく行きません。
筆者は基本Mac
を使って開発しているので、「なんとかしたい」ということでなんとかしてみました。
環境
項目 | value |
---|---|
端末 | Mac Book Pro (13-inch, 2016, Four Thunderbolt 3 Ports) |
プロセッサ | 3.3 GHz Intel Core i7 |
メモリ | 16 GB 2133 MHz LPDDR3 |
OS | macOS Sierra (ver.10.12.3) |
Docker | Docker for Mac |
準備
Dockerコンテナ
今回はDockerからホスト上のアプリケーションにリクエストを投げるので、特にWebサーバは起動しない単純構成とさせていただきます。
ということで、今回使用したDockerfileはこちらになります。
FROM ubuntu:16.04
RUN apt-get update -y && apt-get install -y dnsutils iproute2 iputils-ping curl
あとで使いますが、もうbuild
してrun
しておきましょう。
$ docker build -t request-to-host .
$ docker run -it --rm request-to-host /bin/bash
ホスト上アプリケーション
アクセスが確認できさえすれば良いので、今回は簡素なDjangoアプリケーションを立てておきます。
$ python install django
$ djang-admin startproject host
$ cd host
$ python manager.py runserver
===> Starting development server at http://127.0.0.1:8000/
ホスト上のアプリケーションを求めて
さて、今回の本題です。
コンテナからホスト上アプリケーションにアクセスするためには、
まずコンテナからホストがどのように認識されているかを調べる必要があります。
ipコマンド
ここやここにもあるように、コンテナからホストのアドレスを知るためにはip
コマンドが使えます。
$ ip r
===> default via 172.17.0.1 dev eth0
===> 172.17.0.0/16 dev eth0 proto kernel scope link src 172.17.0.2
上記のdefault
にあたる部分にコンテナから見たホストのアドレスにあたります。
これでホストに・・・
では実際にアクセスしてみます。
$ ping 172.17.0.1
===> PING 172.17.0.1 (172.17.0.1) 56(84) bytes of data.
===> 64 bytes from 172.17.0.1: icmp_seq=1 ttl=64 time=0.113 ms
===> 64 bytes from 172.17.0.1: icmp_seq=2 ttl=64 time=0.107 ms
$ curl 172.17.0.1:8000
===> curl: (7) Failed to connect to 172.17.0.1 port 8000: Connection refused
pingは(どこかに)通るけどhttpリクエスト等は無理のようです。
どうする
こいつですが、ふとnslookupをして問い合わせたserverに対してリクエストを投げるとうまくいきます。
$ nslookup 172.17.0.1
===> Server: 192.168.65.1 <---コレ
===> Address: 192.168.65.1#53
===>
===> ** server can't find 1.0.17.172.in-addr.arpa: NXDOMAIN
$ curl --head 192.168.65.1:8000
===> HTTP/1.0 400 Bad Request
===> Date: Fri, 03 Mar 2017 12:17:18 GMT
===> Server: WSGIServer/0.2 CPython/3.6.0
===> Content-Type: text/html
400
返ってきていますが、これは単にページが存在しないだけで、アクセス自体はできています。
ちなみに、ホスト側でも
Invalid HTTP_HOST header: '192.168.65.1:8000'. You may need to add '192.168.65.1' to ALLOWED_HOSTS.
[03/Mar/2017 12:17:18] "HEAD / HTTP/1.1" 400 59989
というように、リクエストが来ていることがわかります。
おわりに
なぜMacだとip r
で取得できるアドレスではアクセス出来ないのかがよくわからなかった
(Hypervisorあたりの理由?? 詳しい方教えてください )ですが、
これでローカルに直接起動したRedisサーバ等にもアクセスして使うことができそうです。