Description
I am using Docker version 1.12.5 on Windows 10 via Hyper-V and want to use container executables as commands in the current path. I built a Docker image that is running fine, but I have a problem to mount the current path. The idea is to create an alias and do a docker run --rm [...]
command so that it could be used system-wide in the current directory.
Setup
I have a drive E with a folder «test» and in there a folder called «folder on windows host» to show that the command is working. The Dockerfile create the directory /data
, defines it as VOLUME and WORKDIR.
Having E:\test
as the current directory in PowerShell and executing the Docker command with an absolute path, I can see the content of E:\test
:
PS E:\test> docker run --rm -it -v E:\test:/data mirkohaaser/docker-clitools ls -la
total 0
drwxr-xr-x 2 root root 0 Jan 4 11:45 .
drwxr-xr-x 2 root root 0 Jan 5 12:17 folder on windows host
Problem
I want to use the current directory and not an absolute notation. I could not use pwd in the volume because of different error messages:
Trying with ($pwd)
PS E:\test> docker run --rm -it -v ($pwd):/data mirkohaaser/docker-clitools ls -la
C:\Program Files\Docker\Docker\Resources\bin\docker.exe: Error parsing reference: ":/data" is not a valid repository/tag.
See 'C:\Program Files\Docker\Docker\Resources\bin\docker.exe run --help'.
Trying with /($pwd)
PS E:\test> docker run --rm -it -v /($pwd):/data mirkohaaser/docker-clitools ls -la
C:\Program Files\Docker\Docker\Resources\bin\docker.exe: Error parsing reference: "E:\\test" is not a valid repository/tag.
See 'C:\Program Files\Docker\Docker\Resources\bin\docker.exe run --help'.
Trying with \´pwd\´
PS E:\test> docker run --rm -it -v ´$pwd´:/data mirkohaaser/docker-clitools ls -la
C:\Program Files\Docker\Docker\Resources\bin\docker.exe: Error response from daemon: Invalid bind mount spec "´E:\\test´:/data": invalid mode: /data.
See 'C:\Program Files\Docker\Docker\Resources\bin\docker.exe run --help'.
Trying with `pwd`
PS E:\test> docker run --rm -it -v `$pwd`:/data mirkohaaser/docker-clitools ls -la
C:\Program Files\Docker\Docker\Resources\bin\docker.exe: Error response from daemon: create $pwd: "$pwd" includes invalid characters for a local volume name, only "[a-zA-Z0-9][a-zA-Z0-9_.-]" are allowed.
See 'C:\Program Files\Docker\Docker\Resources\bin\docker.exe run --help'.
What is the correct syntax of mounting the current directory as a volume in Docker on Windows 10?
In the previous tutorial we learned how to install Docker and get our first container running. In this tutorial we are going to learn how to mount additional directories within our Docker container that are outside of the c:\Users directory. By default, Docker only mounts the c:\Users directory inside the docker machine and containers. For myself, I have all of my project files two places: c:\projects and c:\personal. I didn’t want to change my standard configuration just for Docker. Luckily, it is really easy to mount additional directories.
To mount additional directories, you need to add the directory as a shared folder within Virtualbox and then enable long file paths and symlinks. Once the Virtualbox shared folders are setup, you need to mount the directories within the docker machine so that they are available to the containers.
The first step is to add the directories as Virtualbox shared folders by using the VBoxManage.exe utility that comes with Virtualbox. VBoxManage.exe is located in your Virtualbox install directory, which by default is C:\Program Files\Oracle\VirtualBox.
Warning: To make symlinks works when you start up the docker-machine, you need to run the Docker Quickstart Terminal or Command Line as an administrator. This is a security limitation of Windows for symlinks.
Before adding the shared folders, we need to make sure that no docker machines are running. We are going to check for running docker containers and machines as both a non-admin and admin.
Non-Admin Checking For Running Machines
Launch the Windows Command Prompt and run
$ docker-machine ls
If any machines comes back with the state of running, you will need to stop the machine.
-
Before stopping the machine you will want to make sure that your containers are stopped.
$ docker ps
-
For any containers that are returned you can stop them by running
$ docker stop [Container ID]
-
Once all of the containers are stop, you can stop the docker machine. Replace the “[machine name]” with you machine name that we returned from the docker-machine ls command. Typically you will only have 1 machine and it will be named default
$ docker-machine stop [machine name]
Admin Checking For Running Machines
-
Open the Windows Command Prompt as an administrator.
- Start Menu
- Search for command prompt
- Right-click on the Command Prompt and select Run as Administrator
-
To check if any docker machines are running, run the command:
$ docker-machine ls
If any machines comes back with the state running, you will need to stop the machine.
-
Before stopping the machine you will want to make sure that your containers are stopped.
$ docker ps
-
For any containers that are returned you can stop them by running
$ docker stop [Container ID]
-
Once all of the containers are stop, you can stop the docker machine. Replace the “[machine name]” with you machine name that we returned from the docker-machine ls command. Typically you will only have 1 machine and it will be named default
$ docker-machine stop [machine name]
We are now ready to add in our shared folders.
-
Navigate to the Virtualbox directory.
$ cd "c:\Program Files\Oracle\Virtualbox"
-
Run the following command to add the shared folders. For your shared folders, replace the projects or personal name in the name and hostpath options.
$ VBoxManage.exe sharedfolder add default --name "c/projects" --hostpath "\\?\c:\projects" --automount $ VBoxManage.exe sharedfolder add default --name "c/personal" --hostpath "\\?\c:\personal" --automount
The \?\ in the hostpath tells Windows to enable long file paths.
Step 2: Allow Long Paths and Symlinks
If you are using node many of the modules will create symlinks which are supported under Virtualbox but you need to make a configuration change to enable them.
$ VBoxManage.exe setextradata default VBoxInternal2/SharedFoldersEnableSymlinksCreate/v-root 1
Next you need to enable symlinks for each of the shared folders. Replace SharedFolderName with the –name value that you used when creating the sharedfolder.
$ VBoxManage.exe setextradata default VBoxInternal2/SharedFoldersEnableSymlinksCreate/c/personal 1
$ VBoxManage.exe setextradata default VBoxInternal2/SharedFoldersEnableSymlinksCreate/c/projects 1
Warning: To make symlinks works when you start up the docker-machine, you need to run the Docker Quickstart Terminal as an administrator. This is a security limitation of Windows for symlinks. Right-click on the Docker Quickstart Terminal and select Run As Administrator.
Unfortunately even with auto-mount Docker will only mount the c/Users folder in the docker-machine. If you want the folders to auto-mount you will need to manually mount them each time you start up the default docker machine.
-
Open the Docker Quickstart Terminal as an administrator
- Start Menu
- Search for Docker Quickstart Terminal
- Right-click on the Docker Quickstart Terminal and select “Run as Administrator”
-
In order to mount the directories we need to ssh into the docker machine
$ docker-machine ssh default
-
Once you have ssh’ed into the docker machine run the following commands to mount the shared folders we created.
$ sudo mkdir --parents /c/projects $ sudo mount -t vboxsf c/projects /c/projects/ $ sudo mkdir --parents /c/personal $ sudo mount -t vboxsf c/personal /c/personal/
-
Within the docker machine you should now be able to see the files and directories in /c/projects and c/personal
$ ls /c/projects $ ls /c/personal
-
exit the ssh session
-
You are now ready to start up or create your containers
Now that the shared folders are mounted in the docker machine to use them from a container -v argument. The command below will mount the local directory c:\projects (in unix form /c/projects) to /projects within the container. The -it say run interactively, ubuntu is the image name and bash is the type of interactive shell
$ docker run -v /c/projects:/projects -it ubuntu bash
From the container, you can look at the projects directory by running
$ ls /projects
You are now ready to start using the container for your development work. In the next tutorial we will look at running docker containers in the background for processes like mysql and postgres.
Mounting a folder to a Docker container allows you to share data back and forth on your host system. It’s a great feature to have especially on Windows where command line editors are not as native to the OS as they are with Unix/Linux.
Docker environment
Your mileage may vary with the information cited in this article depending on the version of Docker you are using. My setup at the time of this writing is…
- Docker Desktop v3.0.4 (51218)
- Engine v20.10.2
Mounting Windows file paths
There are numerous articles available on how to mount folders inside of Docker images.
On Windows…
- Unable to share a local windows path with a container in Docker
- How To Mount Your Current Working Directory To Your Docker Container In Windows
And mounting in general…
- How to mount a host directory in a Docker container
- Docker documentation – Use bind mounts
Though many articles cite different methods for referencing paths.
Referencing Windows paths
It’s likely that the way to reference Windows paths has changed over time and for different versions of Docker. I’m not entirely certain and have not researched it in depth but here is a capture of the different folder path formats I’ve encountered
//c/myFolder
/c/myFolder
c:\myFolder
Of all the pathing styles the last one is the format that worked for me…
docker run -it --name myDockerContainer1 --mount src=C:\myFolder,dst=c:\myDockerMount,type=bind aDockerImage:latest
If a path has spaces you can use quotes to contain it…
docker run -it --name myDockerContainer1 --mount src="C:\myFolder\sub folder",dst=c:\myDockerMount,type=bind aDockerImage:latest
Conclusions
- An absolute path must be used when specifying folders
- Use quotes around a path if it contains spaces
In a native Docker environment, you can mount /source
in a container host onto /destination
in a container by docker run -v /source:/destination
and access it from the container.
Well then, how can you mount C:\Source
in Windows onto /destination
in a container on Docker for Windows? You can’t directly mount C:\Source
in the VM host into the container, of course.
As the first step, you have to set up C:\Source
as a shared folder for a VM when you create it with docker-machine. You can specify the shared folder with the --virtualbox-share-folder
option of the VirtualBox deriver as follows.
docker-machine create --driver virtualbox --virtualbox-share-folder=C:\Source:Source
C:\Source:Source
specifies C:\Source
as a shared folder named Source
. The VM automatically mounts it onto /Source
in the container host by default.
Then, you have to mount /Source
onto /destination
in a container by the -v option of the docker command as follows: docker run -v /Source:/destination
Finally, you can access C:\Source
through /destination
as follows.
By the way, usual VM’s by VirtualBox mount a shared folder named Source
onto /media/sf_Source
in the guest OS. The VM created by docker-machine mounts /Source
. It is because the VirtualBox driver set MountDir
(/media
) to /
and MountPrefix
(sf_
) to /
as follows in the VM configuration.
For C:\Users
If you don’t specify --virtualbox-share-folder
, the driver use \?c:\Users:c/Users
as the default value. The VM mounts C:\User
onto /c/Users
in a container host.
You can just run docker run -v /c/Users:/destination
to access C:\User
through /destination
. You don’t need to specify --virtualbox-share-folder
if you want to access C:\User
from the container.
For VMware Workstation
You can use VMware Workstation as a hypervisor for Docker for Windows. The Installation section in Docker Machine VMware Workstation Driver explains how to do it.
The VMware Workstation driver has no option to specify a shared folder. You have to modify the VM configuration after created. If you specify dev
as the VM name, you can find the following setting in %USERPROFILE%/.docker/machine/machines/dev/dev.vmx
. It specifies C:\User
as a shared folder named Users
.
sharedFolder0.hostPath = "C:\Users"
sharedFolder0.guestName = "Users"
You should directly change it to C:\Source
or set the same setting by VMware Workstation.
sharedFolder0.hostPath = "C:Source"
sharedFolder0.guestName = "Source"
The VM by VMware Workstation automatically mounts the shared folder named Source
onto /mnt/hgfs/Source
in the container host. You can access C:\Source
through /destination
by docker run -v /mnt/hgfs/Source:/destination
.
For C:\Users
with VMware Workstation
By the way, the VMware driver for docker-machine not only set C:\Users
as a shared folder by default, but mount it onto /Users
and make a symbolic link /c/Users -> /Users
in the container host.
As a result, how to access C:\Users
from /destination
in a container is just the same as the case of VirtualBox driver, that is, docker run -v /c/Users:/destination
.
To achieve this compatibility with VirtualBox, the VMware driver runs the following shell script on a container host when you run docker-machine start
.
"C:/Program Files (x86)"/VMware/VMware Workstation/vmrun.exe -gu docker -gp tcuser
runScriptInGuest C:Usersfujie.dockermachinemachinesdevdev.vmx
/bin/sh [ ! -d /Users ]&& sudo mkdir /Users;
[ ! -d /c ]&& sudo mkdir -p /c;
[ ! -d /c/Users ]&& sudo ln -s /Users /c/Users;
[ -f /usr/local/bin/vmhgfs-fuse ]&&
sudo /usr/local/bin/vmhgfs-fuse -o allow_other .host:/Users /Users ||
sudo mount -t vmhgfs .host:/Users /Users
The actual is a one-liner.
How to mount a volume from Windows host to Windows guest system?
I am on Windows Server 2016 TP4 using Docker.
Following the documentation on
https://docs.docker.com/engine/userguide/containers/dockervolumes/
If you are using Docker Machine on Mac or Windows, your Docker daemon
has only limited access to your OS X or Windows filesystem. Docker
Machine tries to auto-share your /Users (OS X) or C:\Users (Windows)
directory. So, you can mount files or directories on OS X using.On Windows, mount directories using:
docker run -v /c/Users/[path]:/[container path] …`
I tried:
docker run --name iisdemo2 -it -p 80:80 -v /c/Users/mlin/meinedaten:/meinedaten iis cmd
which gives me an error:
docker : docker: Error response from daemon: Invalid bind mount spec "/c/Users/mlin/meinedaten:/meinedaten": volumeinvalid: Invalid volume specification:
'/c/Users/mlin/meinedaten:/meinedaten'.
I also tried:
docker run --name iisdemo2 -it -p 80:80 -v /c/Users/mlin/meinedaten:/c/meinedaten iis cmd
Note that the path C:\meinedaten on the guest/container exist already, which is required according to the docker documentation.
The command looks correct to me according to the documentation.
(Mounting volumes from Mac OS X host to Ubuntu docker container works fine, I am just having problems with Windows.)
Update
I also just tried to use Windows Containers natively (via Powershell), not using Docker. I follow the documentation on https://msdn.microsoft.com/en-us/virtualization/windowscontainers/quick_start/manage_powershell#create-a-shared-folder.
Add-ContainerSharedFolder -ContainerName mysql2 -SourcePath C:\Users\mlin\meinedaten -DestinationPath C:\meinedaten
But I am getting problems there are as well.
Eventually related topics:
- https://github.com/docker/docker/issues/12751
- https://github.com/testcontainers/testcontainers-java/issues/84
- https://stackoverflow.com/questions/36053968/mount-volume-to-host