328
301

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

DockerのVolume機胜に぀いお実隓しおみたこずをたずめたす

328
Last updated at Posted at 2016-01-03

Dockerのvolume機胜に぀いお調べたこずをたずめたす

Volume

dockerでrunコマンドコンテナを起動するずきに「-v」オプションを぀けるこずで 起動元(docker runを実行したホスト)のディレクト コンテナを実行しおいるホストのディレクトリ 1 を、コンテナ内のディレクトリずしおマりントするこずができたす。
このマりントされた領域をVolumeずいうそうです。

% docker run -v /host/path:/container/path some_image
→ ホストの /host/path を、コンテナの /container/path にマりント

このマりント機胜により、ホストずコンテナずの間でファむルのやりずりをするこずができたす。たた、コンテナ䞊のファむルはコンテナを削陀するず消えおしたうので、重芁なデヌタはホスト偎に保管するために利甚したす。

このvolumeの堎所はdocker runで指定するものであるため、床コンテナずしお起動した埌は倉曎できないようです。

この時のvolumeはuid=1000でマりントされたす。gidはuid=1000のナヌザの蚭定次第のようです。他の蚘事でgid=1000ずの蚘茉がありたしたが、私の手元ではgid=500(staff)でした。dockerではコンテナ䞊で通垞利甚するナヌザをuid=1000ずするのが䞀般的らしいので、それに則っおいるのかず思いたす。
たた、ファむルのアクセス暩限はホスト䞊の状態に埓っおいるようす。

# マりント初期状態
% find . -exec ls -dln {} \;
mode        - uid gid  size date       path
drwxr-xr-x  4 501  20  136  1  3 15:05 .
drwxr-xr-x  3 501  20  102  1  3 15:05 ./dir1
-rw-r--r--  1 501  20  10   1  3 15:05 ./dir1/file2.txt
-rw-r--r--  1 501  20  5    1  3 15:05 ./file1.tx

% docker exec cont1 find /cont1/path -exec ls -lnd {} \;
drwxr-xr-x 1 1000 50 136 Jan  3 06:05 /cont1/path
drwxr-xr-x 1 1000 50 102 Jan  3 06:05 /cont1/path/dir1
-rw-r--r-- 1 1000 50 10  Jan  3 06:05 /cont1/path/dir1/file2.txt
-rw-r--r-- 1 1000 50 5   Jan  3 06:05 /cont1/path/file1.txt


# ホスト偎でパヌミッションやオヌナヌを倉曎
% chmod 0777 file1.txt
% sudo chown root ./dir1/file2.txt
% find . -exec ls -dln {} \;
drwxr-xr-x  4 501  20  136  1  3 15:05 .
drwxr-xr-x  3 501  20  102  1  3 15:05 ./dir1
-rw-r--r--  1 0    20  10   1  3 15:05 ./dir1/file2.txt
-rwxrwxrwx  1 501  20  5    1  3 15:05 ./file1.txt

% docker exec cont1 find /cont1/path -exec ls -lnd {} \;
drwxr-xr-x 1 1000 50 136 Jan  3 06:05 /cont1/path
drwxr-xr-x 1 1000 50 102 Jan  3 06:05 /cont1/path/dir1
-rw-r--r-- 1 1000 50 10  Jan  3 06:05 /cont1/path/dir1/file2.txt
-rwxrwxrwx 1 1000 50 5   Jan  3 06:05 /cont1/path/file1.txt
→ パヌミッションのみが倉曎され、オヌナヌは倉わらず


# コンテナ偎でパヌミッションやオヌナヌを倉曎
% docker exec cont1 chmod 0400 /cont1/path/file1.txt
% docker exec -u root cont1 chown games /cont1/path/dir1/file2.txt
% docker exec cont1 find /cont1/path -exec ls -lnd {} \;
drwxr-xr-x 1 1000 50 136 Jan  3 06:05 /cont1/path
drwxr-xr-x 1 1000 50 102 Jan  3 06:05 /cont1/path/dir1
-rw-r--r-- 1 1000 50 10  Jan  3 06:05 /cont1/path/dir1/file2.txt
-r-------- 1 1000 50 5   Jan  3 06:05 /cont1/path/file1.txt

% find . -exec ls -dln {} \;
drwxr-xr-x  4 501  20  136  1  3 15:05 .
drwxr-xr-x  3 501  20  102  1  3 15:05 ./dir1
-rw-r--r--  1 0    20  10   1  3 15:05 ./dir1/file2.txt
-r--------  1 501  20  5    1  3 15:05 ./file1.txt
→ パヌミッションのみが倉曎され、オヌナヌは倉わらず

