Docker事始め - ネットワークについて2

[Docer事始め - ネットワークについて1](http://qiita.com/hirame_23/items/316e59faa79f9d3ada62)の続きです。
コンテナ側で起動したミドルウェアへのアクセスについて記載します。
※前回起動していたコンテナは全てdocker rmコマンドで削除しています。

# 環境
- OS : CentOS release 6.5 (Final)
- Kernel : 2.6.32-431.17.1.el6.x86_64
- Docker : docker-io-0.11.1-4.el6.x86_64

# 試す
docker runのhelpを参照するとDockerではコンテナ生成時にポート番号の紐付けが可能のようです。

```bash
# docker run --help
Usage: docker run [OPTIONS] IMAGE [COMMAND] [ARG...]
Run a command in a new container
<snip>
  -p, --publish=[]           Publish a container's port to the host
                               format: ip:hostPort:containerPort | ip::containerPort | hostPort:containerPort
                               (use 'docker port' to see the actual mapping)
  -P, --publish-all=false    Publish all exposed ports to the host interfaces
<snip>
```

apacheを例とするため、以下の内容で試します。
- ホストOS側は8080ポートで受け付けたアクセスをコンテナ側の80ポートに渡す

```bash
# 事前にiptablesの内容を確認
# iptables -L
Chain INPUT (policy ACCEPT)
target     prot opt source               destination         
ACCEPT     all  --  anywhere             anywhere            state RELATED,ESTABLISHED 
ACCEPT     icmp --  anywhere             anywhere            
ACCEPT     all  --  anywhere             anywhere            
ACCEPT     tcp  --  anywhere             anywhere            state NEW tcp dpt:ssh 
REJECT     all  --  anywhere             anywhere            reject-with icmp-host-prohibited 

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination         
ACCEPT     all  --  anywhere             anywhere            ctstate RELATED,ESTABLISHED 
ACCEPT     all  --  anywhere             anywhere            
ACCEPT     all  --  anywhere             anywhere            
REJECT     all  --  anywhere             anywhere            reject-with icmp-host-prohibited 

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination         

# Dockerコンテナをポート番号を紐付けて生成
# docker run -p 8080:80 -i -t centos /bin/bash
bash-4.1#
# コンテナを生成したまま抜ける
bash-4.1# Ctrl+p , Ctrl+q
# 
# docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS                  NAMES
a610057f883b        centos:latest       /bin/bash           15 seconds ago      Up 13 seconds       0.0.0.0:8080->80/tcp   grave_morse
# PORTS列にポート設定について確認できる
# 
# iptables -L
Chain INPUT (policy ACCEPT)
target     prot opt source               destination         
ACCEPT     all  --  anywhere             anywhere            state RELATED,ESTABLISHED 
ACCEPT     icmp --  anywhere             anywhere            
ACCEPT     all  --  anywhere             anywhere            
ACCEPT     tcp  --  anywhere             anywhere            state NEW tcp dpt:ssh 
REJECT     all  --  anywhere             anywhere            reject-with icmp-host-prohibited 

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination         
ACCEPT     tcp  --  anywhere             172.17.0.2          tcp dpt:http 
ACCEPT     all  --  anywhere             anywhere            ctstate RELATED,ESTABLISHED 
ACCEPT     all  --  anywhere             anywhere            
ACCEPT     all  --  anywhere             anywhere            
REJECT     all  --  anywhere             anywhere            reject-with icmp-host-prohibited 

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination         
# Chain FORWARDにコンテナへのポリシーが追加されていることが確認できる
# 
# コンテナ側にapacheを構築して疎通を確認する
# 先ほど生成したコンテナへアタッチ
# docker attach a610057f883b
bash-4.1# 
# 80ポートがListenしていないことを確認
bash-4.1# netstat -tlnp
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address               Foreign Address             State       PID/Program name   
bash-4.1# 
# apacheをyumからインストール
bash-4.1# yum install -y httpd
bash-4.1# 
# httpdパッケージがインストールしたことを確認
bash-4.1# rpm -q httpd
httpd-2.2.15-30.el6.centos.x86_64
bash-4.1# 
# 適当な文字列を返すindex.htmlファイルを作成
bash-4.1# echo "Hello, Docker world." > /var/www/html/index.html
bash-4.1# 
# apacheを起動
bash-4.1# service httpd start
Starting httpd: httpd: Could not reliably determine the server's fully qualified domain name, using 172.17.0.2 for ServerName
                                                           [  OK  ]
# FQDNでメッセージがでるが検証なので気にしない
bash-4.1# 
# 80ポートがListenしていることを確認
bash-4.1# netstat -tlnp
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address               Foreign Address             State       PID/Program name   
tcp        0      0 :::80                       :::*                        LISTEN      89/httpd            
bash-4.1# 
# コンテナ上からのアクセスを確認
bash-4.1# curl 127.0.0.1
Hello, Docker world.
bash-4.1# 
# コンテナを生成したまま抜ける
bash-4.1# Ctrl+p , Ctrl+q
# 
# ホストOSからコンテナに対して確認
# curl 172.17.0.2
Hello, Docker world.
# ホストOS上からはコンテナのIPアドレスとルーティングがわかるため
# 
# ホストOSからホストOSに対して確認
# curl 127.0.0.1:8080
Hello, Docker world.
# ポートマッピングができているので別ホストからはホストOSのポート8080に対してアクセスすると、コンテナ側のapacheが応答を返すという形になる
# 念のため別ホストからも確認
# ssh other-host
[other-host ~]# 
[other-host ~]# curl ホストOSのIPアドレス:8080
Hello, Docker world.
[other-host ~]# 
[other-host ~]# exit
#
```

# 雑感
- コンテナへのポートの紐付けはdocker psコマンドから確認できる
- ポートの紐付けはコンテナ生成時に指定する
    - コンテナ生成後でも可能…？
- ポートの紐付けはiptablesで実現してるっぽい
- 特殊なことはやっていないようにみえる

最小構成のイメージから毎回ミドルウェアをインストール+設定となると面倒なので、次回はカスタムDockerイメージの作成とかその辺を追ってみたいと思います。