Mounting a Windows Shared Folder to a Docker container

Wynne Lo
6 min readJun 15, 2022

This task that sounded so simple actually took me 2 days to figure out.

If you’re just here looking for the solution, just jump straight to the bottom of the page.

I had a network shared drive on my Windows computer that my Docker container would need to access. So I needed to mount that shared drive to my Docker container.

My shared folder was accessible on my Windows computer through typing \\DinosaurDrive . There were folders in it like \\DinosaurDrive\Pictures , \\DinosaurDrive\Videos .

At first, I thought I could do it through a straightforward mount:

services:
scheduler:
volumes:
- //DinosaurDrive/Pictures:/mnt/dinosaur:rw

How naive. I then boot up the docker container and went inside to check

docker exec -it my-docker-container bash
$my-docker-container: cd /mnt

I see a dinosaur directory in there!

And it’s friggin’ empty.

Something about Windows shared drives make it so that this is more complicated than it seemed.

Google to the rescue

Google shows this useful solution, (despite the OP insisting that it’s impossible… it’s actually very possible, as suggested in the answers)

docker volume create --driver local --opt type=cifs --opt device=//networkdrive-ip/Folder --opt o=user=yourusername,domain=yourdomain,password=yourpassword mydockervolume

There’s also similar documentation on how to do this on the Docker official docs: https://docs.docker.com/storage/volumes/#create-cifssamba-volumes

Debugging

However I kept trying that command to no success. I kept running into completely useless error messages like these:

mount error(95): Operation in progress
Refer to the mount.cifs(8) manual page (e.g. man mount.cifs) and kernel log messages (dmesg)
mount error(115): Operation now in progress
Refer to the mount.cifs(8) manual page (e.g. man mount.cifs)
docker: Error response from daemon: error while mounting volume '/var/lib/docker/volumes/mediashare/_data': error while mounting volume with options: type='cifs' device='//localhost/private' o='username=user1,password=user1pass,sec=ntlm,vers=3.0': invalid argument.docker: Error response from daemon: error while mounting volume '/var/lib/docker/volumes/mediashare/_data': error while mounting volume with options: type='cifs' device='//localhost/private' o='username=user1,password=user1pass,sec=ntlm,vers=3.0': no such file or directory

The problem was that I am a complete networking noob and I didn’t actually have any idea what am I supposed to put in the addr or domain or even device field.

We need to fill in these fields in an absolute correct way for this to work:

  • device
  • username
  • domain
  • password
  • o (other stuff to pass in?)

All I knew was that \\DinosaurDrive\Pictures took me to where I needed to be… I had no idea what its address or what CIFS even is.

The point of this article is to give any newbie who is similar to me some more tools to figure out the problem.

What’s CIFS?

Apparently, there are two types of network drives/protocols: CIFS and NFS. CIFS is for talking between Windows/Linux computers. NFS is for pure Linux/Linux. So now you see why we have to choose the cifs in the docker mounting options.

Click on the article I linked there if you want to learn more.

How do I figure out what do I need to put in all those parameter fields?!

What you want to do is actually instantiate a test Docker container, and run smbclient from within it to test out your connection first.

# create a docker container
# doesn't really matter what it is, but I just put in nginx here
# you have to add --cap-add SYS_ADMIN --cap-add DAC_READ_SEARCH to it
# so that you can install linux packages to your container
C:\Users\trex> docker run -d --cap-add SYS_ADMIN --cap-add DAC_READ_SEARCH --name smbtest nginx:latest
# go into your docker container
C:\Users\trex> docker exec -it smbtest bash
# install smbclient
root@yourdockercontainer: apt-get update
root@yourdockercontainer: apt-get install smbclient

SMBClient lets you connect to any CIFS server just like how you would connect to FTP. So we are going to use this tool to test what is the IP or address that we need to input to connect to our shared drive.

But first, what IP should we even try?

Open up Command Prompt on Windows and type in ping DinosaurDrive . (or whatever the name of your drive is, e.g. in my case I use \\DinosaurDrive\Pictures to access my drive, so I would ping DinosaurDrive .)

You should a message similar to this:

