Dockerに入門してみたけど、僕の用途とは合わないと思った件
簡単にテスト環境を構築したい。近頃そんなことを考えていたのだが、市井ではどうやらDockerというものが流行の真っ只中にあるらしい。早速入門記事を漁ってみた。
※実際にDockerに触れて数日経過してから記事を書いてます。思い出しながら書いてるため、一部表現の曖昧な箇所がありますが、どうかご了承ください。
入門にちょうど良かった @ITの記事
大手メディアであるところの@ITに「いまさら聞けないDocker入門」という連載シリーズがあるのだが、それの第2弾である「ついに1.0がリリース! Dockerのインストールと主なコマンドの使い方」という記事を参考にした。
スロースターターな僕にはこのくらいの記事がちょうど良かった。
手始めにインストールするも、ハマりどころが。
まず、32bitなOSを使っている方にとっては悲報だが、Dockerは32bitなLinuxでは動作しないどころか、インストールもさせてもらえない。もしどうしてもDockerを体験したい!ということであれば、どこぞのVPSを契約するとか、新しいPCを購入するとかした方がよいだろう。
さて、僕の使っている環境はUbuntu-14.04(x86_64)なので、単に
sudo apt-get install docker.io
とすればインストールが終わった。
ちなみにubuntuでは別途dockerというパッケージがあるが、これはdesktopにdockを表示するための何からしく、仮想環境をつくるDockerとは別物であるので要注意。念のため、typoなどすると困るので、aliasをはっておく。
alias docker=docker.io
さて、これでdockerコマンドが使えるようになっているはずだが・・・実際のところ使えない。PATHは通っているし、コマンドとしては一応ちゃんとレスポンスをかえしてくれる。しかし、docker.ioのdaemonとの通信ができない、というエラーがでてしまう(数日前なので詳細なエラー文言は忘れました・・・)。
しかし、この現象についての対応方法はちゃんとDockerのドキュメンテーションにまとめられている。
上記ドキュメンテーションの "Memory and Swap Accounting" という項目に、grubに食わせるべきコマンドが記載されているので、/etc/default/grubの中身を以下のように書き換える。
# GRUB_CMDLINE_LINUX="" ### この行を無効にして、下記行を追加
GRUB_CMDLINE_LINUX="cgroup_enable=memory swapaccount=1"
ここまでできたら、sudo update-grub を実行し、ホストOSをリブート。これでdocker.io daemonとdocker.io clientが通信できるようになった。
ちなみに@ITの記事では非rootユーザでdockerを扱えるよう、以下のようなことをしている。
$ sudo usermod -G docker ubuntu
が、これやったらvisudoとかするときに面倒くさいので、僕はroot権限(sudo経由)でdockerを扱うことにした。
Docker Hub Registryでレポジトリを選び、pullする。
ここからいよいよDockerを使っていく。まず、Docker Hub Registry というwebサイトにアクセスする。ここには、主立ったディストリビューションなどのレポジトリが公開されているし、なんかWordPressが最初から入ってるっていう代物もあるらしい。
ちなみに、ここで言うレポジトリというのは、Dockerコンテナの基礎になるOSイメージが数種類(バージョンごとに)格納されているものであり、TAGというのがバージョンを示している。
とりあえず今回はubuntuのレポジトリを使っていこうと思う。これもリンク先を見てもらいたいのだけど、このレポジトリの導入方法について、とても明快に解説されている。引用すると、以下のとおりである。
docker pull ubuntu
なお、docker images ubuntu とすれば、このレポジトリに属するイメージが一覧で表示される。また、pull済みのイメージを確認するには、docker images とすれば良い。
Dockerコンテナを作成・実行する
実はここが一番戸惑った箇所なのだが、Dockerはコンテナの作成と同時に、その中で実行するプログラムを指定する必要があるらしい。(僕はもともとOpenVZをかなり使い込んでいた人間なので、コンテナの作成とプログラムの実行が一緒のタイミング、という概念に違和感を覚えた。)
ともあれ、実際の起動方法を知らないことには何もできないので、とりあえずやってみる。
まず、bashのようなインタラクティブなプログラムを実行する場合、以下のようなコマンドで実行できる。
docker run -it --name my_container ubuntu:latest /bin/bash
これは、ubuntuの最新バージョンのイメージを元にmy_containerという名前のコンテナを新規作成し起動、そのまま/bin/bashを実行し、入力をシェルに戻す、という働きをする。これで直接コンテナ内のbashに対して色々とコマンドを与えることができる。なお、抜ける時にはCtrl + D でホストOSに戻ることができる。(後述のツッコミにて、Ctrl + D ではなく、Ctrl-p + Ctrl-q だとご指摘をいただきました。)
なお、バックグラウンドで動くプログラムを実行する場合、インタラクティブなものに比べて、いくつかオプションが少なくてよい。
docker run --name my_container ubuntu:latest /path/to/daemon
コンテナのライフサイクルについて
※ここから先はだいぶ理解があやふやなので、話半分に読み流してください。
前述のbashを実行し、その後コンテナから抜けるためにCtrl + D(後述のツッコミを参照のこと)を押したと思う。ではその後、コンテナおよびそこに属するプロセスはどうなったのか。
結果だけ書いてしまうと、「Ctrl + Dを押したタイミングで、コンテナごと終了する」のである。これがDockerにおけるコンテナのライフサイクルである。
とどのつまり、単一かつ特定のプログラムを実行するためだけの存在であり、いわゆる「サーバ」として扱うにはいささか不便ではある。
しかし、おそらくこれがDockerの利便性の1つなんだろうと予測しているが、今のところ僕にはその利便性がまだ実感できていない。多分、使い込んでいけばわかるようになるのだろう。
Dockerfileについて
おそらく、このDockerfileの存在こそが、DockerをDockerたらしめているのだろうと思う。
これは、ある一定のルールに基づいて記述される、テキスト形式の「設定書」であり、事前にどのようなプロセスを起こすのかとか、どのようなrpmパッケージをインストールするのか、などのような、いわゆるOpsの管轄に当たる部分をカバーする代物と言える。使い方は
docker build -t oreore_image:oreore_tag - < my_dockerfile
のように標準入力からも読ませられるので、とても便利である。
しかし、このdocker buildコマンド、Dockerfileに記述されている1行ごとにdocker commit を行っている模様で、buildの間、dockerコンテナがもりもりと増えていく。正常に終了すれば、これらの「途中経過」コンテナたちは綺麗にremoveされるのだが、不慣れなうちはDockerfileにミスを埋め込むものであり、結果、処理は正常終了せず、大量の「途中経過」コンテナが残留することとなる。
これらを一気に掃除する方法はあるのだが(awkを使ったりする)、正直そのようなことをしなくても、失敗後に掃除はしてほしいと思った。
数日触ってみた感想
「アプリケーションを稼働する環境を、アプリケーションごとパッケージングする物」としては、Dockerは紛れもなく最高の選択肢であると感じた。しかし、僕のように「テスト環境を構築する物」を欲する身としては、かなり貧弱な印象を受けた。おそらくこれはDockerが悪いのではなくて、用途の向き不向きの問題であると認識している。そういった用途には、まだまだVagrantやOpenVZなどに軍配があがると感じた。
また、OpenVZではコンテナに割り当てるリソースのチューニングができるのだが、Dockerにそのような機能があるのかどうかは今のところ見つけることができていない。実際に本番運用している方はその辺をどのように切り抜けているのだろうか、という疑問が残った。
2014-06-17 追記: ツッコミをいただきました。感謝。
ブクマコメなどで、いくつかご意見・ご教示などをいただきました。ありがとうございます。
今のところメモリ・cpuコア・プロセス相対優先度は割り当てられたはず
なるほど、これは知らなかったです。
といいますか、例えばメモリやCPUの割り当てについては、ドキュメンテーションにかいてますね・・・><
Dockerコンテナはアプリケーションの単位で作るもので、サーバにもできるが多分不幸になる
これは薄々感じていたことですね。
サーバにできるけどおそらく不幸になる、というのは、あくまで「長年の経験に基づく勘」レベルですが、監視やコンテナ間通信などで苦労しそうだなあという勝手な想像を抱いており、何となくわからんでもないです。
テスト環境も本番も同じDockerイメージ使いたい
これは実運用環境でDockerを使っているのであれば、そうすべきですよね。逆に、実運用環境がDockerではないのに、テスト環境としてDockerを使ってみようとしたのは、だいぶ良くないアプローチだったかもしれません。
知の高速道路まだ出来てない感
知の高速道路あるなら教えていただきたい・・・!
他の仮想環境と比較してDockerは揮発的過ぎるかもしれない
揮発性がよしとされる用途なら、これで良いのだと思いますし、そういった用途は案外多かったので、この様に流行しているのかなあ、と思います。
いろいろとツッコミたいところ満載だけどめんどくさいし余白が狭い
気が向いたら、お手すきのときにツッコミ入れてくれるとうれしいです。
あと僕のブログ記事は基本的にタイトルが長いです。
Ctrl-dではなく、Ctrl-p + Ctrl-q
https://docs.docker.com/articles/basics/#running-an-interactive-shell
ctrl + d ではない、のですね。ありがとうございます。
こちらの記事の最下部に、
一通り操作したら、[Ctrl]+[d]キーでbashプロセスを終了しましょう。プロセスの終了とコンテナーの停止は連動するため、この時点でコンテナーubuntu1は停止状態になります。
と書いてあったものですので、その通りにしてみた次第でした。
Dockerfileで失敗した時に大量にゴミが残る件
某所で教えていただきました。
確かあれ、途中まで一緒のやつであれば底からビルドが始まるはず
環境がバージョン管理されていることのメリットを活用するために残す
なるほど。うまくいってる所を再度実行する必要は無いんだから、途中経過は残しておくべき、ということですね。
もう一つ追記: この記事について
ご意見などいくつかお寄せいただきましたが、僕はそこまで理解できてる訳じゃないんだなー、というのが露呈した感じですねw
まあ、ちゃんと調べてから書け!という話は真摯に受け止めます。でも、僕は書かないと忘れる質ですし、不完全でも公開しないことにはツッコミも頂けませんので、気が向いたら記事を書きます。たとえそれが不完全でも、です。その代わり、ツッコミは常時大歓迎です。
さて、ちょっとだけ気になったので追記しますが、この記事はDockerのFUDでは「ありません」。こいつ、釣り針でかくしたなーwとかそういう風に捉えられるとちょっと困ります><。なので、素直な気持ちで捉えていただけるとうれしいです。
それとも、「流行の技術に入門してみた」的な記事は、近頃は釣り針なんでしょうかねえ。