Part IIb: Setup WSL and Docker

This is Part IIb of a 3 1/2-part blog post on how I configured my working environment. Here I’ll explain how to configure WSL together with Docker. Note that I do not use Docker on Windows very often these days. I mainly connect to VMs via WSL and use Docker remotely. However, sometimes, Docker on Windows may become handy - have a look at the instructions below on how to configure WSL together with Docker on Windows.

  • Part I: Setup Dev Environment in Windows
  • Part IIa: Windows Subsystem for Linux (WSL)
  • Part IIb: WSL & Docker setup
  • Part III: Installation of additional packages and tools in WSL

Install Docker

You want to be able to run docker-compose and docker client from WSL1, but the backend needs to be run through native Windows 10 Docker Server. Therefore, install Docker Desktop for Windows 10 first.

Option 1: Install with Chocolatey Package Manager with choco install docker-desktop

Option 2: Download from here and install manually

Setup Docker

In Docker Desktop (Windows), under General, make sure you uncheck Expose daemon on tcp://localhost/2375 without TLS.

Also, disable Use the WSL 2 based engine.

Under Shared Drives, select the drive where you keep your project folders (e.g. docker-compose.yml etc.).

This will allow docker from WSL1 access files on this drive, which is necessary if you want to execute docker-compose in a folder on d:.

I’ve also changed some of the Resource/Advanced settings to fit my needs:

As you can see, I’ve also changed the location where Docker stores my virtual containers to D:

From now on, we’re working in the WSL bash (open with right-click and Open WSL bash here).

  • Update the apt package list.
sudo apt-get update
  • Install Docker’s package dependencies.
sudo apt-get install \
    ca-certificates \
    curl \
    gnupg \
    lsb-release
  • Download and add Docker’s official public PGP key.
sudo mkdir -m 0755 -p /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/debian/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
  • Use the following command to set up the repository
echo \
  "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/debian \
  $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
  • Install Docker Engine
sudo chmod a+r /etc/apt/keyrings/docker.gpg
sudo apt-get update
  • Install Docker Engine, containerd, and Docker Compose.
sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
  • Allow your user to access the Docker CLI without needing root access.
sudo usermod -aG docker $USER

Docker Compose

There is no need to install docker-compose anymore.

docker compose is now available by default (note the missing - in the command)

Setup secure WSL1-Docker connection

A secure connection between WSL1 and Docker Desktop is available through socat1 and npiperelay.

Connect WSL1<->Docker the insecure way?

The steps to set up npiperelay:

  1. Install Socat and tmux
  • tmux for starting the relay in a background session
  • socat for the docker relay stream
sudo apt update && sudo apt install socat tmux
  1. Get the the npiperelay.exe and setup connection

You need to use your Windows username (/c/Users/<username>).

Export your Windows user name as a variable:

export wuser=<username>

Get npiperelay.exe from Github releases, build, and store in Windows user directory:

cd /c/Users/$wuser/
mkdir -p go/bin/
wget -O \
    go/bin/npiperelay_windows_amd64.zip \
    https://github.com/jstarks/npiperelay/releases/download/v0.1.0/npiperelay_windows_amd64.zip
unzip -d go/bin/ go/bin/npiperelay_windows_amd64.zip
rm go/bin/npiperelay_windows_amd64.zip

Symlink npiperelay.exe from Windows to WSL1:

sudo ln -s \
    /c/Users/$wuser/go/bin/npiperelay.exe \
    /usr/local/bin/npiperelay.exe

Get docker-relay script and run as background task:

cd ~
git clone https://github.com/jstarks/npiperelay.git
sudo ln -s ~/npiperelay/scripts/docker-relay /usr/local/bin/
chmod +x /usr/local/bin/docker-relay

We modify docker-relay so it starts the Socket inside the user directory.

mkdir ~/sockets
nano /usr/local/bin/docker-relay

Add the following. Make sure to replace {replace-with-your-username} with your WSL1 username.

#!/bin/sh
SOCKET=/home/{replace-with-your-username}/sockets/docker.sock
if [ -e $SOCKET ]; then rm $SOCKET; fi
exec socat UNIX-LISTEN:$SOCKET,fork,group=docker,umask=007 EXEC:"npiperelay.exe -ep -s //./pipe/docker_engine",nofork

Store with CTRL+O.

I also had to manually remove the docker.sock and symlink with the new one:

cd /var/run
sudo rm docker.sock
sudo ln -s /home/alex/sockets/docker.sock /var/run/docker.sock

Test it with:

sudo docker-relay &
docker info
> Client:
>  Context:    default
>  Debug Mode: false
>  Plugins:
>   app: Docker App (Docker Inc., v0.9.1-beta3)
>   buildx: Build with BuildKit (Docker Inc., v0.5.1-docker)
>   scan: Docker Scan (Docker Inc., v0.8.0)

You may need to add permissions to the docker-sock:

sudo chown $USER:$USER /home/$USER/sockets/docker.sock

To autostart the relay, we need to add these lines to ~/.bashrc:

# set WSL env; configure secure Docker connection through
# socat and npiperelay
if cat /proc/version | grep Microsoft > /dev/null; then
  export WSL=true
fi
if [ "$WSL" ]; then
  export DOCKER_HOST="unix://$HOME/sockets/docker.sock"
  if ! pgrep socat > /dev/null; then
    tmux new -s docker-relay-session -d docker-relay
  fi
fi

(nano ~/.bashrc)

Finally, some commands may use sudo to start docker. In this case, DOCKER_HOST will not be available. Modify sudoers to keep this entry:

sudo nano /etc/sudoers

and add the following line:

Defaults env_keep += DOCKER_HOST

Test docker in WSL

Restart Docker for windows!

docker run hello-world

Some additional information for working with WSL & Docker follow below.

Fix Docker Connectivity Bug

There seems to be a bug, where Docker on Windows 10 may see errors similar to this after restarting the computer:

Cannot restart container my_container: driver failed programming external connectivity on endpoint my_container 
...

The steps described below may solve this issue.

How to disable fast startup on Windows 10

Disable it in just a few steps:

  1. Right-click the Start button.
  2. Click Search.
  3. Type Control Panel and hit Enter on your keyboard.
  4. Click Power Options.
  5. Click Choose what the power buttons do.
  6. Click Change settings that are currently unavailable.
  7. Click Turn on fast startup (recommended) so that the check-mark disappears.
  8. Click Save changes.
Annoying WSL bug: Missing Access rights

Now this may occur on very few occasions, only for WSL1 - for me it happened mainly when building python packages (e.g. setuptools, distutils, pypi). Since the latest Windows Update, some access rights changed and those affect how packages in WSL can access folders.

Wherever you keep your code, right click main folder, select Security and allow “Full Access” to authenticated users.

full access

Update from WSL 1 to WSL 2

Fix Docker Connectivity after WSL2 upgrade

If you used WSL1 before, there may be an entry in ~/.bashrc file that must be removed.

  1. Removed export DOCKER_HOST=tcp://localhost:2375 from ~/.bashrc;

  2. Disabled Expose daemon on tcp://localhost:2375 without TLS in Docker Desktop;

  3. Enabled Use the WSL 2 based engine in Docker Desktop

See WSL/issues/4321