Open meghuizen opened 4 months ago
I suspect this may be related to conversions happening in Docker Desktop.
For context; bind-mounts happen on the daemon-side, not from the client side; e.g., if you pass -v /some/path:/inside-container/path
(mount /some/path
into the container at /inside-container/path
), as path to be mounted, that path is sent to the daemon which creates a container, and lets the OCI runtime mount the path into it; when using the -v <src>:<dst>
shorthand syntax, the daemon also creates the host-path if it's not found, but this defaults to a directory, so if /some/file.txt
does not exist on the host where the daemon runs, it will create a directory named /some/file.txt
.
Docker uses a client-server architecture (the CLI uses the daemon API to control it); that means that the docker
CLI and the Docker Daemon (dockerd
) can run on separate machines, which may be a remote daemon (remote datacenter), or a "VM" running on your local machine; this is the case when running Docker Desktop; the Linux Daemon runs inside a VM (on Windows: Hyper-V or WSL2), and may not have direct access to the files you're trying to bind-mount from your client (where your docker
CLI runs).
Docker Desktop tries to make this work transparently; it shares files from your (Windows) host with the Linux VM, and where needed translates paths to the corect location (C:\some\path\on\Windows
-> /run/desktop/mnt/host/C/some/path/on/Windows
inside the VM). Depending on where the docker
CLI is executed (Windows, WSL2), different translations may be needed, and I suspect something goes wrong in some of these permutations, resulting in a non-existing path to be passed to the daemon, which in its turn then creates a directory at that location (as outlined further above).
I might circumvent this with creating my own images on top of the original images, however that makes my development pipeline a bit more cumbersome.
@thaJeztah thanks for the deduction. That makes a lot of sense.
Yeah, it's a tricky one as there are many moving parts at play; more so on Windows, where there's multiple combinations possible (in addition, MINGW automatic path conversion has been known to cause havoc; https://stackoverflow.com/a/34386471). I'm not on a Windows machine, so not directly able to try to reproduce, but I can move this ticket to the https://github.com/docker/for-win issue tracker; possibly for the team working on those parts to look.
In general, there's some options that (depending on your situation) could help;
--mount
syntax instead of the -v
short-hand. The --mount
flag, unlike the -v
shorthand, does not automatically create missing paths on the host; it requires the path to mount to be an existing location, and otherwise will error out. This can prevent situations where an incorrect path either ends up with an empty directory to be mounted (and created on the host), making such errors a hard failure instead. The --mount
syntax provides more options, at the cost of being more verbose, so YMMV (see https://docs.docker.com/storage/bind-mounts/#choose-the--v-or---mount-flag).Might indeed be good to move to the for-win issue tracker.
Good advice on the mount syntax. I might be able to come away with that one, since I can pass those arguments directly.
I moved the ticket 👍
Description
I'm using .NET Aspire with docker to run some docker containers, but with some additional configuration files of my own. The issue I'm talking about here is NOT about Aspire, but is about docker cli on Windows. This however gives me extra pain when using it with Aspire due to conflicting logic there.
What I want to do I have an init.sql file in my folder and want to map that file as a file in a mysql container. For that I ran the following command:
docker run -v mysql_data:/var/lib/mysql -v ./init.sql:/data/application/init.sql mysql:5.7.18
When I run this and do a ls -al on the folder, the file is located:
drwxr-xr-x 2 root root 4096 Jul 30 10:02 init.sql
Noticed the d of directory. While the source on the host machine is actually a file.Then I ran (change in path delimiter):
docker run -v mysql_data:/var/lib/mysql -v ./init.sql:/data/application/init.sql mysql:5.7.18
Now it is a file (good behaviour):
-rwxrwxrwx 1 root root 54 Jun 28 14:36 init.sql
Now with full system paths
docker run -v mysql_data:/var/lib/mysql -v C:\Users\michiele\source\repos\tp-aspire-architecture\tp-aspire-architecture\Dockerfiles\init.sql:/data/application/init.sql mysql:5.7.18
This results in a file mapping.With inspect JSON
MTAB:
docker run -v mysql_data:/var/lib/mysql -v C/Users/michiele/source/repos/tp-aspire-architecture/tp-aspire-architecture/Dockerfiles/init.sql:/data/application/init.sql mysql:5.7.18
This results in a directory mapping (which is faulty)with inspect json:
MTAB:
How does Aspire do this? Aspire always uses a full file path from a Windows notation:
This will be translated to:
but this also results in a directory mapping (faulty one!)
Reproduce
Expected behavior
I'm expecting in all situations this will be mapped as a file and not a directory.
docker version
docker info
Additional Info
No response