Skip to content

Instantly share code, notes, and snippets.

@tjeufoolen
Last active November 7, 2022 15:23
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tjeufoolen/04f1316e0f7b2682f33147cf6641371a to your computer and use it in GitHub Desktop.
Save tjeufoolen/04f1316e0f7b2682f33147cf6641371a to your computer and use it in GitHub Desktop.
Install docker on Windows WSL2 Ubuntu without Docker Desktop

Install docker on Windows WSL2 Ubuntu without Docker Desktop

Table of contents

Prepare for Docker installation

Remove residue

sudo apt remove docker docker-engine docker.io containerd runc

Install dependencies

sudo apt install --no-install-recommends apt-transport-https ca-certificates curl gnupg2

Debian: switch to legacy iptables

Docker utilizes iptables to implement network isolation. For good reason, Debian uses the more modern nftables, but this means that Docker cannot automatically tweak the Linux firewall. Given this, you probably want to configure Debian to use the legacy iptables by default:

update-alternatives --config iptables

Debian/Ubuntu package repository configuration

On Debian or Ubuntu, first temporarily set some OS-specific variables:

. /etc/os-release

Then, make sure that apt will trust the repo:

curl -fsSL https://download.docker.com/linux/${ID}/gpg | sudo tee /etc/apt/trusted.gpg.d/docker.asc

ID will be either "ubuntu" or "debian", as appropriate, depending on what is in /etc/os-release.

Then add and update the repo information so that apt will use it in the future:

echo "deb [arch=amd64] https://download.docker.com/linux/${ID} ${VERSION_CODENAME} stable" | sudo tee /etc/apt/sources.list.d/docker.list
sudo apt update

Install Docker

sudo apt install docker-ce docker-ce-cli containerd.io

Fix permissions and share common ID

Add user to docker group

sudo usermod -aG docker $USER

Sharing dockerd: choose a common ID for the docker group

First, let's pick one. It can be any group ID that is not in use. Choose a number greater than 1000 and less than 65534. To see what group IDs are already assigned that are 1000 or above:

getent group | cut -d: -f3 | grep -E '^[0-9]{4}' | sort -g

Can't decide what number to use? May I suggest 36257. (Just dial DOCKR on your telephone keypad...) Not likely to be already in use, but check anyway:

getent group | grep 36257 || echo "Yes, that ID is free"

If the above command returns a line from /etc/group (that does not include docker), then pick another number and try again. If it returns "Yes, that ID is free" then you are good to go, with the following:

sudo sed -i -e 's/^\(docker:x\):[^:]\+/\1:36257/' /etc/group

Or, if groupmod is available (which it is on Fedora, Ubuntu, and Debian, but not Alpine unless you sudo apk add shadow), this is safer:

sudo groupmod -g 36257 docker

Prepare a shared directory

DOCKER_DIR=/mnt/wsl/shared-docker
mkdir -pm o=,ug=rwx "$DOCKER_DIR"
chgrp docker "$DOCKER_DIR"

Configure dockerd to use the shared directory

I suggest using the configuration file /etc/docker/daemon.json to set dockerd launch parameters. If the /etc/docker directory does not exist yet, create it with sudo mkdir /etc/docker/ so it can contain the config file. Then the following, when placed in /etc/docker/daemon.json, will set the docker host to the shared socket:

sudo mkdir /etc/docker && sudo nano /etc/docker/daemon.json

Paste the following contents:

{
  "hosts": ["unix:///mnt/wsl/shared-docker/docker.sock"]
}

Launch dockerd

sudo dockerd

Disclaimer; if you get an error mentioning IP tables, use the following command:

sudo update-alternatives --set iptables /usr/sbin/iptables-legacy sudo update-alternatives --set ip6tables /usr/sbin/ip6tables-legacy

Use shared docker socket

export DOCKER_HOST="unix:///mnt/wsl/shared-docker/docker.sock"

Test your work

docker run --rm hello-world

Setup automatic startup

Launch script for dockerd

The following lines can be placed in .bashrc or .profile if autolaunching is desired, or in a separate shell script. For instance, you may want to create a script ~/bin/docker-service so that you can run docker-service only when you want, manually.

DOCKER_DISTRO="Debian"
DOCKER_DIR=/mnt/wsl/shared-docker
DOCKER_SOCK="$DOCKER_DIR/docker.sock"
export DOCKER_HOST="unix://$DOCKER_SOCK"
if [ ! -S "$DOCKER_SOCK" ]; then
    mkdir -pm o=,ug=rwx "$DOCKER_DIR"
    chgrp docker "$DOCKER_DIR"
    /mnt/c/Windows/System32/wsl.exe -d $DOCKER_DISTRO sh -c "nohup sudo -b dockerd < /dev/null > $DOCKER_DIR/dockerd.log 2>&1"
fi

Passwordless launch of dockerd

If the above script is placed in .bashrc (most Linux distros) or .profile (distros like Alpine that have Ash/Dash as the default shell), or other shell init script, then it has an unfortunate side effect: you will likely be prompted for a password most every time a new terminal window is launched.

To work around this, you can, if you choose, tell sudo to grant passwordless access to dockerd, as long as the user is a member of the docker group. To do so, enter sudo visudo and add the following line (if your visudo uses vi or vim, then be sure to press "i" to begin editing, and hit ESC when done editing):

%docker ALL=(ALL)  NOPASSWD: /usr/bin/dockerd

References

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment