CUBE SUGAR CONTAINER

技術系のこと書きます。

CentOS7 で Docker を使ってみる

Docker はコンテナ型ハードウェア仮想化と呼ばれる技術を用いたアプリケーション配布用のプラットフォーム。

今回はその Docker を CentOS7 で一通り使ってみる。

$ cat /etc/redhat-release 
CentOS Linux release 7.1.1503 (Core) 
$ uname -r
3.10.0-229.14.1.el7.x86_64

コンテナ型仮想化とは

ハードウェア仮想化には、大きく分けてハイパーバイザ型とコンテナ型というふたつがある。 どちらにおいても、ホスト OS の上で仮想化された複数のゲスト OS を実行することができる。

まず、ハイパーバイザ型ではハードウェアをソフトウェアまたはハードウェアの支援機能を使ってエミュレーションする。 ゲスト OS はエミュレーションされた仮想的なハードウェアの上で動作することになる。

それに対してコンテナ型では、ホスト OS の内部に隔離されたリソースを用意する。 ゲスト OS はその隔離されたリソースを使って動作することになる。 隔離されたリソースとは、具体的にはプロセスやネットワーク機能 (ネームスペース) を指す。

コンテナ型は、ハイパーバイザ型に比べると実行に必要なオーバーヘッドが小さいというメリットもある。 ただし、あくまでホスト OS の中の隔離されたリソースを使って動作するという特性上、ちょっとクセがある。 例えば Docker ではひとつのプロセスをホスト OS から隔離してゲスト OS に使わせるため、複数のプロセスを動かすにはまずプロセスマネージャなどを使って最初のひとつを fork する必要がある。

Docker をインストールする

CentOS7 であれば追加のリポジトリなどを入れることなく Docker をインストールできる

$ sudo yum -y install docker
...(省略)...
完了しました!

インストールできたら Docker のサービスを開始する。

$ sudo systemctl start docker
$ sudo systemctl enable docker

Docker イメージをダウンロードする

まずは、公式リポジトリに登録されている CentOS6 の Docker イメージをダウンロードしてみる。 これにはゲスト OS の rootfs が入っている。

$ sudo docker pull centos:6
6: Pulling from docker.io/centos

6a7b54515901: Pull complete 
e788880c8cfa: Pull complete 
1debf8fb53e6: Pull complete 
72703a0520b7: Pull complete 
47d44cb6f252: Already exists 
docker.io/centos:6: The image you are pulling has been verified. Important: image verification is a tech preview feature and should not be relied on to provide security.


Digest: sha256:045c14a29c8b318678455a788546705a238249595cdad59f8b880fd3fb21f37a
Status: Downloaded newer image for docker.io/centos:6

動かしてみる

まずは Docker コンテナを起動してみる。 起動する際には、実行するコマンドを指定する。 以下では echo コマンドでメッセージを出力させている。

$ sudo docker run centos:6 /bin/echo "Hello, World"
Usage of loopback devices is strongly discouraged for production use. Either use `--storage-opt dm.thinpooldev` or use `--storage-opt dm.no_warn_on_loop_devices=true` to suppress this warning.
Hello, World

上記では、何やら警告が出ていた。 本番環境でループデバイスを使うのは非推奨ということらしい。 とりあえず今は検証用に過ぎないので警告を消す方向で。

$ sudo sed -i -e '
  s:\(DOCKER_STORAGE_OPTIONS=\):\1"--storage-opt dm.no_warn_on_loop_devices=true":
' /etc/sysconfig/docker-storage

警告を表示しないように起動オプションを変更したら Docker サービスを再起動する。

$ cat /etc/sysconfig/docker-storage | tail -n 1
DOCKER_STORAGE_OPTIONS="--storage-opt dm.no_warn_on_loop_devices=true"
$ sudo systemctl restart docker

再度実行すると警告は表示されない。

$ sudo docker run centos:6 /bin/echo "Hello, World"
Hello, World

端末を取得する

コンテナの起動時に端末を取得する場合は -i オプションを付ける。

$ sudo docker run -i -t centos:6 /bin/bash
# cat /etc/redhat-release 
CentOS release 6.7 (Final)
# uname -r
3.10.0-229.14.1.el7.x86_64
# exit

ハイパーバイザ型の仮想化であれば端末を手放してもシャットダウンしていない限り再度ログインできるが、 コンテナ型仮想化の Docker の場合 exit で抜けるとプロセスが終了してしまう。 起動中のコンテナを docker ps コマンドで確認してみよう。

$ sudo docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES

過去に実行されていたコンテナは docker ps コマンドに -a オプションを付けると確認できる。

$ sudo docker ps -a
CONTAINER ID        IMAGE               COMMAND                CREATED              STATUS                      PORTS               NAMES
00c381768f16        centos:6            "/bin/bash"            About a minute ago   Exited (0) 22 seconds ago                       kickass_sinoussi    
27833b767635        centos:6            "/bin/echo 'Hello, W   6 minutes ago        Exited (0) 6 minutes ago                        hopeful_hopper      
eea7b32a8c08        centos:6            "/bin/echo 'Hello, W   17 minutes ago       Exited (0) 17 minutes ago                       furious_jang        