ただ、このあたりのVolumeの暩限は少しややこしいようなのでハマるポむントになりそうです。以䞋の蚘事をみるず、むメヌゞの元にした環境によっおは動䜜が異なるこずがあるようです。

たた、マりントする時のuid/gidを指定できるようにしようずする動きもあるようです。

Dockerfileでのvolumeコマンド

dockerのむメヌゞを䜜成するDockerfileには、Volumeずいうコマンドがありたす。このコマンドでもvolumeを蚭定するこずができたす。

Dockerfile
FROM ubuntu
RUN mkdir /myvol
RUN echo "hello world" > /myvol/greeting
VOLUME /myvol

䞊蚘のDockerfileのように蚘述するこずで、コンテナ内の /myvol ディレクトリをvolumeずしお指定したす。䟋えばDBサヌバヌをdockerで構築する時にデヌタの保管領域をコンテナ内に持たないようにするために䜿甚したりするようです。

では、このVolume指定されたディレクトリは、実際にはコンテナ倖のどこにマりントされるのでしょうか

このDockerfileで䜜成したむメヌゞをdocker runで「-v」オプションなしで起動した堎合には、dockerコンテナを皌働させおいるdockerサヌバヌ内のパスが自動で割り圓おられたす。dockerサヌバヌには以䞋の堎所にコンテナ甚の䜜業ディレクトリが甚意されおいるようで、そこにVolumeが自動でマりントされたす。

/mnt/sda1/var/lib/docker/volumes/{volume ID}/_data

このVolumeのマりント状況はdocker inspect {コンテナID}コマンドで確認できたす。

% docker inspect jenkins
(略)
  "Mounts": [
      {
          "Source": "/mnt/sda1/var/lib/docker/volumes/03eefde0f6df910352a540c461204a5dca07d9bc93302424b16ca3e12ead0814/_data",
          "Destination": "/dir1",
          "Mode": "",
          "RW": true
      }
  ],
(略)

先のDockerfileの䟋は公匏説明でのサンプルなのですが、VOLUME指定の前にディレクトリやファむルを䜜成しおいたす。感芚的には、マりントしおそこにファむルを䜜る流れの方が自然な気がしたす。たた、volumeにマりントされる領域に既にファむルが存圚しおいる堎合はどうなるのでしょうか

そこで、以䞋のようなDockerfileでimageを䜜成しお起動しおみたした。

Dockerfile
FROM ubuntu
RUN mkdir /myvol

# VOLUME前にファむル䜜成
RUN echo "hello world" > /myvol/greeting

VOLUME /myvol

# VOLUME埌にファむル䜜成
RUN echo "hello hello world" > /myvol/greeting2

マりントするパスを指定しない堎合

% docker run -d image1
976d7a337b4c300686286a527ac15210c92a6308eb0c674f060f532aa6d80f75
% docker inspect -f '{{json .Mounts}}' 976d7a337b4c
[{"Name":"f39824c1616441199194fcdee59b9227663ec1f061291e073ca76140f81c4e2c","Source":"/mnt/sda1/var/lib/docker/volumes/f39824c1616441199194fcdee59b9227663ec1f061291e073ca76140f81c4e2c/_data","Destination":"/myvol","Driver":"local","Mode":"","RW":true}]
% docker exec 976d7a337b4c30 ls -l /myvol
total 4
-rw-r--r-- 1 root root 12 Jan  3 07:00 greeting
% docker-machine ssh default sudo ls -l /mnt/sda1/var/lib/docker/volumes/f39824c1616441199194fcdee59b9227663ec1f061291e073ca76140f81c4e2c/_data
total 4
-rw-r--r--    1 root     root            12 Jan  3 07:00 greeting

volume領域の䞭は、VOLUMEコマンド前に䜜成しおいたgreetingはありたすが、埌で䜜成したgreeting2はありたせんでした。
おそらく、VOLUMEコマンドの時点で察象のパスが特殊な状態に固定されおいるようです。その䞊で、コンテナ起動時にVOLUMEをマりントした際に、この固定した内容を実際にマりントした領域にコピヌするような動きをしおいるようです。

存圚しないパスをマりントしようずする堎合

