Dockerシングルホストでのコンテナ間通信
Docker Composeを使うとyamlでまとめられるし非常に楽、という話を聞いたので試そうと思ったけど、一度くらいはlink使ってみたほうが良い気がしたので試してみる。
環境は前回と同じ。
2016/04/04追記
本記事ではDockerのデフォルトネットワークを使用してコンテナ間通信を試行していますが、公式曰くデフォルトのbrigeはレガシーとのことなのでもっと便利なユーザー定義ネットワークを使用しましょう。
ユーザー定義ネットワークの試行もすぐやろう。
- やること
- 準備
- backendコンテナをたてる
- proxyコンテナをたてる(linkなし)
- コンテナのIPアドレスによる通信についての問題点
- proxyコンテナをたてる(linkあり)
- ちなみに
- 謝辞
やること
個人で所謂LAMP環境なサービスを作ったりする時、私の場合は殴ることができるほどの札束を持っていないので、VPSを借りるにしても複数台借りるようなリッチなことができない。
なので、サーバの80番portはnginxにもたせて、サービス用のWebサーバには3000番だったり5000番を割り当て、リバースプロキシさせることでアクセスを振り分けたりする。
サービスなんか運用してるのかって?してたけど需要なさすぎて止めてるんですよ!何かおもしろいこと思いついたら作りますね!!!!思いつかないけど!!!!
ということで、コンテナ間通信の題材はnginxによるリバースプロキシということにする。
各コンテナをホストのポートとマッピングするのが簡単なんだけど、そうするとDBコンテナやAPコンテナを外部に晒すことになりそうなので回避したい。
そういう時に便利なのがlink
機能なんだそう。
Dockerのネットワーク周りは色々ありそうなので、ドキュメントはちゃんと読んでおきたい。。。願望。
準備
- リバースプロキシ用コンテナ
- コンテナ名
- proxy
- コンテナ名
- バックエンド用コンテナ
- コンテナ名
- backend
- コンテナ名
- ボリュームコンテナ
- proxyのconfig用
- コンテナ名
- proxy_config
- コンテナ名
- proxyのhtml用
- コンテナ名
- proxy_html
- コンテナ名
- backendのhtml用
- コンテナ名
- backend_html
- コンテナ名
- proxyのconfig用
proxy
もbackend
もnginxを立ち上げるだけなので、Dockerfileは以下のようにした。
FROM centos:latest MAINTAINER ryoana RUN yum -y update RUN yum -y install http://nginx.org/packages/centos/7/noarch/RPMS/nginx-release-centos-7-0.el7.ngx.noarch.rpm RUN yum -y install nginx EXPOSE 80 ENTRYPOINT /usr/sbin/nginx -g 'daemon off;'
先にbuild
しておく。
# docker build -t ryoana/nginx .
ドメインでアクセスできるように、Dockerホストが乗ってるクライアントの/etc/hosts
ファイルを編集する。
$ sudo vim /etc/hosts 192.168.0.2 proxy.example.com 192.168.0.2 backend.example.com
backend
コンテナをたてる
先にbackend
コンテナをたてる。
後でテストできるように、/var/lib/docker/volumes/backend_html/_data/index.html
にIt is backend page.
とかなんとか書いておく。
# docker run -d --name backend -v backend_html:/usr/share/nginx/html ryoana/nginx # docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 7a994bad7e68 ryoana/nginx "/bin/sh -c '/usr/sbi" 3 seconds ago Up 2 seconds 80/tcp backend
ホスト側のポートとマッピングしていないので、ブラウザからはまだアクセスできない。
proxy
コンテナをたてる(linkなし)
まずはlink機能を使わずにコンテナ間の通信を実現してみる。
backend
と違いを明確にするために、/var/lib/docker/volumes/proxy_html/_data/index.html
にIt is proxy page.
と書いておく。
# docker run -d --name proxy -v proxy_html:/usr/share/nginx/html -v proxy_config:/etc/nginx -p 80:80 ryoana/nginx # docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES e8bada83de7e ryoana/nginx "/bin/sh -c '/usr/sbi" 24 seconds ago Up 24 seconds 0.0.0.0:80->80/tcp proxy 7a994bad7e68 ryoana/nginx "/bin/sh -c '/usr/sbi" 7 minutes ago Up 7 minutes 80/tcp backend
proxy
はホストの80番ポートとマップして、ちゃんと外から通信できるようにする。
ホストはVirtualBoxで動いているので、クライアントのブラウザからDockerホストの80番ポートにアクセスしてみる。
proxy page
を見ることができた。
ではconfigにリバースプロキシ用の設定を追加して、backend.example.com
宛のリクエストをbackend
に流れるようにしよう。
まずはbackend
のIPアドレスを調べる。
# docker inspect backend | grep IPAddress IPAddress": "172.17.0.2"
IPがわかったのでconfigを編集する。
ここではリクエストを流すことができればそれでいいので、proxy_pass
だけ設定する。
# vim /var/lib/docker/volumes/proxy_config/_data/proxy_config/_data/conf.d/virtual.conf server { listen 80; server_name backend.example.com; location / { proxy_pass http://172.17.0.2; } }
config編集したのでproxy
コンテナを一度停止して、再度起動する。
# docker restart proxy
再起動できたらクライアントのブラウザからbackend.example.com
にアクセスしてみる。
コンテナのIPアドレスによる通信についての問題点
ここまでで一応「コンテナ間の通信」ができることは確認したけど、そもそもDockerコンテナはIPアドレスを固定できない。(私の知る限りでは。。。できるんでしょうか)
色々コンテナを立ち上げたり立ち上げ直したりするたびIPアドレスが変わる→proxy
のconfigを書き換えないといけない、というのはとてもいけてない。
そこでlink機能が登場する。
proxy
コンテナをたてる(linkあり)
ということで、link機能を使ってproxy
コンテナを立ち上げてみる。
# docker run -d --name proxy --link backend:backend -v proxy_html:/usr/share/nginx/html -v proxy_config:/etc/nginx -p 80:80 ryoana/nginx
link機能を使ってproxy
コンテナを立ち上げているので、configを以下のように編集してもアクセスすることができる。(この場合backend
のIPアドレスは変わっていないので、configをいじらなくてもアクセスはできる)
# vim /var/lib/docker/volumes/proxy_config/_data/proxy_config/_data/conf.d/virtual.conf server { listen 80; server_name backend.example.com; location / { proxy_pass http://backend; } }
proxy
コンテナを立ち上げるときに指定している--link backend:bacnend
は、--link <コンテナ名>:<エイリアス>
という書式になっていて、proxy
コンテナからは<エイリアス>
で指定した名前を使ってbackend
コンテナと通信することができる。
ちなみに
link機能を使うだけでどうして通信できるようになるの?と思ったのですが、/etc/hosts
に該当するエントリを書き込んでいるみたい。
# docker exec proxy 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 backend 7a994bad7e68 172.17.0.3 e2df163580d2
link機能を使えばコンテナを直接外部ポートに紐付ける必要がなくなっていい感じかなと思います。
Dockerのネットワーク周りはパフォーマンスにも大きく影響を与えるようなので、もうちょっとお勉強しようかなと思いました。