https://docs.docker.com/userguide/dockervolumes/ (日本語訳)
まず「Data volume」というもの自体が何であるかということを理解する必要がある。
コンテナ上に存在する特別なデータ領域(ディレクトリ)として扱われるという位置付けで、コンテナ間の共有に利用、Volume に対して直接データの書き換えが可能、かつコンテナイメージの変更点に影響を受けないという、外部からマウントされたストレージというように見える存在といえそう。
コンテナを作成する際に -v
オプション (あるいは Dockerfile を使ってビルドする場合は VOLUME
) でディレクトリパスを指定すると、そのパスが Data volume となる。1コンテナに複数の Data volume を用意することも可能な模様。
Data volume の作成
以下の例では、作成するコンテナに /data というパスが data volume となるよう設定している。
$ docker run -i -t -v /data --name storage busybox /bin/sh
(以下 Container による /bin/sh)
/ # ls -la
total 60
drwxr-xr-x 25 root root 4096 Jul 8 14:10 .
drwxr-xr-x 25 root root 4096 Jul 8 14:10 ..
-rwxr-xr-x 1 root root 0 Jul 8 14:10 .dockerenv
-rwxr-xr-x 1 root root 0 Jul 8 14:10 .dockerinit
drwxrwxr-x 2 root root 4096 May 22 2014 bin
drwxr-xr-x 2 root root 4096 Jul 8 14:10 data
drwxr-xr-x 5 root root 380 Jul 8 14:10 dev
drwxr-xr-x 6 root root 4096 Jul 8 14:10 etc
drwxrwxr-x 4 root root 4096 May 22 2014 home
drwxrwxr-x 2 root root 4096 May 22 2014 lib
lrwxrwxrwx 1 root root 3 May 22 2014 lib64 -> lib
lrwxrwxrwx 1 root root 11 May 22 2014 linuxrc -> bin/busybox
drwxrwxr-x 2 root root 4096 Feb 27 2014 media
drwxrwxr-x 2 root root 4096 Feb 27 2014 mnt
drwxrwxr-x 2 root root 4096 Feb 27 2014 opt
dr-xr-xr-x 129 root root 0 Jul 8 14:10 proc
drwx------ 2 root root 4096 Jul 8 14:10 root
lrwxrwxrwx 1 root root 3 Feb 27 2014 run -> tmp
drwxr-xr-x 2 root root 4096 May 22 2014 sbin
dr-xr-xr-x 13 root root 0 Jul 8 14:10 sys
drwxrwxrwt 3 root root 4096 May 22 2014 tmp
drwxrwxr-x 6 root root 4096 May 22 2014 usr
drwxrwxr-x 4 root root 4096 May 22 2014 var
試しにこのまま Data volume 内に適当なファイルを作ってみる。
/ # cd /data
/data # echo "add on storage" > ./foo.txt
/data # cat foo.txt
add on storage
対象コンテナの Data volume の状態は docker inspect
で掲載される情報でチェックできる。
{
....
"Volumes": {
"/data": "/mnt/sda1/var/lib/docker/volumes/739a035f219f82ba922c93d54d43b790755c280948a135da3e741ecaa52eee6f/_data"
},
"VolumesRW": {
"/data": true
},
....
}
元になるコンテナにそのディレクトリパスが存在している必要はなさそう。存在しなければそのパスのディレクトリとして利用可能になるし、既存パスであればそのディレクトリパスが Data volume として扱われることになる模様。
ローカルパスのマウント
この -v
オプションを用いて、Docker コマンドを実行する自分自身のローカルパスをコンテナ上の任意のディレクトリパスとしてマウントすることができる。(さらっと2回目のときに使っている)
以下のコマンド例では、ローカルパス /path/to/src をコンテナの /src としてマウントしている。コンテナの /src にアクセスすると、ローカルの /path/to/src が (存在していれば) 表示される。
$ docker run -i -t -v /path/to/src:/src busybox /bin/sh
(以下 Container による /bin/sh)
/ # ls -la /src
この /src もまた Data volume である。
Data volume を他コンテナと共有する (data volume container)
前述のとおり、Data volume はコンテナ間の共有のために利用することを想定している。Docker では、Data volume を持ったコンテナを別のコンテナへマウントすることで、Data volume の領域をマウントした側のコンテナで参照や更新を行うことができる。
この時の被マウント側、すなわち Data volume を持ったコンテナのことを Data volume container と呼んでいる。永続させたいデータの格納領域を Data volume container に持たせた上で、その永続データの読み書きを行うサービスのコンテナに Data volume container をマウントした上で自分自身は Immutable に扱うといった利用法になりそう。
Data volume container を試す
新たに起動するコンテナに --volumes-from
オプションで既に起動中の storage コンテナを Data volume container として指定。起動後, storage コンテナ側で Data volume として振舞っている /data が新しい serviceコンテナ側でも見えていてデータを参照することができる。
$ docker run -i -t --volumes-from storage --name service busybox /bin/sh
/ # ls -la /data
total 12
drwxr-xr-x 2 root root 4096 Jul 8 14:59 .
drwxr-xr-x 25 root root 4096 Jul 8 15:02 ..
-rw-r--r-- 1 root root 15 Jul 8 15:00 foo.txt
/ # cat /data/foo.txt
add on storage
では新しい service コンテナ側でこの Data volume を操作してみる。
# echo "add on service" >> /data/foo.txt
storage コンテナ側でチェックしてみると、service コンテナ側による変更が参照できる。
# cat /data/foo.txt
add on storage
add on service
バックアップ、リストア
Data volume からデータを抽出したり、逆に注入したりすることで、バックアップ/リストアのフローを行うことができる。
バックアップの場合は、Data volume container とローカルパスをマウントしたコンテナ上で、コンテナ側の必要な Data volume 上のファイルをマウントしたローカルパス側の Data volume に転送してあげればよい。
$ docker run --volumes-from storage -v $(pwd):/backup busybox tar cvf /backup/backup.tar /data
これで、このコマンドを実行したディレクトリパスには backup.tar ファイルが作成される。中身を確認してみると、先ほどまでのテスト実行ファイルが含まれていることがわかる。
$ tar xf backup.tar
$ cat ./data/foo.txt
add on storage
add on service
バックアップしている内容を新しい Data volume container へリストア。
$ docker run -v /data --name storage2 busybox /bin/sh
$ docker run -i -t --volumes-from storage2 -v $(pwd):/backup busybox /bin/sh
# tar xf /backup/backup.tar -C /
# cat /data/foo.txt
add on storage
add on service
考察
ドキュメントをみると、--volues-from
で指定するコンテナ (複数可) 側で定義されている全ての Data volume を作成コンテナにマウントする、と書かれている。
Data volume container の Data volume をマウントする側のコンテナのどういったディレクトリパスとするか、といったような指定はできないように見受けられる。したがって、マウントする側のコンテナ内サービスがどういったディレクトリパスを利用するのかという仕様に基づいて Data volume container を用意する必要がある。(たとえばサービスのデータベースサーバがデータを永続化するためのストレージ領域を /opt としているならば、Data volume container の Data volume も /opt として作成しなければならない。)
何とか任意のディレクトリパスとしてマウントしたい、という要望に対して
-
Data volume container を inspect して Data volume のフルパスを調べ、そのフルパスをサービスコンテナの Data volume として使う(
--volumes-from
を使わない)
http://stackoverflow.com/questions/23137544/how-to-map-volume-paths-using-dockers-volumes-from -
マウント側コンテナでシンボリックリンクを張る (ディレクトリパス依存性の反転)
http://stackoverflow.com/questions/24871006/how-to-mount-docker-container-volumes-to-different-path
といった案がある模様。
… 仮にサービスコンテナ側の仕様変更でパスが変わったとしてもリストアして Data volume container を作り直せばいいだけだし、基本的には普通に「サービスコンテナ側の仕様に基づいて Data volume container を作る」でいいと思う。