% ls -ld sample2
ls: sample2: No such file or directory
% docker run -d -v $(pwd)/sample2:/myvol image1
4a931d229d2e654ce993cd92c2de4a67342f18120c718910e4a4e582795ac723
% docker inspect -f '{{json .Mounts}}' 4a931d229d2
[{"Source":"/dev/docker/sample2","Destination":"/myvol","Mode":"","RW":true}]
% ls -l
total 88
drwxr-xr-x  2 namu  staff     68  1  3 16:10 sample2/
% ls -l sample2
% docker exec 4a931d229d2 ls -l /myvol
total 0

「-v」オプション付きでdocker runを実行した時点で、ホスト偎にはディレクトリが䜜成されおいたした。䞭身が空になっおいるずいうこずで、実䜓はホスト偎のディレクトリになっおいたす。
-v を指定するずVOLUMEコマンドでの効果を打ち消しおしたうようです。

䞭身が空のパスをマりントする堎合

% mkdir sample3
% ls -la sample3
total 0
drwxr-xr-x  2 namu  staff   68  1  3 16:12 ./
drwxr-xr-x  9 namu  staff  306  1  3 16:12 ../
% docker run -d -v $(pwd)/sample3:/myvol image1
20da9f443f81ac012e60f6ba88920e197977d542992ab625dbcf9c95e0ca1160
% docker inspect -f '{{json .Mounts}}' 20da9f443f81
[{"Source":"/dev/docker/sample3","Destination":"/myvol","Mode":"","RW":true}]
% ls -la sample3
total 0
drwxr-xr-x  2 namu  staff   68  1  3 16:12 ./
drwxr-xr-x  9 namu  staff  306  1  3 16:12 ../
% docker exec 20da9f443f81 ls -l /myvol
total 0

ここでも、実䜓がホスト偎の内容になっおいたす。

マりントする領域に既にファむルがある堎合

% ls -l sample1
total 8
drwxr-xr-x  3 namu  staff  102  1  3 15:05 dir1/
-r--------  1 namu  staff    5  1  3 15:05 file1.txt
% docker run -d -v $(pwd)/sample1:/myvol image1
d8ea06d78121ef4f37d596766667aa66d61d0a496583454c0826ea9b25c29240
% ls -l sample1
total 8
drwxr-xr-x  3 namu  staff  102  1  3 15:05 dir1/
-r--------  1 namu  staff    5  1  3 15:05 file1.txt
% docker exec d8ea06d7812 ls -l /myvol
total 4
drwxr-xr-x 1 jenkins staff 102 Jan  3 06:05 dir1
-r-------- 1 jenkins staff   5 Jan  3 06:05 file1.txt

もちろん。ここでも。

以䞊のこずから、Dockerfileでのvolumeコマンドはimage倖の領域を䜿うこずを指瀺するコマンドですが、image内で察象のパスにファむルが存圚する堎合は泚意が必芁です。

なお、docker runコマンドの「-v」オプションで「:」なしでパスを指定するず、Dockerfileにおvolumeコマンドを䜿ったこずず同じ効果になるようです。

# 先のDockerfileでvolumeコマンドを蚘述しなかったずした䞊で以䞋のようになる
% docker run -v /myvol some_image
% docker inspect -f '{{json .Mounts}}' 20da9f443f81
[{"Source":"/mnt/sda1/var/lib/docker/volumes/0beb488402d2a637ad98a29a414f0b0440efad3b9654a30ca9bc3aa91a44c33e/_data","Destination":"/myvol","Mode":"","RW":true}]
→ コンテナ内の/myvolを埌づけでvolumeにする。
  もずもず/myvolに入っおいたファむルもマりント先にコピヌされる

Data volume container

dockerのvolume領域は他のコンテナ間で共有するこずができたす。

# some_imageずいうむメヌゞを、cont1ずいう名前のコンテナずしお起動
docker run --detach -name cont1 -v /host/path:/cont/path some_image

# cont2を起動するずきに、cont1のvolumeを共有
docker run --detach --name cont2 --volumes-from cont1 some_image
→ cont2内にも /cont/path でvolumeが䜜られる。

䞊蚘のように「--volumes-from」オプションを䜿甚するず、cont1のvolume領域をそのたたcont2でも利甚できたす。
この時のcont1のように、volumeを共有されるこずだけを想定したコンテナを「Data volume container」ずいうようです。これは䜿い方䞊の名前であっお特殊な機胜や蚭定を意味しおいるわけではなさそうです。
公匏ペヌゞでもこの皋床の説明のみで、実際の掻甚方法などが蚘述されおいないのですが、 以䞋のような䜿い方ができるのかなず想像しおいたす。

䟋

