akishin999の日記

調べた事などを書いて行きます。

CentOS 6.4 で Docker 0.7 を使ってみる

Docker がバージョン 0.7 から RedHat 系 OS に正式に対応した、という事なのでインストールして軽く触ってみました。

Requirements and Installation on Red Hat Enterprise Linux / CentOS - Docker Documentation
http://docs.docker.io/en/latest/installation/rhel/

試した OS は手元にあった CentOS 6.4 x86_64 です。

インストールといっても公式の手順にもある通り EPEL で入れられるようになったので、yum リポジトリを追加して入れるだけです。
まずは EPEL リポジトリを使えるようにします。

# rpm --import http://dl.fedoraproject.org/pub/epel/RPM-GPG-KEY-EPEL-6
# yum install -y http://dl.fedoraproject.org/pub/epel/6/x86_64/epel-release-6-8.noarch.rpm

EPEL が使えるようになったら yum で docker-io パッケージをインストール。

# yum install -y docker-io

これだけで他は特に何もしなくても Docker が使えるようになりました。
以前試した時は CentOS へ入れようとするとかなり大変だったので、大分楽になりましたね。
ありがたい事です。

せっかくインストールしたのでちょっと使ってみます。
インストールしたらまずはデーモンを起動。

# service docker start

取りあえず Redis をインストールする Dockerfile を作ってみました。

  • Dockerfile
FROM centos

RUN rpm --import http://dl.fedoraproject.org/pub/epel/RPM-GPG-KEY-EPEL-6
RUN rpm --import http://rpms.famillecollet.com/RPM-GPG-KEY-remi
RUN yum install -y http://dl.fedoraproject.org/pub/epel/6/x86_64/epel-release-6-8.noarch.rpm
RUN yum install -y http://rpms.famillecollet.com/enterprise/6/remi/x86_64/remi-release-6.4-1.el6.remi.noarch.rpm
RUN yum install -y --enablerepo=remi redis

RUN echo "vm.overcommit_memory = 1" >> /etc/sysctl.conf
RUN /sbin/sysctl -p

CMD ["/usr/sbin/redis-server"]

保存したらビルドします。
Dockerfile と同じディレクトリで以下を実行。

# docker build -t akishin/redis .

初回は Docker のリポジトリから CentOS のイメージをダウンロードするのでちょっと時間がかかります。
実行が終わったら docker images を実行すると以下のようにイメージが作成された事が分かります。

# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
akishin/redis       latest              24584d69487e        22 seconds ago      355.4 MB (virtual 1.11 GB)
centos              6.4                 539c0211cd76        8 months ago        300.6 MB (virtual 300.6 MB)
centos              latest              539c0211cd76        8 months ago        300.6 MB (virtual 300.6 MB)

作成したイメージを起動してみます。

# docker run -d akishin/redis

ちょっと冗長ですが、以下のコマンドを実行するとコンテナの IP アドレスが分かります。

# docker inspect $(docker ps -q) | grep IPAddress
        "IPAddress": "172.17.0.17",

Redis は Telnet で操作できるので、先ほど調べた IPアドレスで接続して試しに使ってみます。

# telnet 172.17.0.17 6379
Trying 172.17.0.17...
Connected to 172.17.0.17.
Escape character is '^]'.

SET foo bar
+OK
GET foo
$3
bar
quit
+OK
Connection closed by foreign host.

問題無さそうですね。

ただ、このままだと Docker を動かしているホストからしか Redis を使用することが出来ません。
他のマシンから接続するためには、コンテナのポートをホストのポートにマッピングする必要があります。

公式ドキュメントでは以下の辺り。

Port redirection - Docker Documentation
http://docs.docker.io/en/latest/use/port_redirection/

まずは先ほどのコンテナを停止します。

# docker stop $(docker ps -q)

今度は docker run 時に -p でポートを指定します。
以下の指定ではコンテナの 6379 ポートをホストの同じポートにマッピングしています。

# docker run -d -p 6379:6379 akishin/redis

netstat で見てみると今度はホスト側でもポート 6379 が LISTEN されていることが分かります。

# netstat -tln | grep 6379
tcp        0      0 :::6379                     :::*                        LISTEN

これで「ホストのIPアドレス:6379」で外部のマシンから接続できるはず・・・と思ったら以下のようなエラーとなってしまい、接続できません。

% telnet 192.0.2.3 6379
Trying 192.0.2.3...
telnet: Unable to connect to remote host: No route to host

どうやらこれはファイアウォールにブロックされてしまっている事が原因のようです。
学習用環境なので iptables を止めてしまえばいいかとも思ったのですが、docker では iptables に以下のように NAT 設定が追加されていました。

# iptables -L -t nat
Chain PREROUTING (policy ACCEPT)
target     prot opt source               destination
DOCKER     all  --  anywhere             anywhere            ADDRTYPE match dst-type LOCAL

Chain POSTROUTING (policy ACCEPT)
target     prot opt source               destination
MASQUERADE  all  --  172.17.0.0/16       !172.17.0.0/16

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination
DOCKER     all  --  anywhere            !loopback/8          ADDRTYPE match dst-type LOCAL

Chain DOCKER (2 references)
target     prot opt source               destination
DNAT       tcp  --  anywhere             anywhere            tcp dpt:6379 to:172.17.0.18:6379

これだと iptables は止めちゃ駄目っぽいですね。
という訳で、FORWARD チェインに以下のようなルールを追加してみます。

# iptables -I FORWARD -p tcp --dport 6379 -j ACCEPT

再度別のマシンからアクセス。

% telnet 192.0.2.3 6379
Trying 192.0.2.3...
Connected to 192.0.2.3.
Escape character is '^]'.
set hoge fuga
+OK
get hoge
$4
fuga
quit
+OK
Connection closed by foreign host.

今度は上手く行きました!
これで開発時に Redis サーバが欲しくなったらイメージからサクッと起動できますね。

普段開発で使っている Ubuntu がまだ 32bit という事もあって Docker は使ってなかったのですが、CentOS でこれだけ簡単に使えるようになると今後は活用していきたいところ。
取りあえずドキュメント読みながら触ってるところですが、いまいち EXPOSE の使いどころがよく分からず・・・。