Dockerコンテナ内からDockerのホストOSに通信する方法

■ 普通にIPアドレスで通信できない
Docker管理ツールをDockerコンテナ化したいなと思って作業中。
DockeコンテナからWebAPIをたたこうとしてもNAT解決されてるので
ホストOS上のAPIは普通には叩け無いことが判明。

Unixドメインソケットを使う
他の同じようなプロダクトを見てみると--volumeオプションで socket ファイルを渡しているなぁ
なるほど。通信にはこれを使うんだな。

調べてみるとUNIXドメインソケットとかいうものだそうです。

Unixドメインソケット
http://ja.wikipedia.org/wiki/UNIX%E3%83%89%E3%83%A1%E3%82%A4%E3%83%B3%E3%82%BD%E3%82%B1%E3%83%83%E3%83%88

■ コンテナ内のアプリとの通信はProxy。
コンテナ内で動作させたいのはJ2EEなので
JavaUNIXドメインソケットを使えないかどうか調べてみると
そういうライブラリはあるみたいです。

でも、ちょっと待てよ。
コンテナ内で動かしたいアプリに手を入れたくないなぁ
UNIXドメインソケット - HTTP のProxyをかませればいいのか。

■ Proxyソフトの選定
nginxとか使ってもいいのですが、コンテナ内のアプリケーションをなるべく減らしたい
小さいスクリプトで実行できるならそのほうがいいなと思っていろいろググってみました。
ということで見つけたのがこのページ。やりたいことにぴったり!感謝。

PythonUNIXドメインソケットを使ってみる
http://d.hatena.ne.jp/nullpobug/20101028/1288273347

さっそく少し変更して使ってみることに。

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import socket

SOCK_FILENAME = '/tmp/docker_socket'

def main():
    s_srv = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s_cli = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
    s_cli.connect(SOCK_FILENAME)

    s_srv.bind(('0.0.0.0', 55110))
    s_srv.listen(1)
    try:
        try:
            while True:
                conn, addr = s_srv.accept()
                print '---connected---'
                data = conn.recv(1024)
                print data
                print '-----client------'
                # proxy client
                s_cli.send(data)
                content = s_cli.recv(1024)
                print content
                print '-----proxy-------'
                conn.send(content)
                conn.close()
        finally:
            s_cli.close()
    except KeyboardInterrupt:
        pass

if __name__ == '__main__':
    main()

■ 結果
一応動作はしたけど なんか不安定。
Proxy出来る時とできないときがあるみたい。
nginxにしてみたほうがいいのかな。。。


■nginx化
しょうがないのでnginx化してみました。
ちょっと迷いましたが結構お手軽。

ポイントは Unixドメインソケットのパーミッションを666にしないと
uginxから読めなかったところです

#apt-get install nginx
# vi /etc/nginx/sites-available/unix-socket-proxy
upstream backend {
    server unix:/tmp/docker_socket;
}

server {
    listen 55110;
    server_name 127.0.0.1;
    location / {
        proxy_pass http://backend;
    }
}


# ln -s /etc/nginx/sites-available/unix-socket-proxy /etc/nginx/sites-enabled/
# chmod 666 /tmp/docker_socket
# /etc/init.d/nginx reload


■成果物
こんなかんじになりました。
https://registry.hub.docker.com/u/moremagic/bluefairy-in-docker/