😊

Dockerでvolumesを設定する

2022/02/28に公開

【環境】
MacBook Air (M1, 2020)
OS: MacOS Big Sur version11.6
Docker Desktop for Mac version4.5.0

Dockerのvolumesの理解のため記事にまとめます。
Docker Desktop for Macを使っています。

volumesとは

volumesはDockerのコンテナ内で作成したデータを永続化するための場所です。
コンテナに保存したデータはコンテナを破棄すると消えます。
volumesに保存したデータはコンテナを破棄しても残り再利用できます。

やってみる

まずはvolumeをcreateします。

% docker volume create test-volume
test-volume
% docker volume ls
DRIVER    VOLUME NAME
local     test-volume

次に作成したvolumeを指定してコンテナ(alpineサーバー)を起動します。
-v [volume名]:[コンテナのvolume用ディレクトリ]
のオプションでvolumeを指定します。

% docker run -it --rm --name volume-test-container -v test-volume:/volume_dir alpine:latest /bin/ash  
Unable to find image 'alpine:latest' locally
latest: Pulling from library/alpine
9b3977197b4f: Pull complete 
Digest: sha256:21a3deaa0d32a8057914f36584b5288d2e5ecc984380bc0118285c70fa8c9300
Status: Downloaded newer image for alpine:latest
/ # 

無事コンテナに入ることができました。
コンテナ内にvolume用ディレクトリが存在するか確認し、ディレクトリ内にtest.txtを作成します。

/ # ls
bin         etc         lib         mnt         proc        run         srv         tmp         var
dev         home        media       opt         root        sbin        sys         usr         volume_dir
/ # cd volume_dir
/volume_dir # echo "test" > test.txt
/volume_dir # cat test.txt
test

コンテナを破棄し、再度コンテナを立ち上げます。
docker runのオプションに--rmを指定しているので、コンテナを抜けた際にコンテナを自動的に破棄します。

/volume_dir # exit
% docker run -it --rm --name volume-test-container -v test-volume:/volume_dir alpine:latest /bin/ash
/ # cat volume_dir/test.txt
test
/ # 

volumeを使わない場合はtest.txtは破棄され再度コンテナを立ち上げても存在しませんが、volumeに保存したため再びファイルを確認することができました。

volumesはどこに保存される?

volumesはホストに保存されますが、ホストのどこに保存されるのでしょうか?
以下のコマンドでvolumeの保存場所を確認できます。

% docker volume inspect test-volume
[
    {
        "CreatedAt": "2022-02-27T15:21:35Z",
        "Driver": "local",
        "Labels": {},
        "Mountpoint": "/var/lib/docker/volumes/test-volume/_data",
        "Name": "test-volume",
        "Options": {},
        "Scope": "local"
    }
]

Mountpointの"/var/lib/docker/volumes/test-volume/_data"が保存場所です。
しかしDocker Desktop for Macを使っている場合、Docker環境はHyperKitというVM(バーチャルマシン)上で実行されているためMacからは参照できないようです。
nsenter1というコマンドでVMに入って確認することができます。
こちらの記事を参考にさせて頂きました。ありがとうございました。)

docker run -it --rm --privileged --pid=host justincormack/nsenter1
Unable to find image 'justincormack/nsenter1:latest' locally
latest: Pulling from justincormack/nsenter1
726619a9fa8c: Pull complete 
Digest: sha256:e876f694a4cb6ff9e6861197ea3680fe2e3c5ab773a1e37ca1f13171f7f5798e
Status: Downloaded newer image for justincormack/nsenter1:latest
/ # 

実際に/var/lib/docker/volumes/test-volume/_dataにtest.txtが存在するか確認します。

/ # ls /var/lib/docker/volumes/test-volume/_data
test.txt

ちゃんとありました。
/var/lib/dockerディレクトリにはvolumes以外にもcontainers, image, networkなどDockerの重要要素が保存されていました。

ちなみにファイルを確認するだけならDocker Desktopからも確認できます。
Volumes選択
Volumes選択
DATAにtest.txt
DATAにtest.txt
Save As... を選択するとホスト側にファイルを保存し内容を確認できます。
Save As...で内容確認
Save As...で内容確認

やってみる2

先ほどは事前にvolumeを作成し、
-v [volume名]:[コンテナのvolume用ディレクトリ]
というvolumeオプションを使いDocker用VMマシン上のvolumeとマウントしました。
今度はVMではなくホスト(MacBook)に作成したディレクトリとマウントします。
-v [ホストの絶対Pathディレクトリ]:[コンテナのvolume用ディレクトリ]
というvolumeオプションを使います。

% mkdir ~/desktop/volume_dir_mac                                             
% echo "test on mac" > ~/desktop/volume_dir_mac/test_mac.txt
% docker run -it --rm --name volume-test-mac -v ~/desktop/volume_dir_mac:/volume_dir_alpine alpine:latest /bin/ash
/ # cat volume_dir_alpine/test_mac.txt
test on mac

ホスト側でvolume_dir_mac/test_mac.txtを作成し、volume_dir_macの絶対Pathをvolumeに指定したコンテナが立ち上がりました。
volume_dir_alpineディレクトリにホスト側で作成したファイルがあります。
このファイルへの変更はホストとコンテナで共有されます。

追記(2022.3/1)

volumesにはvolume, bind, tmpfsの3種類の機能があることを知りました。
https://qiita.com/aki_55p/items/63c47214cab7bcb027e0
こちらの記事が非常に分かりやすかったです。
特にvolumeとbindが使われます。
volumeがDocker上に作成される記憶領域です。
bind(バインドマウント)がホスト側のディレクトリとコンテナのディレクトリをマウントさせる機能です。

参考

https://qiita.com/gounx2/items/23b0dc8b8b95cc629f32
https://qiita.com/Yarimizu14/items/52f4859027165a805630
https://uzimihsr.github.io/post/2020-12-15-docker-desktop-for-mac-hyperkit-vm/

Discussion