The blacked out parts are where you should see an IP such as 192.168.0.1

Then also what’s my username?

Open up Command Prompt and type in whoami . That’s your username. You may notice it looks like this earth/trex — in this case, earth is your WorkGroup/domain and trex is your username. Either way, in the next step, just input earth/trex the whole thing as your username.

# type in smbclient to take a look at the commands available to you
root@yourdockercontainer: smbclient
Usage: smbclient [-?EgqBVNkPeC] [-?|--help] [--usage] [-R|--name-resolve=NAME-RESOLVE-ORDER] [-M|--message=HOST] [-I|--ip-address=IP] [-E|--stderr]
[-L|--list=HOST] [-m|--max-protocol=LEVEL] [-T|--tar=<c|x>IXFvgbNan] [-D|--directory=DIR] [-c|--command=STRING] [-b|--send-buffer=BYTES]
[-t|--timeout=SECONDS] [-p|--port=PORT] [-g|--grepable] [-q|--quiet] [-B|--browse] [-d|--debuglevel=DEBUGLEVEL]
[-s|--configfile=CONFIGFILE] [-l|--log-basename=LOGFILEBASE] [-V|--version] [--option=name=value] [-O|--socket-options=SOCKETOPTIONS]
[-n|--netbiosname=NETBIOSNAME] [-W|--workgroup=WORKGROUP] [-i|--scope=SCOPE] [-U|--user=USERNAME] [-N|--no-pass] [-k|--kerberos]
[-A|--authentication-file=FILE] [-S|--signing=on|off|required] [-P|--machine-pass] [-e|--encrypt] [-C|--use-ccache] [--pw-nt-hash]
service <password>
# put in the IP you just got from pinging earlier
# you have to make sure you add a folder, e.g. in my case it was Pictures
# Top level without indicating a folder won't work
# Put in the username that you got from whoami
root@yourdockercontainer: smbclient //192.168.60.1/Pictures --user=earth/trex
# This would prompt you for your password. This is the password you use to login to your Windows
Enter earth\trex's password:
# If you succeeded, you should see this prompt
# try `ls` to see if you can see the files you are expecting
Try "help" to get a list of possible commands.
smb: \>

If it didn’t log you in successfully, at least now you know there’s something wrong with your username, password, or IP address. And with the error messages from smbclient, it should be easier to debug.

So now we at least figured out what to put in

  • device
  • username
  • password

We still need to figure out what exactly or how exactly o should be formatted.

Linux Mounting

The next step is to try to mount to the shared drive with the Linux mount command.
For that, we need to install cifs-utils first:

apt-get install cifs-utils

Refer to this page on how to use the linux mount command: https://linuxize.com/post/how-to-mount-cifs-windows-share-on-linux/

# create the directory you are planning to mount to
root@yourdockercontainer: mkdir /mnt/DinoPictures
# So I followed the instructions on that page and ran this naively
mount -t cifs -o "username=trex,password=******,domain=earth" //192.168.60.1/Pictures /mnt/DinoPictures
mount error(95): Operation not supported
Refer to the mount.cifs(8) manual page (e.g. man mount.cifs) and kernel log messages (dmesg)

It gives us a completely cryptic error message — operation not supported… And the kernel logs didn’t help much either. After a bunch of googling, it turns out I had to add vers=1.0 to the command!

mount -t cifs -o "username=trex,password=******,domain=earth,vers=1.0" //192.168.60.1/Pictures /mnt/DinoPictures

So now we finally know what we need to put in the o options!

Now exit out of the container and go back to your Docker.

Putting everything together

docker volume create --driver local --opt type=cifs --opt device=//192.168.60.1/Pictures --opt o=username=trex,password=******,domain=earth,vers=1.0 dinovolume

Or in my case, I put it in my docker-compose file:

version: "3.1"
services:
scheduler:
volumes:
- dinovolume:/mnt/cashftp:rw
volumes:
dinovolume:
driver_opts:
type: cifs
o: username=trex,password=*******,domain=earth,vers=1.0
device: //192.168.60.1/Pictures

Viola! It should work perfectly now!

Hopefully this helps any fellow newbie out there.

--

--