2016/10/18 21:08:44

Docker データボリュームコンテナをつくる

dokcer
目次(クリックするとジャンプします)
  • 1:Dockerでのデータの扱い
  • 2:最小限環境コンテナ
  • 2.1:最小限環境を作るのにうってつけのBusyBox
  • 2.2:どんなものか見てみる
  • 3:データコンテナを作る
  • 3.1:データの保存
  • 3.2:データコンテナとして使う
  • 4:補足・ハマりポイント
  • 4.1:データコンテナは起動する必要はない
  • 4.2:データのホスト上の実ディレクトリ
  • 4.3:データのバックアップ
  • 4.3.1:commitとexportではできない
  • 4.3.2:今のところの定石
  • 4.4:ホストのディレクトリをマウントするのと何がちがうのか?
  • 4.5:データボリュームとデータ(ボリューム)コンテナ
  • 5:まとめ

Dockerでのデータの扱い

Dockerで永続データを扱う際にいろいろな方法があることが勉強できました。

いろいろな方法論がありなかなかに難しい分野ではありますが、勉強し甲斐のある部分でもあります。

今回はデータボリュームコンテナ(以下データコンテナ)についてを書こうと思います。

テストのホスト環境はGUN/LInux debian8で、dockerコマンドはsudoなしで実行できるように設定している状況です。

最小限環境コンテナ

データコンテナはなんのプロセスも動かす必要がないので、できるだけ最小限環境なコンテナであって欲しいです。

今回はBusyboxというツールのイメージを使ったコンテナをデータコンテナとして仕上げていきたいと思います。

最小限環境を作るのにうってつけのBusyBox

BusyBoxとは標準UNIXコマンドの主要コマンドをまとめて1つの実行ファイル化したツールです。 各コマンドの実行ファイルがもっているオーバヘッドを、1つのバイナリにすることで大幅に容量削減しています。

このBusyBoxは主要なコマンドとシェルを備えているので、これだけで基本的なLinux環境が整います。

組み込みLInux等のリソースが絞られた中でも環境構築に使えることから、十得ナイフとの呼び声が高いツールだそうです。

なんでもカーネルとBusyBoxとCライブラリとモジュールローダの4つがあれば最低限Linuxとして動くそうですよ。

Dockerコンテナではカーネル、モジュールローダはホストが持っているものをつかう(はず)なので、BusyBoxをベースイメージとすることで、最小限コンテナが作れるというわけです。

余談ですが最小級のディストリビューションであるTinyCoreもBusyBoxを採用していますよね。

どんなものか見てみる

Busyboxはどんなかんじなんでしょう?

以下のコマンドでBusyBoxコンテナを起動してみます。 (-iは標準入力へのアタッチ、-tはttyの割り当て、--rmはコンテナ終了時にコンテナを削除するオプションです)

$ docker run -it --rm busybox

コンテナが起動すると素っ気ないプロンプトが…。

/ # 

BusyBoxが持っているシェルはashというものです。高機能ではありませんが、小型で高速に動くとのことです。Almquist Shellの略だそうです。

試しにlsコマンドを実行してみます。

/ # ls
bin   dev   etc   home  proc  root  sys   tmp   usr   var
/ #

ちゃんと表示されましたね。このlsは個別にインストールされているlsではなく、BusyBoxのlsです。

ちなみに以下のコマンドでBusyBoxが搭載しているコマンドの一覧を確認することができマス。通常の使用に問題ないくらいのコマンドが搭載されていますね。すげぇ。

/ # busybox
BusyBox v1.24.1 (2016-01-12 21:44:20 UTC) multi-call binary.
BusyBox is copyrighted by many authors between 1998-2015.
Licensed under GPLv2. See source distribution for detailed
copyright notices.

Usage: busybox [function [arguments]...]
   or: busybox --list[-full]
   or: busybox --install [-s] [DIR]
   or: function [arguments]...

        BusyBox is a multi-call binary that combines many common Unix
        utilities into a single executable.  Most people will create a
        link to busybox for each function they wish to use and BusyBox
        will act like whatever it was invoked as.

