error mounting ... to rootfs at "/etc/alpine-release": ... not a directory: Are you trying
to mount a directory onto a file (or vice-versa)? came up here when the host file named
in -v did not exist. Docker Desktop created a folder with that name on
the host and then could not mount a folder over a file in the image. Create the file, move
the folder aside, and run again.
Look in the folder you ran from: the "file" you meant to mount is now an empty directory.
Move it aside or delete it, put the real file in its place, and the same
docker run works.
The error
The host paths are shortened with ...; the rest is as captured.
PS> docker run --rm --name fix9-run-cfg -v ./app.conf:/etc/alpine-release alpine cat /etc/alpine-release
docker: Error response from daemon: failed to create task for container: failed to create shim task: OCI runtime create failed: runc create failed: unable to start container process: error during container init: error mounting "/run/desktop/mnt/host/c/.../lab3b/app.conf" to rootfs at "/etc/alpine-release": mount src=/run/desktop/mnt/host/c/.../lab3b/app.conf, dst=/etc/alpine-release, dstFd=/proc/thread-self/fd/14, flags=MS_BIND|MS_REC: not a directory: Are you trying to mount a directory onto a file (or vice-versa)? Check if the specified host path exists and is the expected type
...
Run 'docker run --help' for more information
Why it happens
Before the run the lab folder was empty: there was no app.conf. After the failed
run, Get-ChildItem showed app.conf with mode d-----,
a directory. The target, /etc/alpine-release, is a file in the image, so the
mount was a directory onto a file and runc refused it with the message above.
The message suggests a type mix-up, and that is what it is, but the directory was not yours:
Docker made it from the missing path, and it stays on disk after the failed run. The same happened with
--mount type=bind,source=./missing.conf,... on this engine: the error was
identical and missing.conf existed afterwards as well.
The fix
PS> Get-ChildItem -Force | Format-Table Mode,Name -AutoSize | Out-String
Mode Name
---- ----
d----- app.conf
PS> Test-Path ./app.conf -PathType Container
True
PS> Move-Item ./app.conf ./app.conf.made-by-docker
PS> Set-Content -Path ./app.conf -Value "3.99.9-fix9" -Encoding ascii
PS> docker run --rm --name fix9-run-cfg -v ./app.conf:/etc/alpine-release alpine cat /etc/alpine-release
3.99.9-fix9
The container printed the host file, so the mount worked. In a real project the file is
often a config such as nginx.conf or appsettings.json. Check the
spelling and the folder you run from: in this test a source path that did not exist was
enough to produce the empty directory, so a typo in the name has the same effect.
How it was reproduced
On Windows 11 with Docker Desktop, engine and client 29.9.3, from Windows PowerShell 5.1, with
the cached alpine image, in an empty scratch folder. -v
./app.conf:/etc/alpine-release with no app.conf on disk gave the error
and left an app.conf directory; creating the file after moving that directory
aside fixed it. The --mount form with a missing missing.conf gave
the same result. The folder and container names are the test's own.
Frequently asked
- Why did Docker create a folder instead of my config file?
- The host file named in -v did not exist. In this test Docker Desktop created a directory with that name, and the mount then failed because the target in the image is a file.
- How do I mount a single file into a Docker container?
- Make sure the host file exists first, then use -v ./app.conf:/path/in/container. In this test that printed the host file's content from inside the container.
- Does --mount avoid the empty folder?
- Not in this test. With Docker Desktop 29.9.3 on Windows, --mount type=bind with a missing source file gave the same error, and afterwards Test-Path ./missing.conf -PathType Container returned True: a directory with that name.
More decoded errors in the Fixes category. A related bind mount error with a Linux-style path on Windows: bind source path does not exist.