Docker for Mac のボリュームの実態はどこにあるのか

以前の記事で、DockerでPostgreSQLを起動するコマンドを紹介した。

% docker run --rm -d \
    -p 6432:5432 \
    -v postgres:/var/lib/postgresql/data \
    postgres:latest

-vオプションでコンテナ内で利用するボリュームを指定しているが、実際にどこにデータが格納されているのかは、以下のコマンドで確認することができる。

% docker inspect --format '{{json .Mounts}}' <コンテナID> | jq
[
  {
    "Type": "volume",
    "Name": "postgres",
    "Source": "/var/lib/docker/volumes/postgres/_data",
    "Destination": "/var/lib/postgresql/data",
    "Driver": "local",
    "Mode": "z",
    "RW": true,
    "Propagation": ""
  }
]

コンテナで利用している/var/lib/postgresql/data内のデータの実態は、/var/lib/docker/volumes/postgres/_dataにあることが確認できる。しかし、指定されたパスを探してもデータを見つけることができない。

% ls /var/lib/docker/volumes/
ls: /var/lib/docker/volumes/: No such file or directory

これはDocker for MacVMで稼働しているためで、通常のボリュームには上記のディレクトリを見つけることができない。 ボリュームの内容を確認するためには、VMに接続して操作を行う必要がある。やり方は大きく分けて2つある。

  1. sockファイルを利用して接続する
  2. docker経由でnsenterを利用して接続する

環境

% sw_vers
ProductName:    Mac OS X
ProductVersion: 10.15.7
BuildVersion:   19H1030

% docker --version
Docker version 20.10.5, build 55c4c88

docker desktop Version 3.3.1 (63152)

1. sockファイルを利用して接続する

Docker for Macをインストールすると作成されるdebug-shell.sockファイルを利用して接続する。 ^[[24;5Rという謎の文字列が入力箇所の先頭についてしまっているが、コマンド自体は問題なく実行できている。

接続した状態でvar/lib/docker/volums配下を見ると、ボリュームが存在していることが確認できる。

% nc -U ~/Library/Containers/com.docker.docker/Data/debug-shell.sock 

/ # ^[[24;5Rcat /etc/os-release
cat /etc/os-release
PRETTY_NAME="Docker Desktop"

/ # ^[[24;5Rls
ls
bin         etc         media       proc        sbin        tmp
containers  home        mnt         root        srv         usr
dev         lib         opt         run         sys         var

/ # ^[[24;5Rls var/lib/docker/volumes/
ls var/lib/docker/volumes
backingFsBlockDev  metadata.db        postgres

socatコマンドを利用すると、screenコマンドで接続することも可能。こちらの方法であれば謎の文字列も表示されず、tabによる補完も効くようになる。

% brew install socat

% socat -dd ~/Library/Containers/com.docker.docker/Data/debug-shell.sock pty,rawer
2021/05/02 21:03:33 socat[15820] N opening connection to LEN=74 AF=1 "/Users/gumfum/Library/Containers/com.docker.docker/Data/debug-shell.sock"
2021/05/02 21:03:33 socat[15820] N successfully connected from local address LEN=16 AF=1 ""
2021/05/02 21:03:33 socat[15820] N successfully connected via 
2021/05/02 21:03:33 socat[15820] N PTY is /dev/ttys002
2021/05/02 21:03:33 socat[15820] N starting data transfer loop with FDs [5,5] and [6,6]
(別のターミナルから接続。ttys0xxの部分はsocatコマンドの実行時に表示されたものを利用する)
% screen /dev/ttys002

/ # ls
bin         etc         media       proc        sbin        tmp
containers  home        mnt         root        srv         usr
dev         lib         opt         run         sys         var

/ # ls var/lib/docker/volumes/
backingFsBlockDev  metadata.db        postgres

2. docker経由でnsenterを利用して接続する

docker経由でnsenterコマンドを利用してVMに接続する。1.の方法と同じ操作が可能であり、こちらの方がコマンド一つで実行できるため便利。

% docker run -it --privileged --pid=host debian nsenter -t 1 -m -u -n -i sh

/ # ls var/lib/docker/volumes/
backingFsBlockDev  metadata.db        postgres

参考サイト