Currently defined functions:
        [, [[, acpid, add-shell, addgroup, adduser, adjtimex, ar, arp, arping, ash, awk, base64, basename, beep, blkid, blockdev, bootchartd, brctl,
        bunzip2, bzcat, bzip2, cal, cat, catv, chat, chattr, chgrp, chmod, chown, chpasswd, chpst, chroot, chrt, chvt, cksum, clear, cmp, comm,
        conspy, cp, cpio, crond, crontab, cryptpw, cttyhack, cut, date, dc, dd, deallocvt, delgroup, deluser, depmod, devmem, df, dhcprelay, diff,
        dirname, dmesg, dnsd, dnsdomainname, dos2unix, du, dumpkmap, dumpleases, echo, ed, egrep, eject, env, envdir, envuidgid, ether-wake, expand,
        expr, fakeidentd, false, fatattr, fbset, fbsplash, fdflush, fdformat, fdisk, fgconsole, fgrep, find, findfs, flock, fold, free, freeramdisk,
        fsck, fsck.minix, fstrim, fsync, ftpd, ftpget, ftpput, fuser, getopt, getty, grep, groups, gunzip, gzip, halt, hd, hdparm, head, hexdump,
        hostid, hostname, httpd, hush, hwclock, i2cdetect, i2cdump, i2cget, i2cset, id, ifconfig, ifdown, ifenslave, ifplugd, ifup, inetd, init,
        insmod, install, ionice, iostat, ip, ipaddr, ipcalc, ipcrm, ipcs, iplink, iproute, iprule, iptunnel, kbd_mode, kill, killall, killall5, klogd,
        last, less, linux32, linux64, linuxrc, ln, loadfont, loadkmap, logger, login, logname, logread, losetup, lpd, lpq, lpr, ls, lsattr, lsmod,
        lsof, lspci, lsusb, lzcat, lzma, lzop, lzopcat, makedevs, makemime, man, md5sum, mdev, mesg, microcom, mkdir, mkdosfs, mke2fs, mkfifo,
        mkfs.ext2, mkfs.minix, mkfs.vfat, mknod, mkpasswd, mkswap, mktemp, modinfo, modprobe, more, mount, mountpoint, mpstat, mt, mv, nameif,
        nanddump, nandwrite, nbd-client, nc, netstat, nice, nmeter, nohup, nslookup, ntpd, od, openvt, passwd, patch, pgrep, pidof, ping, ping6,
        pipe_progress, pivot_root, pkill, pmap, popmaildir, poweroff, powertop, printenv, printf, ps, pscan, pstree, pwd, pwdx, raidautorun, rdate,
        rdev, readahead, readlink, readprofile, realpath, reboot, reformime, remove-shell, renice, reset, resize, rev, rm, rmdir, rmmod, route, rpm,
        rpm2cpio, rtcwake, run-parts, runlevel, runsv, runsvdir, rx, script, scriptreplay, sed, sendmail, seq, setarch, setconsole, setfont,
        setkeycodes, setlogcons, setserial, setsid, setuidgid, sh, sha1sum, sha256sum, sha3sum, sha512sum, showkey, shuf, slattach, sleep, smemcap,
        softlimit, sort, split, start-stop-daemon, stat, strings, stty, su, sulogin, sum, sv, svlogd, swapoff, swapon, switch_root, sync, sysctl,
        syslogd, tac, tail, tar, tcpsvd, tee, telnet, telnetd, test, tftp, tftpd, time, timeout, top, touch, tr, traceroute, traceroute6, true,
        truncate, tty, ttysize, tunctl, ubiattach, ubidetach, ubimkvol, ubirmvol, ubirsvol, ubiupdatevol, udhcpc, udhcpd, udpsvd, uevent, umount,
        uname, unexpand, uniq, unix2dos, unlink, unlzma, unlzop, unxz, unzip, uptime, users, usleep, uudecode, uuencode, vconfig, vi, vlock, volname,
        wall, watch, watchdog, wc, wget, which, who, whoami, whois, xargs, xz, xzcat, yes, zcat, zcip

データコンテナを作る

データの保存

データがちゃんと保存されるかとりあえず作ってみましょう。

Busyboxは公式イメージとして存在しているので、以下のようにしてrunできます。 -vオプションで/dataというボリュームを作っています。またコンテナの名前はdatavolとしてみました。

公式のBusyboxイメージではrun時にshが起動するように設定されていますので、別途/bin/bashなどのようにシェルを指定する必要はありません。オプションのitを付与するだけでOKです。

$ docker run -it -v /data --name datavol busybox

このコマンドでコマンドラインがBusyboxコンテナに移りますので、次にファイルを作ってみましょう。echoコマンドとリダイレクトを使ってdata!! という内容のtest.txtというファイルを作ってみました。

/ # echo "hello" >> /data/test.txt
/ # cat /data/test.txt
data!!

データコンテナとして使う

今度はこのコンテナを他のコンテナでデータコンテナとして利用します。

一度Busyboxコンテナから離脱します

/ # exit

そして今度はデータコンテナを使う側のコンテナをrunしてみます。今回はCentOSにしてみました。

--volumes-fromがデータコンテナをマウントするオプションになります。先ほどのBusyboxコンテナにつけた名前のdatavolを指定しています。

$ docker run -it --volumes-from datavol --name testos centos /bin/bash

(今はデータコンテナとなった)Busyboxコンテナで先ほど作ったファイルを確認してみます。

[root@f1c629fdae43 /]# cat /data/test.txt 
data!!

ちゃんとありますね。

このようにBusyboxコンテナで作ったボリュームを活用することができます。

補足・ハマりポイント

データコンテナは起動する必要はない

通常コンテナのリンクの場合はリンクするコンテナが起動している必要がありますが、データコンテナはデータの保持だけが目的なのでコンテナとして起動している必要がありません。

なのでrunではなくcreateでも構いません。というかcreateの方が楽かも。

$ docker create -it -v /data --name datavol busybox

データのホスト上の実ディレクトリ

さっき作ったtest.txtはどこに保存されているのでしょうか?

コンテナの情報を見てみます。下記のコマンドを実行します。

$ docker inspect datavol

するとたくさん情報が出力されます。以下はマウントに関しての出力を抜粋シタものです。

"Mounts": [
        {
            "Name": "67fb96fd633bbf51c4daa5a37862493f565c15d7e591e2999664f67149765f79",
            "Source": "/var/lib/docker/volumes/67fb96fd633bbf51c4daa5a37862493f565c15d7e591e2999664f67149765f79/_data",
            "Destination": "/data",
            "Driver": "local",
            "Mode": "",
            "RW": true
        }
    ],

この中のSourceの値が先ほどBusyboxコンテナで作ったボリュームのホスト上での実ディレクトリです。

実際に確認してみるとファイルが入っています。

$ sudo cat /var/lib/docker/volumes/67fb96fd633bbf51c4daa5a37862493f565c15d7e591e2999664f67149765f79/_data/test.txt
data!

実ディレクトリを直接扱うことは無いと思いますが、このようにして管理されているんですね。覚えておこうっと。

データのバックアップ

commitとexportではできない

commitexportでデータのバックアップができるという話を散見したのですが、テストしてみるどちらもボリューム上のデータは保存できません。確かにコマンド名からするとできそうな感じ。

でもできません。

docker commit ディレクトリ構造は保存されるが、ボリューム上につくったデータは保存されない。
docker export 同じく構造はエクスポートできるがボリューム上のデータはエクスポートできない。

データのバックアップするにはどうもこれらの方法ではダメですね。

今のところの定石

よく言及されているのは、データコンテナをアプリケーションとは別の管理コンテナにつなげて、データボリュームの中身をさらう方法のようです。以下のページに方法が紹介されていました。

データ・ボリュームのバックアップ・修復・移行(日本語)

これはアプリケーションコンテナを動かしながら、バックアップ処理専用コンテナを走らせるたりすることができるということです(よね?)

アプリケーションコンテナにデータが張り付いている状態だとこういうことはなかなか面倒なので、良い方法かもしれません。

ホストのディレクトリをマウントするのと何がちがうのか?

おそらくデータディレクトリ構造の抽象化(汎化?)ができる点ではないかと思っています。

ホストのディレクトリをマウントする場合、ディレクトリ階層や名前や権限がどこのホストでも同じというわけには行きません。

コンテナ側に変化がなくてもホスト側の構成に変化があるとボリュームに不具合が出かねません。と思います。

しかしデータコンテナであればそのへんの違いを吸収できます。

どこでも同じ状態でデータディレクトリ構造を作れるというのは確かに便利な気がします。

データボリュームとデータ(ボリューム)コンテナ

データボリュームはコンテナの中に作られたボリュームであくまでそのコンテナと運命を共にします。

データ(ボリューム)コンテナは今回記事にした件で、データ保存専用のコンテナのことを指します。

複数のコンテナからデータを参照する場合、どこかのコンテナだけに所属しているボリュームを参照しあうのはとても複雑なリンクが必要になり心が折れそうな気がします。

なのでデータ(ボリューム)コンテナでアプリケーションからデータを分離することで、コンテナのリンク構造を単純化できるメリットがありそうな、そんな気がしています。

データボリュームはそのコンテナ特有のデータを扱う場合に使い、データコンテナは複数のコンテナから参照されるデータを収める場合に使うといいのかなと思っておりマス。

まとめ

Docker勉強するほど便利に思えてきて仕方がない。

データの扱いもちょっと見えてきたので楽しくなってきたデス。