Docker Desktop for MACのDockerホストの仮想マシン(HyperkitのVM)に入りたい
Dockerでローカルストレージの名前付きボリュームを作成した際に、マウントポイントの実体を確認したかった。
ただそれだけ。
環境
- Macbook Pro
- macOS Catalina 10.15.7
- Docker Desktop for MAC 3.6.0
- Docker 20.10.8
ボリュームを作成する
まず、適当なローカルストレージのボリュームを作成する。
$ 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のみならず、debianやubuntu、centos等、大概のコンテナOSイメージにはインストールされているので、それらのイメージを使っても同様にDockerホストへのアクセスは可能。
また、調べていたらnsenter1という、nsenterのコマンド入力を省略するイメージも存在していたので、こっちを使っても良いかも。
$ docker run -it --rm --privileged --pid=host justincormack/nsenter1 / #