Search code examples
angulardocker-composehyper-vwindows-subsystem-for-linuxdocker-desktop

With Docker Desktop on WSL 2, how to find and inspect the exact host folder of a bind mount?


My main question is: with docker compose on Docker Desktop with WSL 2, when using a bind mount where the host path is a relative path, where and what is the actual host path on the WSL distro used by the docker desktop backend?

Sections below help understanding the context, what I searched and understood, and detail my questions.

Actual source issue

I have a docker compose configuration and a container with an Angular application. The content of the project is located on the Windows file system, and the docker compose uses a bind mount with a relative path.

The container does get the initial content, but it seems to never be updated: no live reload, no updated content when (hard-)refreshing the browser page.

Note that this is with Docker Desktop on Windows, after switching from the Hyper-V backend to the WSL 2 one. With Hyper-V, everything worked as expected, it was just much slower (as they state in the documentation).

My investigations

I really searched a lot... and got quite mad since I took many paths and always got badly stuck.

  • I tried to run a WSL shell inside docker-desktop-data which was running: it fails, returning immediately, and the process exit code is just the generic 1 for error. Btw, doing the same for docker-desktop does work.
  • I tried to find the content using the Windows explorer in the network folder \\wsl$\docker-desktop-data. There I could finally see the persisted volumes, but couldn't find any folder that would correspond to the bind mount
  • I couldn't find the information about what internal path the docker engine exposes to the container (which is what my question's title targets). I could see the WSL distro had mounted paths corresponding to the Windows file system drives, but it doesn't mean that this is what it uses (and in fact, there I could see my content updated, while, as I said, nothing was updated when refreshing the browser hence my hypothesis that the content is lying elsewhere)
  • I discovered the existence of the ext4.vhdx files located under C:\Users\<username>\AppData\Local\Docker\wsl\{data,distro}. I tried to mount it, but as expected it refused since it was already mounted. However I couldn't find any info about where to see the mounted content. It might by this \\wsl$\docker-desktop[-data] thing, but no doc, nor any command (I tried PowerShell's Get-VHD which just told me it's "attached") could tell me how to get that info.

And probably a few other things which I don't even remember and that were probably already too far from the initial topic.

I also checked the official Docker documentation pages with no luck finding these details.

My next step would be to read the source code of the backends directly...

My expectations

The real, pragmatic outcome for me is to be able to have the container interact with the local Windows file system content, instead of what seems to be a copy, which I can't locate.

As a bonus, I would love to understand what paths are involved, and what mechanisms are used to bind all of that (e.g. with the working Hyper-V backend, I expect a Hyper-V specific mechanism to have been used to make it possible for the virtualized docker process to expose a Linux path to the container which eventually was just a sort of hard link / shared folder - conceptually speaking - to the Windows file system folder). So, in docker compose's configuration I see a host <=> container path mapping, but being on Windows there's really a windows host <=> linux host <=> container mapping and it's that windows host <=> linux host mapping which seems to behave differently between Hyper-V and WSL 2, with me being unable to locate the linux host path.

If all of that could be backed by links to documentations (preferably reference/official) it would make it PERFECT.

But, really, getting a solution to the first point would already be extremely helpful.


Solution

  • So, while I still couldn't find a perfect source of info (like official documentation or even source code), I could find some data which confirms some of the information or hypothesis made earlier.

    The strategy

    Remembering that Docker is a tool that builds around core Linux APIs, like other container systems, I started to look at namespaces, and more specifically mount namespaces.

    The procedure to get the information

    Therefore, on a WSL 2 shell instance on the docker-desktop distro (wsl -d docker-desktop), the procedure is as follows:

    • find the process ID corresponding to the container for which you want to get information about the mounts: use ps for that. We'll name that value <pid> below.
    • then show the content of /proc/<pid>/mountinfo: you can use cat for that
    • each line corresponds to a mount and contains all the needed information. Find the relevant line for your use case. Examples:
      • for Portainer with standard installation, which uses a named volume: 975 931 8:32 /version-pack-data/community/docker/volumes/portainer_data/_data /data rw,relatime master:3 - ext4 /dev/sdc rw,discard,errors=remount-ro,data=ordered
      • for my use case with a bind mount: 1092 1070 0:56 /whatever/path/on/the/c/drive /container/path rw,noatime - 9p C:\134 rw,dirsync,aname=drvfs;path=C:\;uid=0;gid=0;metadata;symlinkroot=/mnt/host,mmap,access=client,msize=65536,trans=fd,rfd=8,wfd=8

    Interpretation of the information

    The named volume use case (applied to Portainer)

    975 931 8:32 /version-pack-data/community/docker/volumes/portainer_data/_data /data rw,relatime master:3 - ext4 /dev/sdc rw,discard,errors=remount-ro,data=ordered contains the following relevant information:

    • /version-pack-data/community/docker/volumes/portainer_data/_data is the path of the volume data on the Linux host, relatively to:
    • /dev/sdc, which points to the docker-desktop-data distro (you can check that using findmnt -S /dev/sdc, which gives us something like /mnt/host/wsl/docker-desktop-data)
    • it is exposed on /data within the container, as configured when creating it

    So eventually, it maps /data to /version-pack-data/community/docker/volumes/portainer_data/_data on device /dev/sdc, which can be accessed as well from /mnt/host/wsl/docker-desktop-data/version-pack-data/community/docker/volumes/portainer_data/_data.

    However I suspect the mount namespace to be using the device directly, not its mounted path (which I provided only to "prove" it corresponds to the docker-desktop-data distro).

    The bind mount use case

    1092 1070 0:56 /whatever/path/on/the/c/drive /container/path rw,noatime - 9p C:\134 rw,dirsync,aname=drvfs;path=C:\;uid=0;gid=0;metadata;symlinkroot=/mnt/host,mmap,access=client,msize=65536,trans=fd,rfd=8,wfd=8:

    • /container/path inside the container points to...
    • /whatever/path/on/the/c/drive on the host, through the filesystem of type...
    • 9p, which contains the following parameters:
      • path=C:/: so /whatever/path/on/the/c/drive is relative to the C:/ Windows drive
      • symlinkroot=/mnt/host: that C:/ drive is mounted in /mnt/host, implicitly under /mnt/host/c

    So eventually, the host path is again directly consumed from the filesystem, but it has a correspondence on /mnt/host/c/whatever/path/on/the/c/drive.

    References