Docker on WSL for Windows 10

Configure Docker for Windows

In the general settings, you’ll want to expose the daemon without TLS. This step is necessary so that the daemon listens on a TCP endpoint. If you don’t do this then you won’t be able to connect from WSL.

blog/docker-for-windows-expose-daemon-without-tls.jpg

You may also want to share any drives you plan on having your source code reside on. This step isn’t necessary but I keep my code on a regular HDD, so I shared my “E” drive too.

Can’t use Docker for Windows?

This is only necessary if you are NOT running Docker for Windows!

No problem, just configure your Docker daemon to use -H tcp://0.0.0.0:2375 and --tlsverify=false. Then you can follow along with the rest of this guide exactly.

 

Here’s the Ubuntu 16 installation notes taken from Docker’s documentation:

This will install the edge channel, change ‘edge’ to ‘stable’ if you want. You may also want to update the Docker Compose version based on the latest release.

# Environment variables you need to set so you don't have to edit the script below.
export DOCKER_CHANNEL=edge
export DOCKER_COMPOSE_VERSION=1.21.0

# Update the apt package index.
sudo apt-get update

# Install packages to allow apt to use a repository over HTTPS.
sudo apt-get install -y \
    apt-transport-https \
    ca-certificates \
    curl \
    software-properties-common

# Add Docker's official GPG key.
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -

# Verify the fingerprint.
sudo apt-key fingerprint 0EBFCD88

# Pick the release channel.
sudo add-apt-repository \
   "deb [arch=amd64] https://download.docker.com/linux/ubuntu \
   $(lsb_release -cs) \
   ${DOCKER_CHANNEL}"

# Update the apt package index.
sudo apt-get update

# Install the latest version of Docker CE.
sudo apt-get install -y docker-ce

# Allow your user to access the Docker CLI without needing root.
sudo usermod -aG docker $USER

# Install Docker Compose.
sudo curl -L https://github.com/docker/compose/releases/download/${DOCKER_COMPOSE_VERSION}/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose &&
sudo chmod +x /usr/local/bin/docker-compose

At this point you must close your terminal and open a new one so that you can run Docker without sudo. You might as well do it now!

Configure WSL to Connect to Docker for Windows

The next step is to configure WSL so that it knows how to connect to the remote Docker daemon running in Docker for Windows (remember, it’s listening on port 2375).

Open up your ~/.bashrc file and add this line to the bottom:

export DOCKER_HOST=tcp://0.0.0.0:2375

Logout of your WSL shell and come back in, or run source ~/.bashrc to reload it now.

If you want to get cute, you could do all of that with this 1 liner:

echo "export DOCKER_HOST=tcp://0.0.0.0:2375" >> ~/.bashrc && source ~/.bashrc

You can verify it works by running docker info. You should get back a list of details. If you get a permission denied error then make sure you log out and log back in, because that’s necessary to apply the changes so non-root users can run Docker. That’s what the sudo usermod bit of the long command did in the command chain when installing Docker.

Ensure Volume Mounts Work

The last thing we need to do is set things up so that volume mounts work. This tripped me up for a while because check this out…

When using WSL, Docker for Windows expects you to supply your volume paths in a format that matches this: /c/Users/bcochran/dev/myapp.

But, WSL doesn’t work like that. Instead, it uses the /mnt/c/Users/bcochran/dev/myapp format.

To get things to work for now, you need to bind a custom mount for any drives that you shared with Docker for Windows.

Bind custom mount points to fix Docker for Windows and WSL differences:
sudo mkdir /c
sudo mount --bind /mnt/c /c

You’ll want to repeat those commands for any drives that you shared, such as d or e, etc..

Verify that it works by running: ls -la /c. You should see the same exact output as running ls -la /mnt/cbecause /mnt/c is mounted to /c.

You can use volume mount paths like .:/myapp in your Docker Compose files and everything will work like normal. That’s awesome because that format is what native Linux and MacOS users also use.

It’s worth noting that whenever you run a docker-compose up, you’ll want to make sure you navigate to the /c/Users/bcochran/dev/myapp location first, otherwise your volume won’t work. In other words, never access /mnt/cdirectly.

 

Automatically set up the bind mount:

 

You can do that with this 1 liner: echo "sudo mount --bind /mnt/c /c" >> ~/.bashrc && source ~/.bashrc and make sure to repeat the command for any additional drives you shared with Docker for Windows. By the way, you don’t need to mkdir because we already did it.

Allow your user to bind a mount without a root password:

To do that, run the sudo visudo command.

That should open up nano (a text editor). Goto the bottom of the file and add this line: bcochran ALL=(root) NOPASSWD: /bin/mount, but replace “bcochran” with your username.

That just allows your user to execute the sudo mount command without having to supply a password. You can save the file with CTRL+O, confirm and exit with CTRL+X.