目次
概要
Debian8.6にDocker1.13.0をインストールし、そこでCentOSのコンテナを作成する。コンテナで適当に作業を行い、コミットして再利用するところまでをチュートリアルする。Dockerそのものに関する説明はそんなに無い。Dockerfileによる構築も扱わない。Dockerの雰囲気が味わえれば良いかなぐらい。
前提
以下の環境にDockerを導入する
要素 | バージョン |
---|---|
Debian | 8.6 |
Docker | 1.13.0 |
Dockerとは
Dockerはサーバ仮想化ソフトウェアの一つ。ただし、VMWareなどの、ハイパーバイザ型における完全な仮想化を提供するのではなく、ホストOSのカーネルを共有し、その上に「コンテナ」と呼ばれるOSのシステムレベルで仮想化されたゲストOSを取り扱う。
つまり、VMWareなどの仮想化と比べると不完全な仮想化で、ゲストOSの独立レベルは低い。Dockerではそのような構成にすることで以下のメリットが得られる。
- 個別にOSを立ち上げる必要がないので作成や起動、破棄が高速
- 使用する資源(CPU/メモリ/ストレージ)が少ない
- オーバーヘッドが少なく性能劣化が殆ど無い
よって、Dockerの使い方としては、永続的に稼働している環境というよりは、頻繁に作成、破棄が行われる使い捨ての環境に用いることが向いていると言える。
個人的には開発環境を手軽に構築、共有するのに使っていけたら良いなと思う
Dockerのインストール
DockerはホストOSのカーネルを共有するので、当然Linux上に構築するのが望ましい。一応WindowsやMacでもDockerを導入することができるが、本記事ではMac上に構築したDebianの上にDocker環境を構築する。
例によってapt-getでインストールしたいところだが、Debianに標準で含まれてるaptリポジトリにdockerが含まれていないので、手作業でリポジトリを追加する必要がある。
/etc/apt/sources.list
が、aptのリポジトリリストなので、これに以下を追記する。ドメイン的に日本のDebian公式リポジトリなんだと思う。
deb http://ftp.jp.debian.org/debian/ sid main deb-src http://ftp.jp.debian.org/debian/ sid main
で、アップデート
$ sudo apt-get update
dockerをインストール
$ sudo apt-get install docker.io
インストールできたことを確認
docker -v Docker version 1.13.0, build 49bf474
Dockerイメージのインストール
Dockerでコンテナを作成するためには、元となるイメージが必要になる。
Dockerには、DockerイメージのリポジトリであるDockerHubを通じて、Dockerイメージを共有する機能があるので、今回はそちらからCentOSのDockerイメージをインストールする。
権限周りがやかましいのでここからはsudo権限を持たせる
$ sudo -s # whoami root
DockerHubからDockerイメージをダウンロードする場合は、docker pullコマンドを使用する。今回はCentOSをダウンロードする。
# docker pull centos Using default tag: latest latest: Pulling from library/centos 93857f76ae30: Already exists Digest: sha256:4eda692c08e0a065ae91d74e82fff4af3da307b4341ad61fa61771cc4659af60 Status: Downloaded newer image for centos:latest
ダウンロード済みのDockerイメージの一覧の確認は、docker imagesコマンドで行う。centosのDockerイメージがダウンロードされていることが確認できる。
# docker images REPOSITORY TAG IMAGE ID CREATED SIZE centos latest a8493f5f50ff 3 weeks ago 192 MB
Dockerイメージが仮想マシンのイメージと同じようなものと考えると、192MBというのは実に小さい。仮想マシンイメージと異なり、カーネルが含まれていないからである。
DockerコンテナによるHello World
DockerコンテナはDockerイメージから生成される仮想環境の実体である。一つのイメージから複数のコンテナを生成できるので、オブジェクト指向におけるクラスとインスタンスの関係のようなものだ。
コンテナ起動は、docker run コマンドを用いる。といっても、コンテナはホストOSのカーネルを用いてプロセスを実行するものなので、どんなプロセスを実行するかを指定する必要がある。
ここでは、”Hello Docker World”という文字列をechoするプロセスを実行するだけのコンテナを立ち上げてみる。
# docker run centos echo "Hello Docker World!" Hello Docker World! #
“Hello Docker World!” の文字列が出力され、コマンドの実行は終了する。ではこの時コンテナはどのような状態なのか、docker psコマンドで確認する。psコマンドは基本的にプロセスが動いているコンテナの一覧を表示するが、-aオプションを付与することで終了しているコンテナも表示する。
# docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 627496810cd6 centos "echo 'Hello Docke..." About a minute ago Exited (0) About a minute ago angry_blackwell
627496810cd6がコンテナのID(ユニーク)で、angry_blackwellがコンテナの名称である。名称はユニークでない可能性もあるが、コンテナ生成時に任意の名称を付けることができる。
このコンテナはコマンド”echo ‘Hello Docker…”を実行完了し、Exited状態に移行している。
コンテナの削除
前項で作成したコンテナは、Hello Docker World!を出力してお役御免なので、docker rmコマンドを用いて削除する。削除の際はコンテナIDがコンテナ名を指定する。特に重複の可能性がないのであれば、可読性のあるコンテナ名を使ったほうが良さそう。
# docker rm angry_blackwell angry_blackwell
削除されたことを確認
docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
コンテナを作成し、アクセスする
“アクセスする”という言い方には語弊がある気がするが、つまりSSHでアクセスしたときみたいにコンテナ内でシェルを使いたいということである。前項の用に、コンテナを起動する際にプロセスを指定することで、コンテナはプロセスを実行し、実行完了するまで稼働し続ける。
つまり、コンテナで実行するプロセスにシェルを指定してあげればよい。ここではbashを用いてシェルを利用することにする。また、-itオプションを付与することで、現在の標準入出力を引き継ぐことができるので、シェルを利用するためには必須となる。
# docker run -it centos /bin/bash [root@a3936fcb8f31 /]# cat /etc/redhat-release CentOS Linux release 7.3.1611 (Core)
コンテナ内でシェルを利用できるようになり、catコマンドでコンテナ内のOS情報ファイルを出力できていることがわかる。CentOSと書かれているが、実際にはホストOSであるDebianのカーネルを利用している。ややこしい。
コンテナ内でRubyをインストールする
コンテナ内に開発環境を作る、というほど大層なことは本記事では行わないが、その前進としてRubyをインストールして、適当なスクリプトを作成してみる。
カーネルはDebianのものを使ってるが、コンテナはCentOSなので、apt-getではなくyumを用いてRubyをインストールする。ここではRubyのバージョンとかは気にせず、簡単にインストールできる方法を用いる。
[root@a3936fcb8f31 /]# yum install ruby
インストールできたことを確認。どうやらこのコンテナ内のyumで標準でインストールできるRubyは2.0.0らしい。だいぶ古い。
[root@a3936fcb8f31 /]# ruby -v ruby 2.0.0p648 (2015-12-16) [x86_64-linux]
適当にスクリプトを作成する。と思ったらvimも入っていないので先にvimをインストールする
[root@a3936fcb8f31 /]# yum install vim
インストールしたvimで、/fizzbazz.rb を作成する。フィズバズについてはWikipediaを参照。ここでは、コマンドライン引数Nを取り、1〜Nに対してのフィズバズを行うプログラムを作成する。カッコいいアルゴリズムでも使おうと思ったが、コードの内容は本記事とは関係ないので普通に書く。
N = ARGV[0].to_i N.times do |m| if m % 3 == 0 && m % 5 == 0 puts "Fizz Buzz" elsif m % 3 == 0 puts "Fizz" elsif m % 5 == 0 puts "Buzz" else puts m end end
実行してみるとこんな感じ
root@a3936fcb8f31 /]# ruby /fizzbazz.rb 10 Fizz Buzz 1 2 Fizz 4 Buzz Fizz 7 8 Fizz
フィズバズを持つDockerイメージを作成する
前項では、コンテナ内でRubyとvimのインストール及びフィズバズプログラムの作成を行った。しかし、これからはあくまでコンテナ内に存在するだけで、元となったDockerイメージに存在するものではない。したがって、本コンテナを削除してしまえば前項の作業は水の泡となってしまい、再利用することができない。
そこで、本コンテナを元にしたDockerイメージを新たに作成する。つまり、「CentOSのイメージ」を元に、「CentOSの中にRubyとVimとフィズパズスクリプトが入ったイメージ」を作成するということだ。
コンテナからイメージを作成するには、docker commitコマンドを用いる。以下では、”unruffled_blackwell”(本コンテナの名前)を元に、”fizzbazz”というイメージを作成する。
# docker commit unruffled_blackwell fizzbazz sha256:7bf2cab2f57325c76c67affd54f7545ecc7ecde41925e7cd2404ba6c602e05a7
イメージが作成されたことを確認。RubyとVimを入れたせいで容量がかなり増えている。それでも348MBだが。
# docker images REPOSITORY TAG IMAGE ID CREATED SIZE fizzbazz latest 7bf2cab2f573 26 seconds ago 348 MB centos latest a8493f5f50ff 3 weeks ago 192 MB
作成したイメージから新たにコンテナを生成する
とりあえず先程Rubyやvimをインストールしたコンテナはもう不要なので削除する。以下は全てのコンテナを削除するおまじない的なコマンド。といっても、「全てのコンテナ一覧のコンテナIDのみ標準出力し、それらをdocker rmの引数にする」という一連の処理を行っているだけ。
# docker ps -aq | xargs docker rm a9f5293d88a0 a3936fcb8f31 0357fffe82b2
これでRubyやVimがインストールされたコンテナが削除された。インストール作業は水の泡となってしまった。
# docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
ということはもちろん無く、以下のように先程作成したコンテナを用いてフィズバズプログラムを実行できることが確認できる。
# docker run fizzbazz ruby /fizzbazz.rb 10 Fizz Buzz 1 2 Fizz 4 Buzz Fizz 7 8 Fizz
まとめ
以上より、Dockerを用いることで非常に手軽にCentOSの環境を導入し、そこでRubyの開発環境(の卵)を作成することができた。さらに、Ruby開発環境を持ったCentOSのイメージを作成し、手軽に再利用できるようになった。
また、本記事では割愛しているが、DockerHubを用いて、本記事で作成したイメージをpushすることで、他のユーザがそれを再利用することもできる。逆に他のユーザが作成したイメージからコンテナを作成することもでき、例えばRubyの開発環境に留まらず、Ruby on railsの開発環境一式が揃ったイメージなども数多く出回っている。
つまり、今後何らかの技術を使って開発を行いたくなったら、その開発環境に適合するイメージを探して、docker pullするだけでスグに環境構築を行えるということだ。
完全に適合したイメージが無ければ、近いものをpullし、自分でカスタマイズしてcommit,pushすればさらに特定の目的に特化したイメージを流通させることができる。
今回、本記事を書くために初めてDockerを利用したが、まだまだ使いみちは模索中で、基礎的なコマンドしか抑えられていないので、今後はさらに実用的な使い方ができるように勉強し、実務にも取り入れられたらなと画策している。