DEV Community

Running Docker on WSL2 without Docker Desktop (the right way)

Felipe Santos on October 15, 2021

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 ho...
Collapse
 
mattschlosser profile image
Matt Schlosser

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

wsl.exe --list --verbose
Enter fullscreen mode Exit fullscreen mode

If your distro is labeled as version 1, you can update it with

 wsl.exe --set-version Ubuntu 2
Enter fullscreen mode Exit fullscreen mode

Where "Ubuntu" is the name of your distro.

Collapse
 
felipecrs profile image
Felipe Santos

That's absolutely true. Thanks for sharing the tip!

Collapse
 
terminatedprocess profile image
Mark Ryan

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?

Collapse
 
terminatedprocess profile image
Mark Ryan

I repeated the whole process installing the wincred properly. This time it worked. Thanks!

Collapse
 
felipecrs profile image
Felipe Santos

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. :-)

Collapse
 
ac76 profile image
Adam Carr • Edited

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.

function docker {
    wsl -d "{DISTRO_NAME}" -u {DISTRO_USER} -e docker $args
}

function docker-compose {
    wsl -d "{DISTRO_NAME}" -u {DISTRO_USER} -e docker-compose $args
}
Enter fullscreen mode Exit fullscreen mode
Collapse
 
felipecrs profile image
Felipe Santos

Thanks for the tip, I would also recommend using PowerShell-WSL-Interop to achieve this.

Collapse
 
douglewis22 profile image
douglewis22 • Edited

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 the chmod command and tried the docker login and it was successful.

Collapse
 
felipecrs profile image
Felipe Santos

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.

Collapse
 
nmtoken profile image
James Passmore • Edited

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. using command = "sudo service docker start" has the same effect. Editing the .profile does work though

Collapse
 
jledesma84 profile image
jledesma84

I have the same issue. I'm using WSL2. Any solution?

Collapse
 
lemosluan profile image
Luan Lemos Almeida

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. ;)

Thread Thread
 
felipecrs profile image
Felipe Santos

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!

Thread Thread
 
felipecrs profile image
Felipe Santos • Edited

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!

Thread Thread
 
felipecrs profile image
Felipe Santos

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.

Collapse
 
felipecrs profile image
Felipe Santos • Edited

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.

Collapse
 
felipecrs profile image
Felipe Santos

Most likely your WSL version isn't new enough to support this feature.

Collapse
 
david24622147 profile image
David

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?

Collapse
 
felipecrs profile image
Felipe Santos

In all my devcontainers, I add --network=host to the runArgs of it, so that it does not suffer of this issue.

However, have you tried Rancher Desktop? It may work for you.

Collapse
 
mariomeyrelles profile image
Mario Meyrelles

Thanks Felipe. Works like a charm. Lovely :)

Collapse
 
trevmlt profile image
trevmlt

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!

Collapse
 
felipecrs profile image
Felipe Santos

You are very welcome!

Collapse
 
darwinjs profile image
Darwin Sanoy

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.

Collapse
 
felipecrs profile image
Felipe Santos

You get that by default on every ports exposed in WSL, accessing through localhost. Unless you explicitly disabled. See this and this.

Collapse
 
zachary profile image
zachary

Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?

Collapse
 
felipecrs profile image
Felipe Santos

What shows up if you type sudo service docker start?

Collapse
 
felipecrs profile image
Felipe Santos

Chances are that your WSL version isn't new enough to support boot.command in wsl.conf. Did you try the .profile trick as mentioned in the guide?

Collapse
 
proscatinatingpro profile image
Trung Ly

Note that if wsl2 is set to networkingMode=mirrored, you will might run into issues trying to connect to the container from your Windows host (on the same local machine). Connecting from other host within the network worked but ymmv depending on your setup. A workaround from on gist.github.com/shigenobuokamoto/b... and github.com/microsoft/WSL/issues/10... finally addressed the issue for me.

Create a new file as root /etc/systemd/system/network-mirrored.service

[Unit]
Wants=network-pre.target
Before=network-pre.target shutdown.target

[Service]
User=root
ExecStart=/bin/sh -ec '\
  [ -x /usr/bin/wslinfo ] && [ "$(/usr/bin/wslinfo --networking-mode)" = "mirrored" ] || exit 0;\
  echo "\
  add chain   ip nat WSLPREROUTING { type nat hook prerouting priority dstnat - 1; policy accept; };\
  insert rule ip nat WSLPREROUTING iif loopback0  ip daddr 127.0.0.1 counter dnat to 127.0.0.1 comment mirrored;\
  "|nft -f -\
'
ExecStop=/bin/sh -ec '\
  [ -x /usr/bin/wslinfo ] && [ "$(/usr/bin/wslinfo --networking-mode)" = "mirrored" ] || exit 0;\
  for chain in "ip nat WSLPREROUTING";\
  do\
    handle=$(nft -a list chain $chain | sed -En "s/^.*comment \\"mirrored\\" # handle ([0-9]+)$/\\1/p");\
    for n in $handle; do echo "delete rule $chain handle $n"; done;\
  done|nft -f -\
'
RemainAfterExit=yes
[Install]
WantedBy=multi-user.target
Enter fullscreen mode Exit fullscreen mode

