まーぽんって誰がつけたの?

iOS→Scala→インフラなおじさん技術メモ

開発環境のFTPサーバーをboot2dockerでコンテナとして作ろうとしたらなんかコレジャナイ感じになった

Dockerがローカルの開発環境に使えるのかを検証してみようと思って、ただのFTPサーバーを作ってみました。
コンテナの考え方とboot2dockerのネットワークがよく分かってなかったので、苦労しました。ただ、がんばって環境ができたはいいけど、なんか、全然便利じゃない感じになってDockerの使い道を間違ってる気がしてきたという話です。

f:id:masato47744:20140624023646p:plain

Docker初心者脳で素直に考えてみる

Dockerfileはこんな感じ。yumでvsftpdインストールして起動するだけ。

FROM centos:latest
MAINTAINER Masato Oshima <qqw75pn9@gmail.com>

# proxyあればね
ENV http_proxy http://proxyuser:password@proxyhost:port
ENV https_proxy http://proxyuser:password@proxyhost:port

RUN yum -y update && yum -y install vsftpd

EXPOSE 21
CMD ["/etc/init.d/vsftpd","start"]

これでビルド&コンテナ起動

$ docker build -t mpon/vsftpd .
$ docker run -d mpon/vsftpd
$ docker ps
CONTAINER ID        IMAGE                COMMAND                CREATED              STATUS                        PORTS               NAMES

コンテナが起動してない・・・

起動してもすぐにコンテナが終了してしまう。docker psしてもコンテナが出てこない。
-dをつければデーモンみたいに動くんじゃないの?docker ps -aのSTATUS見ると、Exited (0)になってる。0ってことは成功っぽいんだけどな。
じゃあということで、-i -tをつけて、コマンドの出力内容を見てみると、vsftpdが起動していることが分かる。

$ docker run -i -t mpon/vsftpd
Starting vsftpd for vsftpd:                                [  OK  ]

うーん、コマンドは実行されてるっぽいんだけどなー。bashで起動して確認してみるか。

bashでコンテナに入ってからvsftpdを起動してみる

$ docker run -i -t mpon/vsftpd bash
bash-4.1# /etc/init.d/vsftpd status
vsftpd is stopped

あれ?そもそも、vsftpdは起動してないぞ。よく分からないけど、とりあえずもう一回bash上で/etc/init.d/vsftpd startで起動する。

ここでコンテナのbashはログインしたまま、ローカルからftpでログインしてみる。 まずは、boot2dockerVMのIPアドレスを調べる。

$ boot2docker ip
The VM's Host only interface IP address is: 192.168.59.103

macからftp接続しようとするがConnecition refusedになる。

$ ftp
ftp> open 192.168.59.103
ftp: Can't connect to `192.168.59.103': Connection refused
ftp: Can't connect to `192.168.59.103'

コンテナ起動時にポートをバインドしてないからかな。ポートをバインドして、起動して同様にbashからコマンド入力してvsftpdを起動する。

$ docker run -i -t -p 21:21 mpon/vsftpd bash

そしたら今度はftpログインできた!

ftp> open 192.168.59.103
Connected to 192.168.59.103.
220 (vsFTPd 2.2.2)
Name (192.168.59.103:mpon): ftp
331 Please specify the password.
Password:
230 Login successful.
Remote system type is UNIX.
Using binary mode to transfer files.
ftp>

bashでログインして起動してればOKで、-d/etc/init.d/vsftpd startで、コンテナ起動した場合はコンテナが終了しちゃうということは、コンテナは実行中のコマンドが終了しちゃうと終わっちゃうんじゃないかという気がしてきた。

  • bashは実行中だからコンテナも起動状態のまま(当たり前な気がするけど)
  • /etc/init.d/vsftpd startというコマンド自体は終了、だからコンテナも終了。

みたいな。

dockerのコンテナはコマンドが終了してはいけないんじゃないか説

ってことで、tailコマンドとtail -fで確認してみる。

tail

Dockerfileの以下の部分をtailに書き換える。

CMD ["tail", "/var/log/yum.log"]

ビルドして実行すると、コンテナのSTATUSが予想通りExited(0)になってる。コンテナは終了してる。

$ docker build -t mpon/tail
$ docker run -d mpon/tail
$ docker ps -a
CONTAINER ID        IMAGE                COMMAND                CREATED              STATUS                        PORTS               NAMES
64d8def11df9        mpon/tail:latest     tail /var/log/yum.lo   22 seconds ago       Exited (0) 20 seconds ago                         focused_pasteur

tail -f

DockerfileのCMDを書き換える

CMD ["tail", "-f", "/var/log/yum.log"]

ビルドして実行すると、コンテナのSTATUSがUp になってて、コンテナが終了してない。 -aをつけなくても出てくる。logsも見れるし。予想はあたってた!

