Docker mount folder to container windows

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.

  1. Before stopping the machine you will want to make sure that your containers are stopped.

     $ docker ps
    
  2. For any containers that are returned you can stop them by running

     $ docker stop [Container ID]
    
  3. 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

  1. 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
  2. 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.

  1. Before stopping the machine you will want to make sure that your containers are stopped.

     $ docker ps
    
  2. For any containers that are returned you can stop them by running

     $ docker stop [Container ID]
    
  3. 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.

  1. Navigate to the Virtualbox directory.

     $ cd "c:\Program Files\Oracle\Virtualbox"
    
  2. 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.

  1. 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”
  2. In order to mount the directories we need to ssh into the docker machine

     $ docker-machine ssh default
    
  3. 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/
    
  4. 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
    
  5. exit the ssh session

  6. 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/Usersas 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.

enter image description here

(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.

enter image description here

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

  • Docker hyper v windows 10
  • Docker desktop for windows 10 не запускается
  • Docker for windows server 2016
  • Docker desktop for windows 10 install
  • Docker for windows server 2012