So, now that Docker Desktop is paid under certain scenarios, you may want to switch to something else.
This is a straight to the point guide on how to make Docker CE run fully on WSL2.
PS: the title says right way, but it is just my personal opinion. I am not claiming that any other guide does it in a wrong way.
What you will get
- A full-fledged Docker installation on WSL2
- Docker Daemon automatic start without any crazy hacks
What you will not get
- Docker Daemon sharing between Windows and WSL (i.e. you cannot run docker from Windows PowerShell)
- Docker Daemon sharing between WSL distributions
Requisites
I will consider that you already have WSL2 working, and you are using Ubuntu as your distribution.
Guide
- Install Docker CE on Ubuntu by following the official guide:
# Ensures not older packages are installed
$ sudo apt-get remove docker docker-engine docker.io containerd runc
# Ensure pre-requisites are installed
$ sudo apt-get update
$ sudo apt-get install \
ca-certificates \
curl \
gnupg \
lsb-release
# Adds docker apt key
$ sudo mkdir -p /etc/apt/keyrings
$ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
# Adds docker apt repository
$ echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \
$(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
# Refreshes apt repos
$ sudo apt-get update
# Installs Docker CE
$ sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
- Perform the post-installation steps:
# Ensures docker group exists
$ sudo groupadd docker
# Ensures you are part of it
$ sudo usermod -aG docker $USER
# Now, close your shell and open another for taking the group changes into account
- Make Docker Daemon start on WSL initialization:
First, make sure you are running a recent version of WSL2 (you can update with wsl.exe --update
).
Then, you only need to add:
[boot]
systemd=true
To your /etc/wsl.conf
within your WSL distribution.
Then, restart it with wsl.exe --shutdown
.
To verify that docker works, you can run docker version
. If you do not receive any permission denied error, you are good to go.
You can also verify that Docker Compose got installed by running docker compose version
.
Bonus
- Installing Docker Compose Switch (to use the legacy
docker-compose
command instead ofdocker compose
):
# Finds the latest version
$ switch_version=$(curl -fsSL -o /dev/null -w "%{url_effective}" https://github.com/docker/compose-switch/releases/latest | xargs basename)
# Downloads the binary
$ sudo curl -fL -o /usr/local/bin/docker-compose \
"https://github.com/docker/compose-switch/releases/download/${switch_version}/docker-compose-linux-$(dpkg --print-architecture)"
# Assigns execution permission to it
$ sudo chmod +x /usr/local/bin/docker-compose
PS: I suggest to install the docker-compose
binary to /usr/local/bin/
because otherwise, the VS Code - Dev Containers extension will not find it.
To verify it works, you can run docker-compose version
.
- Install the Docker Credential Helper:
You will need this if you want Docker to store your credentials securely when you perform docker login
. Thanks to the WSL interoperability between Windows, you can install the Windows version of the Docker Credential Helper inside of WSL itself.
# Finds the latest version
$ wincred_version=$(curl -fsSL -o /dev/null -w "%{url_effective}" https://github.com/docker/docker-credential-helpers/releases/latest | xargs basename)
# Downloads and extracts the .exe
$ sudo curl -fL -o /usr/local/bin/docker-credential-wincred.exe \
"https://github.com/docker/docker-credential-helpers/releases/download/${wincred_version}/docker-credential-wincred-${wincred_version}.windows-$(dpkg --print-architecture).exe"
# Assigns execution permission to it
$ sudo chmod +x /usr/local/bin/docker-credential-wincred.exe
Then, configure your Docker CLI to use it by assuring that the following is present in your ~/.docker/config.json
:
{
"credsStore": "wincred.exe"
}
To verify that it works, you can try to docker login
and if not, Docker will complain about storing credentials in plain text.
Final considerations
The entire setup process may take some time, but you will have achieved almost everything that Docker Desktop used to provide to you (by the way, I use k3d
as an alternative to Docker Desktop's built-in K8s provisioner).
However, you can achieve a similar (and even higher/better) level of easiness that Docker Desktop provided to you by wrapping all the steps above in your dotfiles installation steps.
For example, in my dotfiles, all these steps are automated, including configuring /etc/docker/daemon.json
, changing ~/.profile
, and even providing a way to automatically update your extra binaries (docker-compose
, or the wincred.exe
) every time you update your dotfiles (by using a feature of chezmoi - a dotfiles manager which I totally recommend).
Top comments (39)
If you get the
Cannot connect to the Docker daemon at unix:///var/run/docker.sock.... error.
and have already tried starting the docker daemon, it may be that your docker daemon is crashing. This will happen if your WSL is still on version 1.To update, open PowerShell and type
If your distro is labeled as version 1, you can update it with
Where "Ubuntu" is the name of your distro.
That's absolutely true. Thanks for sharing the tip!
Hi Felipe! Thank you for this excellent guide! I was able to install using your dotfile link. All seems to work, however, I can't use docker login. It just times out. I do have WIndows 11 fully updated, and WSL 2. I even tried unregistering Ubuntu and loading a fresh copy. Repeated things and it won't let me log in. I'm using the username on the dockerhub upper right corner and the password I created when I created my account. What could I be doing wrong?
I repeated the whole process installing the wincred properly. This time it worked. Thanks!
I'm not sure if there was something wrong with the dotfiles installation (which could be fixed by running
chezmoi apply --force
if so), or maybe some bug with the WSL interoperability with.exe
- which I have more frequently than I liked.Anyway, I'm glad it's working now. :-)
You can run the commands in Powershell. You need to add proxy functions to your $PROFILE.
Replace the {} tokens with the relevant distribution and the username you use in that distribution.
Thanks for the tip, I would also recommend using PowerShell-WSL-Interop to achieve this.
Felipe,
First let me say thank you for sharing this with us! It is a very good help.
I do have one small issue. Today when I attempted to get the credential helper setup I get the following error:
curl: (22) The requested URL returned error: 404
I can see the .exe file for v0.7.0 but not seeing a .zip file though. So, I downloaded the .exe file and copied it to the
/usr/local/bin
location, issued thechmod
command and tried thedocker login
and it was successful.Hey, thanks for reporting it.
You're right about copying the file to
/usr/local/bin
, but don't forget to give it execution permission as well.I updated the guide to point the new changes.
Going just with adding the boot command to wsl.conf, I don't get a permission denied error, but 'docker version' gives version information and the
Cannot connect to the Docker daemon at unix:///var/run/docker.sock....
error. usingcommand = "sudo service docker start"
has the same effect. Editing the .profile does work thoughI have the same issue. I'm using WSL2. Any solution?
I've the same issue, and using wsl2 and ubuntu 22.04;
I found the possible reason.
If you are using debian or some ubuntu version that has iptables-nft as default:
Install Docker on Windows (WSL) without Docker Desktop.
Try it
sudo update-alternatives --config iptables
and change it to iptable-legacy
It works for me. ;)
That's interesting to know about. I haven't tried yet with Ubuntu 22.04, but I will try and update the guide in case something like this is missing. Thank you!
It turns out that it's indeed necessary for Ubuntu 22.04 on WSL. So, I added instructions for it in the guide. Thanks again for pointing out!
Just to update you, later versions of docker seems to have fixed the issue without requiring this step so I have removed it from the guide.
This specific feature is only available in Windows 11. See the link below for reference.
I also updated the guide to make this clearer.
docs.microsoft.com/en-us/windows/w...
But you can, of course, just use the alternative approach as the guide mentions.
Most likely your WSL version isn't new enough to support this feature.
This is an excellent replacement except I haven't been able to get K8s clusters from the WSL side to connect on the devcontainer side. Docker Desktop offers its built-in cluster API at a special address that resolves correctly back out of the devcontainer. Any other cluster: kind, k3d, minikube, created on the WSL side will not resolve inside the devcontainer.
This is the devcontainer feature I'm using to enable cluster access on the devcontainer side using its kubeconfig copy script to copy my local kubeconfig in.
Have you tried this? Is Docker Desktop somehow blessed in its operation?
In all my devcontainers, I add
--network=host
to therunArgs
of it, so that it does not suffer of this issue.However, have you tried Rancher Desktop? It may work for you.
Thanks Felipe. Works like a charm. Lovely :)
Signed up just to say thanks for this! Was driving me crazy that docker would not start automatically in Ubuntu. Was able to start manually with service docker start but with the addition to ~/.profile it starts automatically!
You are very welcome!
Thanks for this!
Which guide to docker networking would make a port I expose when running docker in wsl available to the Windows host?
So if in this docker setup I run
docker run -p 3000:3000 -it ruby bash
- I would like to be able to get to that port from the browser in Windows.You get that by default on every ports exposed in WSL, accessing through
localhost
. Unless you explicitly disabled. See this and this.Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?
What shows up if you type
sudo service docker start
?Chances are that your WSL version isn't new enough to support
boot.command
inwsl.conf
. Did you try the.profile
trick as mentioned in the guide?