$ docker ps
CONTAINER ID        IMAGE               COMMAND                CREATED             STATUS              PORTS               NAMES
9a24f8a90fab        mpon/tailf:latest   tail -f /var/log/yum   3 seconds ago       Up 2 seconds        21/tcp              prickly_ritchie

$ docker logs 9a24f8a90fab
Jun 22 03:33:55 Updated: libxml2-2.7.6-14.el6_5.2.x86_64
Jun 22 03:34:04 Installed: 2:ethtool-3.5-1.4.el6_5.x86_64
Jun 22 03:34:04 Installed: upstart-0.6.5-13.el6_5.3.x86_64
Jun 22 03:34:04 Installed: iputils-20071127-17.el6_4.2.x86_64
Jun 22 03:34:05 Installed: iproute-2.6.32-32.el6_5.x86_64
Jun 22 03:34:06 Installed: initscripts-9.03.40-2.el6.centos.1.x86_64
Jun 22 03:34:06 Installed: policycoreutils-2.0.83-19.39.el6.x86_64
Jun 22 03:34:07 Installed: iptables-1.4.7-11.el6.x86_64
Jun 22 03:34:07 Installed: logrotate-3.7.8-17.el6.x86_64
Jun 22 03:34:07 Installed: vsftpd-2.2.2-11.el6_4.1.x86_64

やっぱり、そうだ、最後のコマンドは終了しちゃうようなやつだとダメなんだ。
ってことは、vsftpdをforegroundで起動するようなものにすればいいんだということになる。
なので、vsftpdをforegroundで動かす方法を探ってみる。

vsftpdをforegroundで動かすには?

vsftpd.confでbackground=NOにすればいいみたいなのを見つけた。

background
When enabled, and vsftpd is started in "listen" mode, vsftpd will background the listener process. i.e. control will immediately be returned to the shell which launched vsftpd.
Default: NO

あと、/etc/init.d/vsftpd経由で動かすと、そのコマンド自体が終了してしまうので、直接 /usr/sbin/vsftpdをたたくようにする。

そのあたりの変更を加えたDockerfileがこちら。なんか迷走し始めてる気がするけど。。

FROM centos:latest

MAINTAINER Masato Oshima <qqw75pn9@gmail.com>

RUN yum -y update && yum -y install vsftpd

RUN echo "background=NO" >> /etc/vsftpd/vsftpd.conf

EXPOSE 21

CMD ["/usr/sbin/vsftpd"]

ビルドして、ポート21をバインドするのは忘れないようにしてコンテナ起動して、ftp接続できるか確認。

$ docker build -t mpon/vsftpd .
$ docker run -d -p 21:21 mpon/vsftpd
9d7377fedc502995dbc8c24930a8e7ad6ad6c2423f1091798d8f5258e9265278
$ vsftpd  docker ps
CONTAINER ID        IMAGE                COMMAND             CREATED             STATUS              PORTS               NAMES
9d7377fedc50        mpon/vsftpd:latest   /usr/sbin/vsftpd    2 seconds ago       Up 2 seconds        21/tcp              stupefied_yonath

$ ftp
ftp> open 192.168.59.103
Connected to 192.168.59.103.
220 (vsFTPd 2.2.2)
Name (192.168.59.103:mpon): ftp
331 Please specify the password.
Password:
230 Login successful.
Remote system type is UNIX.
Using binary mode to transfer files.

やったーftpでログインできた!

パッシブモード

しかし、このあと、ftpサーバー上で、lsとか打ってみると怒られるので、パッシブモードでftpサーバーを動かそうと、そのやり方を調べた。
色々試行錯誤した結果、以下のvsftpd.confの設定も追加されるように、Dockerfileに書いておく必要があった。
pasv_addressでboot2dockerのip書かなきゃいけないのがいけてない...。あと、起動時にバインドするポートを最小限にしたくて、パッシブに使うのは50000番だけにした。

pasv_address=192.168.59.103
pasv_enable=YES
pasv_min_port=50000
pasv_max_port=50000

Dockerfileはこんな感じ

FROM centos:latest

MAINTAINER Masato Oshima <qqw75pn9@gmail.com>

RUN yum -y update && yum -y install vsftpd

RUN echo "background=NO" >> /etc/vsftpd/vsftpd.conf
RUN echo "pasv_address=192.168.59.103" >> /etc/vsftpd/vsftpd.conf
RUN echo "pasv_enable=YES" >> /etc/vsftpd/vsftpd.conf
RUN echo "pasv_min_port=50000" >> /etc/vsftpd/vsftpd.conf
RUN echo "pasv_max_port=50000" >> /etc/vsftpd/vsftpd.conf

EXPOSE 21
EXPOSE 50000

CMD ["/usr/sbin/vsftpd"]

これで起動するときにパッシブモード用のポートもバインドしないとつながらいので、起動するときは以下のようにする。

$ docker run -d -p 21:21 -p 50000:50000 mpon/vsftpd

