Docker Desktop for MACのDockerホストの仮想マシン(HyperkitのVM)に入りたい

Dockerでローカルストレージの名前付きボリュームを作成した際に、マウントポイントの実体を確認したかった。

ただそれだけ。

環境

ボリュームを作成する

まず、適当なローカルストレージのボリュームを作成する。

$ docker volume create sample
sample

作成したボリュームをinspectしてマウントポイントを確認。

$ docker volume inspect sample
[
    {
        "CreatedAt": "2021-10-23T15:57:48Z",
        "Driver": "local",
        "Labels": {},
        "Mountpoint": "/var/lib/docker/volumes/sample/_data",
        "Name": "sample",
        "Options": {},
        "Scope": "local"
    }
]

ボリュームの実体は/var/lib/docker/volumes/sample/_dataにある事が分かった。

ただ、このパスはDockerホストが稼働している仮想マシン上に存在する為、ターミナルで普通に探しても見つからない。

$ ls /var/lib/docker/volumes/sample/_data
ls: /var/lib/docker/volumes/sample/_data: No such file or directory

Docker Desktop for MACは、HyperkitというmacOSのHypervisor.frameworkのみをサポートしているアプリケーションにHypervisorの機能を組み込むツールを利用しており、DockerホストはこのHyperkitの仮想マシンLinuxkitを使って構成したコンテナランタイム環境(containerd&runc)で動いている。

その為、上述のマウントポイントの実体を確認するには、Dockerホストが稼働している仮想マシンに入る必要がある。

で、Dockerホストに入る方法を調べてみると、以下の様なscreenコマンドを使ってDockerホストのttyにアクセスする方法が出てくるのだが、

$ screen ~/Library/Containers/com.docker.docker/Data/vms/0/tty

自分の環境ではパーミッションエラーとなり、rootでもパーミッションを変更出来なかった為、この方法では無理だった。

その為、別の方法を探していたところ、nsenterを使って特権モードのコンテナを起動することで、Dockerホストに入ることが出来ると分かった。

nsenterを利用すると、docker execとは異なり、cgroupに縛られることなく、指定のコンテナのプロセス空間に対して、外から新しいプロセスを生成出来るようになる。

nsenterコマンドはalpineにインストールされているので、以下の様なコマンドを実行することで、Dockerホストに入ることが可能となる。

$ docker run -it --rm --privileged --pid=host alpine:edge nsenter -t 1 -m -u -n -i sh
/ # 

--pidにhostを指定してコンテナ内からDockerホストのプロセスを見えるようにし、--privilegedでDockerホストリソースへのアクセスを許可することで、nsenterを使ってDockerホスト側のプロセス空間にshプロセスを生成している訳である。

これで、Dockerホストに入ってボリュームのマウントポイントの実体を確認することが出来た。

$ docker run -it --rm --privileged --pid=host alpine:edge nsenter -t 1 -m -u -n -i sh
/ # ls -al /var/lib/docker/volumes/sample/_data
total 8
drwxr-xr-x    2 root     root          4096 Oct 23 15:57 .
drwx-----x    3 root     root          4096 Oct 23 15:57 ..
/ #

ちなみに、nsenterはalpineのみならず、debianubuntucentos等、大概のコンテナOSイメージにはインストールされているので、それらのイメージを使っても同様にDockerホストへのアクセスは可能。

また、調べていたらnsenter1という、nsenterのコマンド入力を省略するイメージも存在していたので、こっちを使っても良いかも。

$ docker run -it --rm --privileged --pid=host justincormack/nsenter1
/ #