When you have created the file, run it by $ sudo systemctl --now enable network-mirrored. This may or may not resolve the issue. If it doesn't, add the following to your ** .wslconfig**, the one found in **Windows **host, not the Linux distro (wsl.config).

firewall=false
dnsTunneling=true
Enter fullscreen mode Exit fullscreen mode

So that your full file could look something like this:

[wsl2]
networkingMode=mirrored
firewall=false
dnsTunneling=true

[experimental]
autoMemoryReclaim=gradual
Enter fullscreen mode Exit fullscreen mode

Reboot your wsl2 instance from powershell and open a new wsl2 instance:

wsl --shutdown
wsl
Enter fullscreen mode Exit fullscreen mode
Collapse
 
mhangaard profile image
Martin Hangaard Hansen

Thank you for this tutorial @felipecrs . Will this work together with an Azure Client installed on windows?

For example:
$ which az
/mnt/c/Program Files (x86)/Microsoft SDKs/Azure/CLI2/wbin/az

with az acr login?

Thanks
Martin

Collapse
 
felipecrs profile image
Felipe Santos

If it delegates to the docker cli I see no reason for it not to work. Let me know if you ended up testing it, though.

Collapse
 
mhangaard profile image
Martin Hangaard Hansen

I couldn't get it to do it, but worked around by taking the token from az and passing it to docker login

docker login ${MY_ACR}.azurecr.io -u 00000000-0000-0000-0000-000000000000 -p $(az acr login -n ${MY_ACR} --expose-token | jq .'accessToken' | tr -d \")
Enter fullscreen mode Exit fullscreen mode
Collapse
 
sstranks profile image
Simon Stranks

Any idea how to get rootless working on WSL2? I can get the rootless daemon running successfully, but it won't connect to the docker registry when trying to pull images - 'no such host'.

I managed to get it working on WSL2 Ubuntu 20.04 then stupidly upgraded it (and WSL2). Something somewhere obviously broke and now I can't get it working again.

Collapse
 
sstranks profile image
Simon Stranks

OK just found the solution: github.com/microsoft/WSL/issues/74...

I'm using WSL2 on Windows 10, Ubuntu 22.04 LTS.

  • Install Docker Engine using the official instructions, using apt-repository method docs.docker.com
  • Install Docker Rootless using the official instructions docs.docker.com - add the '--skip-iptables' flag to the install command.
  • As per the solution linked above, create/amend the '/etc/wsl.conf' file to enable 'systemd' (works on WSL2 now, both Windows 10 and 11) and disable WSL from automatically creating '/etc/resolv.conf', so we can create our own manually and set the nameserver to 1.1.1.1.

You don't need to change iptables to legacy anymore either, you can leave them on the newer nft setting.

Collapse
 
abirb profile image
abirax • Edited

Hi Felipe,

Thanks for the article, I am on ubuntu 22 I am able to start docker but unable to pull images from docker.io I get an error
When I run docker pull hello-world
i get the error:
Using default tag: latest
Error response from daemon: unknown:

408 Request Time-out


Your browser didn't send a complete request in time.

any idea? My proxies are fine since I can run curl docker.io -v
I also tried docker login and it didnt work
I get errors like
docker: Error response from daemon: Get "registry-1.docker.io/v2/": dial tcp: lookup registry-1.docker.io on [::1]:53: read udp [::1]:56718->[::1]:53: read: connection refused.

Collapse
 
eramosce profile image
eramos-ce

Felipe, this worked great! I am trying to identify what to migrate to now that Docker for Windows changed their licensing model.

Thank you for sharing!

Collapse
 
felipecrs profile image
Felipe Santos

Awesome! I'm very glad it helped you!

Collapse
 
vikas_bhandari_2e2a7aead1 profile image
Vikas Bhandari

Docker not starting in wsl2 arm machine. Getting Iptables related issues.
ERROR:

Unable to detect if iptables supports xlock: 'iptables --wait -L -n ': 'iptables v1.8.7 (legacy): can't initialize iptables table 'filter': Table does not exist (do you need to insmod?)

I have tried the switching from iptables-nft to iptables-legacy as well but still seeing the same issue can someone help please.

Collapse
 
bhabermann profile image
Bruno Habermann

Excelente conteúdo! Me ajudou demais.

Collapse
 
bwdavis profile image
bwdavis

Very good guide, thank you very much. It solved our issue.