まぁ開発環境だし、こんなもんかと思ったけど、今度は、FileZillaで同時に複数ファイルをアップロードしようとしたら、エラーになってコンテナが終了してしまった。
そもそもコンテナが終了してしまうってハードすぎじゃね?とは思ったけど、まぁそこは置いといて。

ubuntu - Make FTP Server on virtualbox work in passive mode - Super User を見ると、パッシブモードで複数のファイルをやりとりしたければ、その分のポートを開けないといけないということか。

となると例えば同時50接続を許すなら、Dockerfileは、こうなった。ヤバい。

FROM centos:latest

MAINTAINER Masato Oshima <qqw75pn9@gmail.com>

RUN yum -y update && yum -y install vsftpd

RUN echo "background=NO" >> /etc/vsftpd/vsftpd.conf
RUN echo "pasv_address=192.168.59.103" >> /etc/vsftpd/vsftpd.conf
RUN echo "pasv_enable=YES" >> /etc/vsftpd/vsftpd.conf
RUN echo "pasv_min_port=50000" >> /etc/vsftpd/vsftpd.conf
RUN echo "pasv_max_port=50050" >> /etc/vsftpd/vsftpd.conf

EXPOSE 21
EXPOSE 50000
EXPOSE 50001
EXPOSE 50002
EXPOSE 50003
EXPOSE 50004
EXPOSE 50005
EXPOSE 50006
EXPOSE 50007
EXPOSE 50008
EXPOSE 50009
EXPOSE 50010
EXPOSE 50011
EXPOSE 50012
EXPOSE 50013
EXPOSE 50014
EXPOSE 50015
EXPOSE 50016
EXPOSE 50017
EXPOSE 50018
EXPOSE 50019
EXPOSE 50020
EXPOSE 50021
EXPOSE 50022
EXPOSE 50023
EXPOSE 50024
EXPOSE 50025
EXPOSE 50026
EXPOSE 50027
EXPOSE 50028
EXPOSE 50029
EXPOSE 50030
EXPOSE 50031
EXPOSE 50032
EXPOSE 50033
EXPOSE 50034
EXPOSE 50035
EXPOSE 50036
EXPOSE 50037
EXPOSE 50038
EXPOSE 50039
EXPOSE 50040
EXPOSE 50041
EXPOSE 50042
EXPOSE 50043
EXPOSE 50044
EXPOSE 50045
EXPOSE 50046
EXPOSE 50047
EXPOSE 50048
EXPOSE 50049
EXPOSE 50050

CMD ["/usr/sbin/vsftpd"]

起動スクリプトも激ヤバ。ワロタ

docker run -d  \
-p 21:21       \
-p 50000:50000 \
-p 50001:50001 \
-p 50002:50002 \
-p 50003:50003 \
-p 50004:50004 \
-p 50005:50005 \
-p 50006:50006 \
-p 50007:50007 \
-p 50008:50008 \
-p 50009:50009 \
-p 50010:50010 \
-p 50011:50011 \
-p 50012:50012 \
-p 50013:50013 \
-p 50014:50014 \
-p 50015:50015 \
-p 50016:50016 \
-p 50017:50017 \
-p 50018:50018 \
-p 50019:50019 \
-p 50020:50020 \
-p 50021:50021 \
-p 50022:50022 \
-p 50023:50023 \
-p 50024:50024 \
-p 50025:50025 \
-p 50026:50026 \
-p 50027:50027 \
-p 50028:50028 \
-p 50029:50029 \
-p 50030:50030 \
-p 50031:50031 \
-p 50032:50032 \
-p 50033:50033 \
-p 50034:50034 \
-p 50035:50035 \
-p 50036:50036 \
-p 50037:50037 \
-p 50038:50038 \
-p 50039:50039 \
-p 50040:50040 \
-p 50041:50041 \
-p 50042:50042 \
-p 50043:50043 \
-p 50044:50044 \
-p 50045:50045 \
-p 50046:50046 \
-p 50047:50047 \
-p 50048:50048 \
-p 50049:50049 \
-p 50050:50050 \
mpon/vsftpd

なんだろう、、このコレジャナイ感は。。
configにboot2dockerのVMIPアドレスを書かなきゃいけないってのもいけてないし。
なんか、ポートを複数使うようなやつにはこういうのは向いてないのかな。
ってか、AWSとかはどうやってるんだろう。セキュリティグループとか。
iptablesはなんか、あんじょうやってくれるそういう設定が合った気がする。

仮想マシンに向いてること、Dockerが得意なことがあるんだろうな。
プロセスが死ぬとコンテナまで終了するとか、怖すぎる。

まぁ、とりあえず、Dockerのいい勉強にはなった! Vagrant使ったことなくて、いきなりDocker使ってみようってなったからこうなったんだね。
次はVagrantで同じことをやってみよう。

追記

Vagrant試してみました。コレじゃなくてコッチでした。
開発環境作るのにVagrantを使ったら非常にコレダ感になった話 - まーぽんって誰がつけたの?