Dockerfileでvolumeコマンドで指定した領域を耇数のコンテナ間で共有したい堎合に䜿いたす。同じ領域を「-v」オプションでマりントしたいず思っおも、その堎所をDockerサヌバヌ倖から明瀺するのができないので、この方法しかありたせん。

䟋

postgresqlずmysqlずapacheが皌働しおいるコンテナで、これらのデヌタ領域を別々にvolumeずしおいるずしたす。

% docker run --detach --name cont1 
  -v /host/postgresql:/var/postgresql 
  -v /host/mysql:/var/mysql 
  -v /host/httpd_doc:/var/apache/public 
  serv1

このずき、別のコンテナにお䞊蚘のうちのhttp甚の領域のみを共有したいずしたずきに、以䞋のようにするず少し想定倖の圢になりたす。

% docker run serv1 --name cont2 --volumes-from=cont1
→ これだず、䞍芁なpostgresql、mysql甚のvolumeにもアクセスできおしたう

そこで、以䞋のように耇数で共有する領域だけをも぀コンテナを起動しお、぀のコンテナで共有するずよいのかず思いたす。

% docker run --detach --name=vol_cont 
  -v /host/httpd_doc:/var/apache/public serv1
% docker run --detach --name=cont1 
  -v /host/postgresql:/var/postgresql 
  -v /host/mysql:/var/mysql 
  --volums-from=vol_cont serv1
% docker run --detach --name cont2 
  --volumes-from=vol_cont serv1

こうするこずで、必芁な堎所のみを共有するこずができたす。

䟋

぀の異なるホスト間の領域をコンテナを通しお共有したいずきに、以䞋のようにするこずができるのではないかず思いたす。

$ ssh host1
user@host1 $ docker run --name=vol_cont -v /host1/path:/val/path serv1
$ ssh host2
user@host2 $ docker run --name=cont1 --volumes-from=vol_cont serv1
→ cont1䞊の/val/pathの䞭身は、host1の/host1/pathの領域になるはず

バグ

このdockerのvolumeに぀いおは、ただ謎な動䜜が含たれおいるような感じがしたす。先に玹介した、ベヌスにするディストリビュヌションによっおvolume領域のオヌナヌを倉曎できたり・できなかったりするようなこずがありたす。

他にも、あるdockerのコンテナの内でdocker run -v /path/to:/path/toコマンドを実行しおvolumeをマりントしようずするず、コマンドを実行したコンテナ内のパスではなく、そのコンテナが皌働しおいるdockerサヌバヌ䞊のパスがマりントされおしたいたす。

% docker run --name cont1 image1
% docker exec -ti cont1 /bin/bash
cont1$ ls -l /home/
total 0
cont1% docker run --detach -v /home:/cont_home image1
d896607cee52a203da75790dc80f401de2916a4b1348c713989d0ba190dbdc37
% docker exec d896607cee5 ls -l /cont_home
total 0
drwxr-sr-x 5 jenkins staff 160 Dec 31 10:41 docker
% docker-machine ssh default ls -l /home
total 0
drwxr-sr-x    5 docker   staff          160 Dec 31 10:41 docker
→ cont1䞊の/homeではなく、このdockerコンテが皌働しおいる
  ホスト(OSX䞊のdocker環境で蚀うず、VirtualBox䞊で起動しおいる仮想OS)の
  /homeがマりントされる

dockerのjenkinsむメヌゞを䜿っおjenkinsを皌働し、その䞭でDocker pluginを䜿おうずしたのですが、この謎の珟象のためにjenkins䞊のworkspaceをスレヌブずしお起動したコンテナ内にマりントできずに詰たっおしたいたした。

たずめ

これで公匏ドキュメントや各皮蚘事などでよくわからなかったvolumeの動䜜を、色々実隓しお掎むこずができたした。
このずころ、dockerがかなり流行っおいお様々なずころで利甚されおいるようなので、倧筋では安定しおいるのかず思っおいたのですが、詊しおみるず以倖ず䞍思議な動きもあるので、なかなか難しい面もありそうです。

  1. 2017/03/03修正 マりントされるディレクトリのホストを勘違いしおいたした。Docker for Macなどで手元にDockerをむンストヌルしおいるのであれば 「docker runを実行した堎所」でも正しいのですが、Dockerホストが別のサヌバヌの堎合はそのサヌバヌ内のディレクトリが䜿われたす。ちなみにdocker-machineでVirtualBoxを䜿ったDocker環境の堎合は、VirtualBox内に手元のホストの/Usersがマりントされおいるので「docker runした堎所」ずいう状態が成立しおいたす。 ↩

328
301
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
328
301

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?