こんにちは。 インフラ開発部の上田です。
普段は自社開発システムのインフラ担当として、日々頑張って仕事をしています。 今回は、近年話題になっているDockerについて、取り上げてみようと思います!
なぜDockerなのか・・・? そもそもDockerとは何か・・・?
当社では様々なサービスを自社開発していますが、インフラ環境もオンプレだけではなく、VMwareなどの仮想環境、AWSなどのクラウドサービスなど、サービスに合わせてインフラ環境も適宜選択しています。
このため、やはり話題のDockerについても評価し、自社開発システムにおける今後の構成案の一つとして取り入れられるよう、理解を深めていかなければいけません・・・
ということで、試行錯誤しながらDockerを評価していた内容を交えながら、ご説明したいと思います!
今回はまず前編となります。
- Dockerとは!? 多くのサイトのご説明だと、 ・コンテナ型の仮想化を実現するためのソフトウェア ・XenやHyper-V、VMwareのようなサーバ仮想化とは異なる ・コンテナ上でプロセスが実行される
あまりピンと来ないですね・・・ イメージでは下記のような構成となります。
左はVMwareのようなサーバ仮想化の一般的な構成ですね。 サーバが下段にあり、VMwareでいうESXiサーバOS上で各ゲストOSが動作します。 そして、各ゲストOS上で複数のプロセスが起動する構成となります。
次に右はDockerを使用したコンテナ構成の構成となります。 サーバが下段にあり、RedHatやCentOSなどのOSがサーバ上でDockerが動作します。 そして、このDocker上でコンテナと呼ばれる各空間上でプロセスが起動する構成となります。
もちろん、コンテナ上で複数のプロセスを起動することは可能ですが、大きな差は右のサーバ仮想化構成とは異なり、
ゲストOSがない!
というところです。
ということは、サーバ仮想化構成のような各ゲストOSのリソース消費がないということがDockerの特徴の一つと言えます。
また、コンテナ構成などをDockerfileと呼ばれるテキストファイルに纏めて記述することが可能なため、全く同じ環境を容易に作成、またはロールバックも可能です。
これにより、構成ズレや構築手順のズレをなくすことができ、バージョン管理ができることも特徴です。
- 既設自社サービスのDocker化
と、ここまでDockerの構成についてお話しましたが、やっぱりよく分からない!まずはやってみよう!!と思い、既設自社サービスのDocker化をしてみました。
今回は、AWS EC2上の自社開発し、提供している広告配信システムをDocker化してみます。
具体的な個所はオープンにできませんが、この記事を読まれている方は、ApacheやNginxなどのWebサーバを想像して頂ければと思います。
- base image作成
base imageとは、コンテナとして起動させるベースとなるイメージです。
base imageとして、公式DockerレジストリであるDocker Hubで公開されているコンテナを使用して構築することも可能です。
ただ、今回は既にAWS EC2上に構築済みの広告配信システムをDocker化し、Dockerの理解を深めていきたいと思います! ※ 自社開発していなくても、既に色々とサーバに手を加えている内容を新規環境に設定するのは手間ですしね・・・
また、公式Dockerレジストリは外部公開されているため、今回のような独自のbase imageを作成する場合は、Dockerプライベートレジストリを構築し、base imageを管理しましょう。 ※ 自社開発のソースが外部公開されるなんてことが起きたら・・・
尚、docker自体のインストールはyumでできますので記載しておりません。ご了承ください・・・ まずはDockerを起動させるサーバ(以下、DockerServer)上で、既にEC2上に構築済みの広告配信サーバ(以下、ClientServer)のEBSをアタッチします。
アタッチはEC2のコンソールから、実施します。
今回の趣旨とは異なるため、作業イメージとしては、以下のサイトが分かりやすいため、ご参考に確認してみてください。
http://qiita.com/yuppi/items/ceed29f19e2b38fd0a79
次にアタッチしたEBSをDockerServerでマウントします。 ※ アタッチしたEBSが/dev/sdfで認識されたこととしています。
[root@DockerServer /] #mount /dev/sdf /mnt/ [root@DockerServer mnt] # cd /mnt/ [root@DockerServer mnt] # ls bin data etc lib media mnt opt root selinux sys tmp var boot dev home lost+found misc net proc sbin srv tftpboot usr
これでまずはマウントされ、ClientServerのディスク内容が確認できました。 そして、このClientServerのディスクイメージをbase imageとして作成し、さらにコンテナとしてDocker上で起動できるようにしてみます。
[root@DockerServer mnt] # tar --numeric-owner -cjp . | docker import - ClientServer:1.0 tar: ./var/run/dbus/system_bus_socket: socket ignored 55568f37XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
「ClientServer:1.0」はClientServerという名前で作成し、バージョン管理のイメージで1.0としています。
処理は結構時間が掛かりますが、1h程放置していれば終わりました。 完了後、確認してみます。
[root@DockerServer mnt] # docker images REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE ClientServer 1.0 87433f37eb30 55 minutes ago 9.24 GB
9GB強のbase imageとしてClientServerができたようです。 尚、「docker images」コマンドで、Docker上で管理しているコンテナ一覧を確認することが可能です。
- コンテナ起動
では、「docker run」コマンドで作成したコンテナを起動してみます。
各種オプションですが、「-i」でコンテナの標準入力を開く、「-t」でttyを確保します。 今回は/bin/bashでコンテナを操作したいため、指定しています。 また、バックグラウンドではなくフォアグラウンドで起動させたいため、バックグラウンドでの起動オプションは指定していません。
[root@DockerServer mnt] # docker run -i -t ClientServer:1.0 /bin/bash [root@3655XXXXXX /] #
正常に起動できたようですが、ホスト名が違うみたいです。
[root@3655XXXXXX /] # hostname 3655XXXXXX
一度コンテナのプロンプトを抜けるため、「Ctrl + d」で押下します。 そうすると、DockerServer側に戻ることができます。 このとき、フォアグラウンドで起動したため、「Ctrl + d」で戻るとコンテナが終了してしまいます。 ということで、ホスト名を指定してコンテナを起動してみましょう。 先程の起動オプションに「-h ホスト名」を追加することで、指定したホスト名で起動することができます。
[root@DockerServer mnt] # docker run -i -t -h ClientServer ClientServer:1.0 /bin/bash [root@ClientServer /] # [root@3655XXXXXX /] # hostname ClientServer
これでClientServerというホスト名で起動することができました。
ところで最初に「サーバ仮想化構成のような各ゲストOSのリソース消費がない」、「コンテナと呼ばれる各空間上でプロセスが起動する構成」とお話しましたが、どういうことかと実際に確認すると、
[root@ClientServer /]# ps aux USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND root 1 0.0 0.0 4692 1480 ? Ss 11:50 0:00 /bin/bash root 25 0.0 0.0 4408 948 ? R+ 11:52 0:00 ps aux
という形で、通常OS起動時にinitが最初に様々なプロセスを起動しますが、コンテナ上では上述のようにありません。 例えばですが、sshdを起動したい場合、実行してあげる必要があります。
[root@ClientServer /]# /etc/init.d/sshd start Starting sshd: [ OK ] [root@ClientServer /]# ps aux USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND root 1 0.0 0.0 4804 1504 ? Ss 11:50 0:00 /bin/bash root 35 0.0 0.0 7304 984 ? Ss 11:58 0:00 /usr/sbin/sshd root 37 0.0 0.0 4408 952 ? R+ 11:59 0:00 ps aux
では、せっかく起動したsshdなので、リモート接続してみたいところですが、確認するために「Ctrl + d」でコンテナのプロンプトから抜けると、コンテナが終了してしまいます。
ターミナルをもう一つ開いて確認してもいいのですが、これだとずっとコンテナを起動したターミナルを開き続けないといなないため、コンテナをバックグラウンドで起動します。 まずは先程と同じように「Ctrl + d」でコンテナのプロンプトから抜け、コンテナが終了させます。
そして、起動オプションで「-d」を指定して起動します。さらに、「-p」オプションでポートを指定してポートフォワーディングします。
[root@DockerServer mnt] # docker run -d -p 22:22 -h ClientServer ClientServer:1.0 /usr/sbin/sshd -D 39cadf5202ab2154e7cbe45efdcXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
コンテナが正常にバックグラウンドで起動していることを確認するため、「docker ps」コマンドで確認します。
[root@DockerServer mnt] # docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES dd3e42XXXXXX ClientServer:1.0 /usr/sbin/sshd -D About a minute ago Up About a minute 0.0.0.0:10022->22/tcp hungry_thompson
ちなみに起動したコンテナは自動でIPアドレスが割り振られるため、どのIPアドレスが付与されたかを確認する必要があります。 ※ IPアドレスの固定化は、次回にでもお話させて頂きます。
最後の「dd3e42XXXXXX」は「docker ps」コマンドで確認できるコンテナIDとなります。このコンテナIDはコンテナ起動毎にランダムで付与されます。
[root@DockerServer mnt] # docker inspect --format="{{ .NetworkSettings.IPAddress }}" dd3e42XXXXXX 172.17.0.10
今回は「172.17.0.10」となっていることを確認できたので、sshしてみましょう。
[root@ip-10-146-136-123 ~]# ssh testuser@172.17.0.10 The authenticity of host '[172.17.0.10]:22 ([172.17.0.10]:22)' can't be established. RSA key fingerprint is XX:XX:XX:XX:XX:XX:XX. Are you sure you want to continue connecting (yes/no)? yes Warning: Permanently added '[172.17.0.10]:22' (RSA) to the list of known hosts. testuser@172.17.0.10's password: Last login: Thu Oct 23 11:18:52 2014 from 172.17.XX.XX [pubadda@ClientServer ~]$
と、sshができました! ここまで、base imageを作成し、コンテナを起動させることについてお話してみました。 次回は色々と試してみたことについてお話できればと思います。
宜しくお願いします!!