プロセスを終了せずにコンテナから抜ける (端末を手放す) には Ctrl+p, Ctrl+q を入力する

$ sudo docker run -i -t centos:6 /bin/bash
#

今度はコンテナから抜けても起動したままであることが確認できる。

$ sudo docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
72d863377ecf        centos:6            "/bin/bash"         41 seconds ago      Up 40 seconds                           happy_goodall       

起動中のコンテナの端末を再度取得するには docker attach コマンドを使う。

$ sudo docker attach 72d863377ecf
# cat /etc/redhat-release 
CentOS release 6.7 (Final)

自分用の Docker イメージを作ってみる

次に、自分でカスタマイズを施した Docker イメージを作ってみる。 一旦作ってしまえば同じコンテナが何度も作れるようになる。

docker images コマンドを使うと今ローカルにあるイメージを確認できる。

$ sudo docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
docker.io/centos    6                   72703a0520b7        13 days ago         190.6 MB

まずは先ほどリポジトリから pull してきた CentOS6 のイメージからコンテナを起動して /var/tmp 以下にテキストファイルを設置しておく。

$ sudo docker run -i -t centos:6 /bin/bash
# cat << EOF > /var/tmp/greet.txt
Hello, World
EOF
# exit

今実行したコンテナの ID を docker ps コマンドで確認しておく。

$ sudo docker ps -a | head -n 2
CONTAINER ID        IMAGE               COMMAND                CREATED             STATUS                      PORTS               NAMES
149ce7af73d5        centos:6            "/bin/bash"            5 minutes ago       Exited (0) 23 seconds ago                       hungry_payne        

docker commit コマンドで確認したコンテナからイメージを作ることができる。

$ sudo docker commit 149ce7af73d5 amedama/centos:6
12c4ba192dc361f2870ed485d2141a34cc4b14020e5652c1d929f26a47a21010

新しくイメージが登録された。

$ sudo docker images
REPOSITORY          TAG                 IMAGE ID            CREATED              VIRTUAL SIZE
amedama/centos      6                   12c4ba192dc3        11 seconds ago       386.2 MB
docker.io/centos    6                   72703a0520b7        13 days ago          190.6 MB

作成したイメージからコンテナを起動すると、確かに /var/tmp 以下にテキストファイルがあることが確認できる。

$ sudo docker run amedama/centos:6 /bin/cat /var/tmp/greet.txt
Hello, World

ちなみにコンテナの履歴は消さないといつまでも残り続けてディスクを圧迫するようなので定期的にクリーンアップしよう。

$ sudo docker rm $(sudo docker ps -a -q)

Dockerfile を使ってイメージを作る

先ほどの例では起動したコンテナからイメージを作ったけど、イメージを作る場合は Dockerfile という設定ファイルを使った方が便利。

試しに MySQL をインストールして起動するイメージを作ってみる。

$ cat << EOF > Dockerfile
FROM centos:6
MAINTAINER example <example@example.jp>

RUN yum -y install mysql-server

EXPOSE 3306

CMD ["/usr/bin/mysqld_safe", "--skip-grant-tables"]

EOF

Dockerfile の書き方は公式サイトのリファレンスを参照のこと。

https://docs.docker.com/reference/builder/

Dockerfile を元にイメージをビルドする。

$ sudo docker build -t amedama/centos:mysql .
...(省略)...
Successfully built 4f2ccbbabf0c

ビルドしたイメージを元にコンテナを起動する。 -d オプションはデーモンモードで標準入出力を表示しないというもの。 -p オプションはコンテナのポートをホスト OS 経由でアクセスできるようにするためのもの。 MySQL 用にコンテナの TCP:3306 ポートを、ホスト OS の TCP:3306 ポートと接続している。

$ sudo docker run -d -p 3306:3306 -t amedama/centos:mysql
64a36059d1055d6f1ab630e45de37f93f494e4b68fd3c6458e56a5e8b6c23a17

コンテナに接続するために MySQL クライアントをインストールする。

$ sudo yum -y install mysql

インストールできたら mysql コマンドで localhost に接続する。 実際にアクセスしている先は Docker コンテナということになる。

$ mysql -u root -h 127.0.0.1
Welcome to the MariaDB monitor.  Commands end with ; or \g.
Your MySQL connection id is 1
Server version: 5.1.73 Source distribution

Copyright (c) 2000, 2015, Oracle, MariaDB Corporation Ab and others.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

MySQL [(none)]> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
+--------------------+
1 row in set (0.00 sec)

MySQL [(none)]> Bye

ばっちり。

まとめ

今回は CentOS7 を使って Docker を一通り使ってみた。 CentOS6 の頃は追加のリポジトリを必要としていた Docker も 7 では標準でサポートされている。 ちなみに、Docker の RHEL/CentOS6 サポートは既に打ち切られているので、Docker ホストに RHEL/CentOS を使う場合は必ず 7 を使うようにしよう。

blog.amedama.jp