1. Overview
It is now possible to run Docker containers on Windows 10 and Windows Server, leveraging Ubuntu as a hosting base.
Imagine running your own Linux applications on Windows, using a Linux distribution you are comfortable with: Ubuntu!
It is now possible to do so using the power of Docker technology and Hyper-V virtualization on Windows.
Originally authored by Mathieu Trudel-Lapierre.
2. Requirements
You will need a 64-bit x86 PC with 8GiB of RAM running Windows 10 or Windows Server, updated to include the Windows 10 Fall Creator update, released October 2017.
You will also need a recent installation of Docker.
Finally, you will need to make sure you have installed a program for decompressing the Ubuntu host container image, e.g. 7-Zip or XZ Utils
3. Install Docker for Windows
Download Docker for Windows from Docker Store.
Once downloaded, proceed with the installation steps, and either logout or reboot of your system as indicated by the installer.
After reboot, Docker will be started. Docker requires that the Hyper-V feature is enabled, so if necessary will ask you to enable it and restart. Click OK for Docker to enable Hyper-V and restart your system.
4. Download the Ubuntu container image
Download the latest Ubuntu container image for Windows from the Canonical Partner Images website
Once downloaded, extract the image, using e.g. 7-Zip, or XZ Utils:
C:\Users\mathi\> .\xz.exe -d xenial-container-hyper-v.vhdx.xz
5. Prepare the container environment
First, create two directories:
Create C:\lcow, which will be used as scratch space for Docker while preparing the containers.
Also create C:\Program Files\Linux Containers. This is where the Ubuntu container image will live.
You will need to give this folder extra permissions to allow Docker to use the images from it. Run the following Powershell script in an administrator Powershell window:
param(
[string] $Root
)
# Give the virtual machines group full control
$acl = Get-Acl -Path $Root
$vmGroupRule = new-object System.Security.AccessControl.FileSystemAccessRule("NT VIRTUAL MACHINE\Virtual Machines", "FullControl","ContainerInherit,ObjectInherit", "None", "Allow")
$acl.SetAccessRule($vmGroupRule)
Set-Acl -AclObject $acl -Path $Root
Save this file as set_perms.ps1 and run it:
TIP You may need to run ‘Set-ExecutionPolicy -Scope process unrestricted’ to be allowed to run unsigned Powershell scripts.
C:\Users\mathi\> .\set_perms.ps1 "C:\Program Files\Linux Containers"
C:\Users\mathi\>
Now, copy the Ubuntu container image .vhdx file that was decompressed at the previous step to uvm.vhdx under C:\Program Files\Linux Containers.
6. More Docker preparation
Docker for Windows requires some pre-release features in order to work with Hyper-V isolation. While these features are not yet available in the Docker CE installation that was done previously, the necessary files can be downloaded from master.dockerproject.org.
Retrieve dockerd.exe and docker.exe from master.dockerproject.org, and put the two programs somewhere safe, such as in your own folder. They will be used to start the Ubuntu container in the next step.
7. Run an Ubuntu container on Hyper-V
You’re now ready to start your container. First, open a Command-line prompt (cmd.exe) as Administrator, and start dockerd.exe with the right environment:
C:\Users\mathi\> set LCOW_SUPPORTED=1
C:\Users\mathi\> .\dockerd.exe -D --data-root C:\lcow
Docker already running?
If the Docker installer sets Docker to run automatically at boot, you may need to quit the already running daemon, via its toolbar icon, before running the above commands.
Then, start a Powershell window as Administrator; and run docker.exe, instructing it to pull the image for your container:
C:\Users\mathi\> .\docker.exe pull ubuntu
We can now finally start the container. Run docker.exe again, and tell it to run the new image:
C:\Users\mathi\> .\docker.exe run -it ubuntu
Congratulations! You have successfully set up your system to use containers with Hyper-V isolation on Windows, and have run your very own Ubuntu container.
8. Getting help
If you need some guidance getting started with the Ubuntu container images for Hyper-V, or if you get stuck, help is always at hand:
- Ask Ubuntu
- Ubuntu Forums
- IRC-based support
Was this tutorial useful?
Thank you for your feedback.
Время на прочтение
4 мин
Количество просмотров 89K
Для полноценной работы с проектом на docker’е в WSL необходима установка WSL 2. На момент написания заметки ее использование возможно только в рамках участия в программе предварительной оценки Windows (WSL 2 доступна в сборках 18932 и выше). Так же отдельно стоит упомянуть, что необходима версия Windows 10 Pro для установки и настройки Docker Desktop.
Важно! В WSL 2 пропала острая необходимость в Docker Desktop для Windows 10. Как обходиться без него описано в пункте Про Docker в Ubuntu.
Первые шаги
После вступления в программу предварительной оценки и установки обновлений необходимо установить дистрибутив Linux (в данном примере используется Ubuntu 18.04) и Docker Desktop с WSL 2 Tech Preview:
- Docker Desktop WSL 2 Tech Preview
- Ubuntu 18.04 из Windows Store
В обоих пунктах следуем всем инструкциям по установке и настройке.
Установка дистрибутива Ubuntu 18.04
Перед запуском Ubuntu 18.04 необходимо включить Windows WSL и Windows Virtual Machine Platform посредством выполнения двух команд в PowerShell:
Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Windows-Subsystem-Linux
(потребует перезагрузку компьютера)Enable-WindowsOptionalFeature -Online -FeatureName VirtualMachinePlatform
После необходимо удостовериться, что мы будем использовать WSL v2. Для этого в терминале WSL или PowerShell последовательно выполняем команды:
wsl -l -v
— смотрим, какая версия установлена в данный момент. Если 1, то движемся далее по спискуwsl --set-version ubuntu 18.04 2
— для обновления до версии 2wsl -s ubuntu 18.04
— устанавливаем Ubuntu 18.04 в качестве дистрибутива по-умолчанию
Теперь можно запустить Ubuntu 18.04, провести настройку (указать имя пользователя и пароль).
Установка Docker Desktop
Важно! В WSL 2 пропала острая необходимость в Docker Desktop для Windows 10. Как обходиться без него описано в пункте Про Docker в Ubuntu.
В процессе установки следуем указаниям. Компьютер потребует перезапуск после установки и при первом запуске для включения Hyper-V (из-за поддержки которого и требуется версия Windows 10 Pro).
Важно! Если Docker Desktop сообщит о блокировке со стороны firewall’а, идем в настройки антивируса и вносим следующие изменения в правила сетевого экрана (в данном примере в качестве антивируса используется Kaspersky Total Security):
- Проходим в Настройки -> Защита -> Сетевой экран -> Настроить пакетные правила -> Local Service (TCP) -> Изменить
- Из списка локальных портов удаляем порт 445
- Сохранить
После запуска Docker Desktop в его контекстном меню выбираем пункт WSL 2 Tech Preview.
В открывшемся окне нажимаем кнопку Start.
Теперь docker и docker-compose доступны внутри дистрибутива WSL.
Важно! В обновленном Docker Desktop теперь вкладка с WSL внутри окна настроек. Там включается поддержка WSL.
Важно! Помимо галочки активации WSL также необходимо в вкладке Resources->WSL Integration активировать Ваш WSL дистрибутив.
Запуск
Неожиданностью стали те многие проблемы, которые возникли при попытке поднять контейнеры проектов, расположенных в директории пользователя Windows.
Ошибки различного рода, связанные с запуском bash-скриптов (которые как правило стартуют при сборке контейнеров для установки необходимых библиотек и дистрибутивов) и прочих, обычных для разработки на Linux, вещей, заставили задуматься о размещении проектов непосредственно в директории пользователя Ubuntu 18.04.
.
Из решения предыдущей проблемы вытекает следующая: как работать с файлами проекта через IDE, установленную на Windows. В качестве «best practice» я нашел для себя только один вариант — работа посредством VSCode (хотя являюсь поклонником PhpStorm).
После скачивания и установки VSCode обязательно устанавливаем в расширение Remote Development extension pack.
После установки выше упомянутого расширения достаточно просто выполнить команду code .
в директории проекта при запущенной VSCode.
В данном примере для обращения к контейнерам через браузер необходим nginx. Установить его через sudo apt-get install nginx
оказалось не так просто. Для начала потребовалось обновить дистрибутив WSL посредством выполнения sudo apt update && sudo apt dist-upgrade
, и только после этого запустить установку nginx.
Важно! Все локальные домены прописываются не в файле /etc/hosts дистрибутива Linux (его там даже нет), а в файле hosts (обычно расположенном C:\Windows\System32\drivers\etc\hosts) Windows 10.
Про Docker в Ubuntu
Как подсказали знающие пользователи в комментариях к заметке, docker внутри дистрибутива WSL 2 абсолютно работоспособен. Это позволяет не устанавливать Docker Desktop на Windows 10 и решает проблему с наличием версии Windows 10 Pro (необходимость в Pro возникает именно в связи с использованием Docker Desktop). Устанавливается согласно инструкциям с родного сайта:
- https://docs.docker.com/install/linux/docker-ce/ubuntu/
- https://docs.docker.com/install/linux/linux-postinstall/
- https://docs.docker.com/compose/install/
Если при выполнении команды docker начнет ругаться на демона, проверьте статус сервиса — в моем случае как и nginx он не запускается автоматически. Запустите его командой sudo service docker start
.
Если в момент сборки вывалится ошибка «Service failed to build: cgroups: cannot find cgroup mount destination: unknown» попробуйте следующее решение (не мое, найдено мною, ссылка в источниках): sudo mkdir /sys/fs/cgroup/systemd
; sudo mount -t cgroup -o none,name=systemd cgroup /sys/fs/cgroup/systemd
.
Работа с проектом через PhpStorm
Чтобы обеспечить возможность работы с проектом в WSL через PhpStorm, необходимо сделать следующее:
- Запускаем командную строку Windows 10 от имени администратора;
- В командной строке Windows 10 выполняем команду
mklink /D C:\project_directory \\wsl$\Ubuntu\home\user\project_directory
, которая создаст символьную ссылку на папку проекта.
После этого в IDE можно открыть проект по пути C:\project_directory
P.S. Дмитрий Симагин, спасибо за решение.
Источники
Более подробное описание каждого шага можно найти тут:
- https://code.visualstudio.com/docs/remote/wsl
- https://docs.docker.com/docker-for-windows/wsl-tech-preview/
- https://docs.docker.com/docker-for-windows/
- https://docs.microsoft.com/ru-ru/windows/wsl/wsl2-install
- https://docs.docker.com/install/linux/docker-ce/ubuntu/
- https://docs.docker.com/install/linux/linux-postinstall/
- https://docs.docker.com/compose/install/
- https://github.com/docker/for-linux/issues/219
Updated April 10, 2022, with current Alpine instructions, Debian/Ubuntu package signing tweaks (no more apt-key), and better guidance for handling iptables in Debian. A little more suggestion about TCP access, as well. And further emphasis on the optional nature of the
/mnt/wsl/shared-docker
socket directory.
Windows Subsystem for Linux 2 sports an actual Linux kernel, supporting real Linux containers and Docker. Docker works on WSL 2, and without requiring the robust but heavy Docker Desktop if that is undesirable. However, due to both WSL and Docker complexities, a little tender loving care is required to get Docker up and running. This article attempts to explore such a process and options along the way.
Contrary to what the length of this article might suggest, getting Docker working on WSL is fairly simple. In a nutshell:
- Instead of using an init system such as systemd to launch the Docker daemon, launch it by calling
dockerd
manually. - If sharing the Docker daemon between WSL instances is desired, configure it to use a socket stored in the shared
/mnt/wsl
directory. - If sharing and privileged access without sudo are desired, configure the
docker
group to have the same group ID across all WSL instances - For simplicity, rather than launch a Windows-based Docker client, launch
docker
inside WSL.
Plenty more nuance and decisions below, of course. See details regarding the companion Github repo by scrolling to the bottom.
Are you sure you don’t want Docker Desktop?
Before proceeding, let’s note that Docker Desktop is amazing. If you want Docker to work on Windows and WSL 2, installing Docker Desktop is most likely the way to go. With Docker Desktop’s WSL 2 backend, Docker integrates with Windows in a fairly elegant way, and the docker client can be launched from either Powershell or Linux. Reading about what goes on under the hood is an entertaining and informative endeavor, as well. Very clever.
If you came here looking how to get Docker running easily, or if you want Windows containers (still a rarity) out of the box, then Docker Desktop is your friend, and you can go install it now.
But if you, like me, feel that all the added complexity of Docker Desktop is unnecessary, you don’t need Windows containers, or you are simply tired of that whale in the system tray taking… so… long… then perhaps you want to run the docker daemon (dockerd
) in the WSL distro of your choice and be happy. You are at the right place.
Note that Docker Desktop is only free individuals or for small companies. If you are using it for work, and your company exceeds a certain size or revenue, then consider paying for a subscription. Of course, if you use Docker without Docker Desktop, as detailed in this article, then this does not apply. See more details about the Docker subscription model here.
Have you tried Podman?
Before we mosey along, though: are you aware of Podman? Podman is daemonless (no background service needed), modern (cgroups v2 out of the box), supports rootless, and serves as a drop-in replacement for Docker. Without needing to worry about sockets and ports, a lot of headaches go away.
I have written about getting Podman to work on WSL 2. Feel free to try it out. You may never look back. And, yes, VSCode can work with podman.
And yet… Sometimes, one just needs Docker to work. Maybe some tooling you use can’t handle Podman, or you just want to put WSL through its paces. If so, read on.
Make sure that WSL is version 2
Please note that these steps require WSL 2 (not version 1). WSL 2 uses an actual Linux kernel that allows Linux containers. WSL 1 was genius with running Linux on the Windows kernel, but of course lacked some of the features, such as containers. Microsoft offers a more detailed comparison in the docs.
You will most certainly need WSL 2 to run the Docker service.
Does the command wsl --set-default-version 2
work? This will set the default version to WSL 2, or fail if you are still on the first version.
Microsoft’s has step-by-step instructions on how to upgrade to WSL 2.
To run WSL 2, Windows version 1903 or higher is needed, with Build 18362 or higher. To tell what version you are running, run winver
in Powershell or CMD, or just type Win key and R (⊞-r) to open the Run dialog and then enter winver
. Hopefully you will see something like «Version 21H2. OS Build 19044.1586»
Install a Linux distro
If you do not yet have a running WSL instance with a distro of your choice, the next step is to pick one from the Microsoft Store. If you dislike the Windows Store, there are other options.
Custom installations are also a great option with WSL 2. For instance, install and configure Fedora, or any other distro for which you can obtain a rootfs in tar format and then wsl --import rootfs.tar
.
This guide includes instructions for launching dockerd in Debian, Ubuntu, Alpine, and Fedora. If you think there is another obvious WSL distro that should be considered, feel free to let me know in the comments.
Configure a non-root user
Once you have installed the distro of your choice, launch it and set up a non-root user if you have not already. Debian and Ubuntu will configure this automatically at first launch, as should Alpine if you installed it from the Store. If the whoami
command returnes «root», then you will want to add a non-root user. For Alpine or Fedora, use adduser myusername
to create a new user. On Alpine, this should prompt for the new password. On Fedora, you will additionally need to passwd myusername
and enter the password you want to use. (If your Fedora does not have passwd
, then you will need to first dnf install passwd cracklib-dicts
).
On later versions of Alpine from the Microsoft Store, while a non-root user is created as part of setup, this user is initially password-less. You can double check on any distro with:
cat /etc/shadow | grep myusername | cut -d: -f2
Enter fullscreen mode
Exit fullscreen mode
(If you are not root, you may need to su
first).
If the result is «!» then that user has no password set. If the result is a random hash string, then you are good. If you need to set a password, you can use passwd myusername
(of course, in all of the above, use your username in place of «myusername.»
Configure admin (sudo) access for the non-root user
If you used Debian or Ubuntu from the Windows store and set up the default user on first launch, then sudo should already be configured on behalf of the default user. You can skip this step, and proceed to updating packages and testing network connectivity, below.
When signed in as the user you set up (try su myusername
if you are still root), can you sudo -v
without an error?
If not, first make sure that sudo is installed. On Alpine, that’s apk add sudo
and on Fedora, dnf install sudo
. If this fails due to network connectivity, see below. You can follow the directions there in order to correct DNS, but of course eliminate any occurrence of sudo
in those commands, as you do not have it yet, and you should still be root anyway.
Is your user a «sudoer»? Try the following to see if they are part of the sudo
or wheel
group:
grep -E 'sudo|wheel' /etc/group
Enter fullscreen mode
Exit fullscreen mode
On distros that have a sudo
group, such as Ubuntu and Debian, you should see something like sudo:x:27:myusername
and on distros that have a wheel
group, such as Fedora and Alpine, you should see something like wheel:27:myusername
.
If your username is missing from the group, take note of the group name (sudo
or wheel
) and add the user in question to that group:
- Alpine:
addgroup myusername wheel
- Fedora:
usermod -aG wheel myusername
- Probably not necessary, but on Ubuntu/Debian:
usermod -aG sudo myusername
Finally, as root, make sure that the admin group (whether sudo
or wheel
) is enabled for sudo:
grep -E '%sudo|%wheel' /etc/sudoers
Enter fullscreen mode
Exit fullscreen mode
If the line is there, but commented out with a #
, then run visudo
then make sure the line reads thus (use wheel
or sudo
as determined earlier):
%wheel ALL=(ALL) ALL
Enter fullscreen mode
Exit fullscreen mode
Then save.
Once these steps are complete, test again with:
su myusername
sudo -v
Enter fullscreen mode
Exit fullscreen mode
If you are prompted for the password, then all is well. If you instead received an error containing something like «Sorry, user myusername may not run sudo» then you may need to follow the steps again, from the beginning.
Set default user
If you obtained your Linux distro from the Store, you can likely skip this step, as the default user is already set up.
If, however, when you launch WSL, you are still root, then set your new user as the default.
Assuming you have Windows build 18980 or later: simply add a user section to /etc/wsl.conf
.
Something like this will work well if you do not already have that file, or a [user]
section in it:
printf "\n[user]\ndefault = myusername\n" | sudo tee -a /etc/wsl.conf
Enter fullscreen mode
Exit fullscreen mode
However, if on a version of Windows before build 18980, then you will instead need to edit the registry to set a default user. Before doing this, we will need two bits of information: the user id, and the name of the WSL distro. Chances are, you already know these. If not, you can obtain the user id with id -u myusername
and check your list of WSL distros with (in Powershell) wsl -l
Then, use the following command in Powershell, but use your WSL distro name in place of «Alpine» and use your user id in place of «1000»:
Get-ItemProperty Registry::HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Lxss\*\ DistributionName | Where-Object -Property DistributionName -eq Alpine | Set-ItemProperty -Name DefaultUid -Value 1000
Enter fullscreen mode
Exit fullscreen mode
Whichever method you use, test by logging out of WSL, and then log back in. Confirm that whoami
yields the correct username. Success.
Update/upgrade packages and test network connectivity
Let’s make everything new and shiny with one of the following:
- Debian/Ubuntu:
sudo apt update && sudo apt upgrade
- Fedora:
sudo dnf upgrade
- Alpine:
sudo apk upgrade -U
Network issues?
Upgrading the packages also serves as a network test. For a variety of reasons, network connectivity issues can happen with WSL 2, and tweaking the DNS settings often resolves these problems in my experience. If the upgrade command succeeded, you can skip this section. But if the above commands fail to access the package servers, it may be something unique to your network, or your firewall or anti-malware software. I recommend the following:
echo -e "[network]\ngenerateResolvConf = false" | sudo tee -a /etc/wsl.conf
sudo unlink /etc/resolv.conf
echo nameserver 1.1.1.1 | sudo tee /etc/resolv.conf
Enter fullscreen mode
Exit fullscreen mode
The first line tells WSL to cease auto-configuring the /etc/resolv.conf
file. Then we remove/unlink the old file, and create a new one.
With this newly-configured DNS resolver (in this case, pointing directly to Cloudflare’s DNS server) you can try upgrading packages again. Success? Excellent.
Prepare for Docker installation
Thankfully, there are official guides for installing Docker on various Linux distributions. I have based these instructions on those, with some tweaks learned from real world testing.
Remove residue
If this is not a fresh install, and you may have experimented with docker before, then first clear out any residual docker installs:
- Fedora:
sudo dnf remove moby-engine docker docker-client docker-client-latest docker-common docker-latest docker-latest-logrotate docker-logrotate docker-selinux docker-engine-selinux docker-engine
- Debian/Ubuntu:
sudo apt remove docker docker-engine docker.io containerd runc
- Alpine (probably not necessary, but just in case):
sudo apk del docker-cli docker-ce docker-openrc docker-compose docker
Install dependencies
Then, install pre-requisites:
- Debian/Ubuntu:
sudo apt install --no-install-recommends apt-transport-https ca-certificates curl gnupg2
- Fedora:
sudo dnf install dnf-plugins-core
- Alpine: Nothing needed. Dependencies will be installed later, automatically.
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
Enter fullscreen mode
Exit fullscreen mode
And select iptables-legacy.
If you are comfortable, instead, with nftables and want to configure nftables manually for Docker, then go for it. I suspect that most, however, will want to switch to iptables legacy.
Debian/Ubuntu package repository configuration
On Debian or Ubuntu, first temporarily set some OS-specific variables:
. /etc/os-release
Enter fullscreen mode
Exit fullscreen mode
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
Enter fullscreen mode
Exit fullscreen mode
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
Enter fullscreen mode
Exit fullscreen mode
Fedora package repository configuration
On Fedora, first add Docker’s repo:
sudo dnf config-manager --add-repo https://download.docker.com/linux/fedora/docker-ce.repo
Enter fullscreen mode
Exit fullscreen mode
Install Docker
Now we can install the official Docker Engine and client tools:
- Debian/Ubuntu:
sudo apt install docker-ce docker-ce-cli containerd.io
- Fedora:
sudo dnf install docker-ce docker-ce-cli containerd.io
- Alpine (install the latest from edge):
sudo apk add docker --repository=http://dl-cdn.alpinelinux.org/alpine/edge/community
Add user to docker
group
The Docker daemon is a service that Docker requires to be running in the background. The service (dockerd
) and client (docker
) communicate over a socket and/or a network port. For communication over the socket, privileged access is required. Two ways to obtain this access:
- Run
docker
as root (i.e.sudo docker
) - Through group membership, grant specific users privileged access to the Docker socket
In other words, unless you want to utilize sudo
or root access every time, add your user to the Docker group, named docker
:
- Fedora/Ubuntu/Debian:
sudo usermod -aG docker $USER
- Alpine:
sudo addgroup $USER docker
Then close that WSL window, and launch WSL again. You should see docker
when you run the command groups
to list group memberships.
Sharing dockerd: choose a common ID for the docker
group
If you only plan on using one WSL distro, this next step isn’t strictly necessary. However, if you would like to have the option of sharing the Docker socket system-wide, across WSL distributions, then all will need to share a common group ID for the group docker
. By default, they each may have a different ID, so a new one is in order.
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
Enter fullscreen mode
Exit fullscreen mode
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"
Enter fullscreen mode
Exit fullscreen mode
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
Enter fullscreen mode
Exit fullscreen mode
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
Enter fullscreen mode
Exit fullscreen mode
Once the group id has been changed, close the terminal window and re-launch your WSL distro.
Note that the above steps involving the docker
group will need to be run on any WSL distribution you currently have or install in the future, if you want to give it access to the shared Docker socket.
(Optionally) prepare a shared directory
As with the last step, if you only plan on using one WSL distro, this next step isn’t strictly necessary. However, if you would like to have the option of sharing the Docker socket system-wide, across WSL distributions, then a shared directory accessible to all is needed.
Let’s first make a shared directory for the docker socket, and set permissions so that the docker group can write to it.
DOCKER_DIR=/mnt/wsl/shared-docker
mkdir -pm o=,ug=rwx "$DOCKER_DIR"
chgrp docker "$DOCKER_DIR"
Enter fullscreen mode
Exit fullscreen mode
Configure dockerd
to use the shared directory
Again, this step can be skipped if you opt against using a shared directory for the docker socket. However, you may have other settings you wish to put in daemon.json
, so you may appreciate some familiarity with this topic.
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:
{
"hosts": ["unix:///mnt/wsl/shared-docker/docker.sock"]
}
Enter fullscreen mode
Exit fullscreen mode
Launch dockerd
Most Linux distributions use systemd or other init system, but WSL has its own init system. Rather than twist things to use the existing init system, we just launch dockerd
directly:
sudo dockerd
Enter fullscreen mode
Exit fullscreen mode
There should be several lines of info, warnings related to cgroup blkio
, and the like, with something like API listen on /mnt/wsl/shared-docker/docker.sock
at the end. If so, you have success.
Open another wsl terminal.
If and only if you opted to use the shared docker socket in /mnt/wsl/shared-docker
as detailed above, first set the DOCKER_HOST
environment variable:
export DOCKER_HOST="unix:///mnt/wsl/shared-docker/docker.sock"
Enter fullscreen mode
Exit fullscreen mode
Then, try out the docker cli:
docker run --rm hello-world
Enter fullscreen mode
Exit fullscreen mode
You should see the «Hello from Docker!» message.
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
Enter fullscreen mode
Exit fullscreen mode
If you went with the default docker socket location of /var/run/docker.sock
instead of the shared socket directory of /mnt/wsl/shared-docker
as detailed above, then the script can be something like this:
DOCKER_DISTRO="Debian"
DOCKER_LOG_DIR=$HOME/docker_logs
mkdir -pm o=,ug=rwx "$DOCKER_LOG_DIR"
/mnt/c/Windows/System32/wsl.exe -d $DOCKER_DISTRO sh -c "nohup sudo -b dockerd < /dev/null > $DOCKER_LOG_DIR/dockerd.log 2>&1"
Enter fullscreen mode
Exit fullscreen mode
You may choose whatever location you would like for your docker logs, of course. It just needs to be in a place that has permissions so that your user can write to it.
Note that DOCKER_DISTRO
should be set to the distro you want to have running dockerd
. If unsure of the name, simply run wsl -l -q
from Powershell to see your list of WSL distributions. Pick the right one and set it to DOCKER_DISTRO
.
The script above does the following:
- Sets the environment variable
$DOCKER_HOST
to point to the shared socket. This isn’t necessary fordockerd
but it will allow runningdocker
without needing to specify-H unix:///mnt/wsl/shared-docker/docker.sock
each time. - Checks if the
docker.sock
file already exists and is a socket. If it is present, do nothing. If not present then the script does the remaining steps, as follows. - Creates the shared docker directory for the socket and
dockerd
logs, setting permissions appropriately - Runs
dockerd
from the specified distro. This is important, because it allows any WSL distro to launchdockerd
if it isn’t already running. - When
dockerd
is launched, pipe its output and errors to a shared log file. - When
dockerd
is launched, it runs in the background so you don’t have to devote a terminal window to the process as we did earlier. Thesudo -b
flag gives us this, and we run withnohup
so that it runs independent of the terminal, with an explicit null input tonohup
to avoid extra warnings. Both standard output and errors are written to the logfile, hence the2>&1
redirect.
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
Enter fullscreen mode
Exit fullscreen mode
Save and exit («:wq
» if the editor is vi
, or Ctrl-x if it is nano
), and then you can test if sudo dockerd
prompts for a password or not. For peace of mind, you can double-check: something like sudo -k ls -a /root
should still require a password, unless the password has been entered recently.
Make sure $DOCKER_HOST
is always set
If using the script earlier to launch dockerd
, then $DOCKER_HOST
will be set, and future invocations of docker
will not need an unwieldy -H unix:///mnt/wsl/shared-docker/docker.sock
If that script is already in your .bashrc
or .profile
, then the following is unnecessary. If, however, you manually invoke dockerd
in some way, then the following may be desirable in your .bashrc
or .profile
, if you opted for the shared docker socket directory:
DOCKER_SOCK="/mnt/wsl/shared-docker/docker.sock"
test -S "$DOCKER_SOCK" && export DOCKER_HOST="unix://$DOCKER_SOCK"
Enter fullscreen mode
Exit fullscreen mode
The above checks for the docker socket in /mnt/wsl/shared-docker/docker.sock
and, if present, sets the $DOCKER_HOST
environment variable accordingly. If you want a more generalized «if this is wsl, then set the socket pro-actively» then you may prefer the following, which simply check for the existence of a /mnt/wsl
directory and sets the docker socket if so:
[ -d /mnt/wsl ] && export DOCKER_HOST="unix:///mnt/wsl/shared-docker/docker.sock"
Enter fullscreen mode
Exit fullscreen mode
Running docker
from Windows
If configured as above, I recommend always running docker from wsl. Do you want to run a container? Do so from a WSL window. (See my article on using Windows Terminal for a convenient way to use WSL and Powershell.)
This doesn’t just apply to the terminal, either. For instance, VSCode supports docker in WSL 2.
But if you want the convenience and utility of running docker in a Powershell window, I have a couple suggestions.
One is to expose dockerd
over a TCP Port, or, better yet, set up an SSH server in WSL and connect that way. docker context
will likely be your friend. Such methods will be explored in a later article, but I encourage you, reader, to explore. A hint: ever tried scoop.sh? After setting it up, scoop install docker docker-compose
will get you some familiar tools, then an SSH server such as Dropbear or OpenSSH on the WSL side…
A simplified method I recommend: a Powershell function that calls the WSL docker
, passing along any arguments. This function can be placed in your Powershell profile, usually located at ~\Documents\WindowsPowerShell\Microsoft.PowerShell_profile.ps1
$DOCKER_DISTRO = "fedora"
function docker {
wsl -d $DOCKER_DISTRO docker -H unix:///mnt/wsl/shared-docker/docker.sock @Args
}
Enter fullscreen mode
Exit fullscreen mode
Again, try wsl -l -q
to see a list of your WSL distributions if you are unsure which one to use.
Make sure the Docker daemon is running, then launch a new Powershell window, and try the hello-world
container again. Success?
You could also make a batch file with the appropriate command in it. For instance, name it docker.bat
and place in C:\Windows\system32
or other location included in %PATH%
. The following contents will work in such a script:
@echo off
set DOCKER_DISTRO=fedora
wsl -d %DOCKER_DISTRO% docker -H unix:///mnt/wsl/shared-docker/docker.sock %*
Enter fullscreen mode
Exit fullscreen mode
You could go a step further and ensure that dockerd
is running whenever you start Powershell. Assuming that the dockerd
start script detailed above is saved in a file in WSL as $HOME/bin/docker-service
and is executable (try chmod a+x $HOME/bin/docker-service
), then the following line in your Powershell profile will launch dockerd
automatically:
wsl -d $distro ~/bin/docker-service
Enter fullscreen mode
Exit fullscreen mode
Not sure where your Powershell profile is located? Try entering $profile
in a powershell window.
If you don’t want to rely on a particular WSL shell script, you could implement a Powershell function to launch dockerd, such as this:
function Docker-Service {
Param ([string]$distro)
$DOCKER_DIR = "/mnt/wsl/shared-docker"
$DOCKER_SOCK = "$DOCKER_DIR/docker.sock"
wsl -d "$distro" sh -c "[ -S '$DOCKER_SOCK' ]"
if ($LASTEXITCODE) {
wsl -d "$distro" sh -c "mkdir -pm o=,ug=rwx $DOCKER_DIR ; chgrp docker $DOCKER_DIR"
wsl -d "$distro" sh -c "nohup sudo -b dockerd < /dev/null > $DOCKER_DIR/dockerd.log 2>&1"
}
}
Enter fullscreen mode
Exit fullscreen mode
This function takes one parameter: the distro name.
In all of the above, the principle is the same: you are launching Linux executables, using WSL interoperability.
A note on bind mounts: stay on the Linux filesystem
With docker, it is possible to mount a host system’s directory or files in the container. The following often works, but is not advisable when launching WSL docker from Windows:
echo "<h1>Hello, World</h1>" > index.html
docker run -p "8080:80" -v "$PWD:/usr/share/nginx/html:ro" nginx
Enter fullscreen mode
Exit fullscreen mode
Instead of doing the above haphazardly, when launching WSL docker from Powershell, two recommendations:
- For performance reasons, only bind mount from within the Linux filesystem. To get to a Linux directory while in Powershell, try something like
cd (wsl wslpath -m ~/path/to/my/dir)
- Instead of
$PWD
to get the current directory, try'$(wslpath -a .)'
and, yeah, the single quotes are helpful for escaping.
An example:
cd (wsl wslpath -m ~)
mkdir html
cd html
echo "<h1>Hello, World</h1>" > index.html
docker run -p "8080:80" -v '$(wslpath -a .):/usr/share/nginx/html:ro' nginx
Enter fullscreen mode
Exit fullscreen mode
Then point your browser to http://localhost:8080, and happiness will result. (Depending on your network configuration, you may instead need to access this through http://[WSL IP Address]:8080 which should be obtainable with ifconfig
or ip addr
)
Try wsl wslpath
from Powershell, or just wslpath
from Linux, to see the options. This is a very useful tool, to say the least.
Example scripts
After walking through the steps in this article, you should now have a working and potentially auto-launched dockerd
, shared Docker socket, and conveniently configured docker
command.
Some of the code examples above have been placed in scripts in a companion Github repo. I summarize the files available here:
-
docker-service.sh is a Unix shell script to launch
dockerd
-
docker-service.ps1 contains a Powershell function to launch
dockerd
in WSL -
docker.bat is a Windows batch file for launching WSL
docker
from CMD -
docker.ps1 contains a Powershell function for launching WSL
docker
from Powershell, if placed in your profile
No doubt there are ways these can be tweaked to be more useful and reliable; feel free to post in the comments.
Interested in further tinkering with WSL 2?
Other articles I have written on WSL:
- Using podman instead of Docker
- You Probably Don’t Need systemd on WSL
- Install Fedora on WSL
- How to Upgrade from Fedora 32 to Fedora 33
As a developer who switched from Linux to Windows because of many reasons, I have used Docker Desktop for several months now because it updates my Docker environment automatically.
Unfortunately, this is not possible anymore and I have to remove Docker Desktop.
Luckily I did not use Docker Desktop for any commands or functionality except for updating the Docker engine so this change will not affect my workflow.
Why Should You Install Docker Without Docker Desktop?
Docker updated its Docker Desktop License Agreement and permit the professional use of Docker Desktop in large organizations without having a paid Docker subscription. This means that if your company has 250+ employees or more than $10 million in annual revenue you will not able to use Docker Desktop without a paid subscription. It remains free for smaller companies, private use, open-source projects, and educational purposes.
This license update is only related to Docker Desktop and not to Docker or the Docker Engine. This enables you to still use Docker for development and all types of environments, including the production ones. Normally, this license update does not impact your company’s business if working with Docker.
Prerequisites
To follow this How-To you need to have a WSL2 compatible workstation like Windows 10 version 2004 or higher. To check which version is installed press Windows logo key + R
and press Enter to show your system settings. If you do not meet the requirement please update your Windows.
If Docker Desktop is installed you have to uninstall it
In Windows, the Linux Subsystem has to be enabled. This can be done by pressing the Windows log key, typing “Turn Windows features on and off” and open it.
Scroll to the bottom and activate the feature if it is deactivated.
After activating press OK and restart your computer.
You can also install the Linux Subsystem with a PowerShell command:
Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Windows-Subsystem-Linux
Install Ubuntu on WSL2
After you set up the prerequisite you have to open a PowerShell with administrative privileges and install Ubuntu in WSL2 with the following command:
wsl --set-default-version 2
wsl --install -d Ubuntu
You can also install different Linux submodules within this step.
After the installation is finished you should check if Ubuntu was installed in the correct version:
wsl -l -v
If everything worked correctly you should see your installed Ubuntu with the corresponding WSL version. If the version is not correct you can change it with:
wsl --set-version Ubuntu-YY.MM 2
YY.MM is the version of the Ubuntu version that you installed recently.
Install Docker
To install Docker on Windows within the Ubuntu submodule you can follow the official steps for installing Docker on Ubuntu:
- https://docs.docker.com/engine/install/ubuntu/
Another way will be to create a new file and copy the following script into it. These commands are only copied from the official tutorial into a file to share with fellow developers
#/bin/bash
# 1. Required dependencies
sudo apt-get update
sudo apt-get -y install apt-transport-https ca-certificates curl gnupg lsb-release
# 2. GPG key
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
# 3. Use stable repository for Docker
echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu \
$(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
# 4. Install Docker
sudo apt-get update
sudo apt-get -y install docker-ce docker-ce-cli containerd.io
# 5. Add user to docker group
sudo groupadd docker
sudo usermod -aG docker $USER
Switch to your Ubuntu submodule within PowerShell and execute the file to install Docker and the needed dependencies.
You can now start and check if everything runs correctly with:
sudo service docker start # start the engine
sudo service docker status # print some nice status information
docker run hello-world # run a test docker container
After the last command finish, you should see the running Docker image output:
Hello from Docker! This message shows that your installation appears to be working correctly.
To generate this message, Docker took the following steps:
The Docker client contacted the Docker daemon.
The Docker daemon pulled the "hello-world" image from the Docker Hub. (amd64)
The Docker daemon created a new container from that image which runs the executable that produces the output you are currently reading.
The Docker daemon streamed that output to the Docker client, which sent it to your terminal.
To try something more ambitious, you can run an Ubuntu container with: $ docker run -it ubuntu bash
Share images, automate workflows, and more with a free Docker ID: https://hub.docker.com/
For more examples and ideas, visit: https://docs.docker.com/get-started/
Common Problems with Ubuntu WSL2 Distro
If you install Ubuntu as your WSL2 Distro and use at least one that is based on Ubuntu Hirsute Hippo (21.04) it could happen that your docker daemon will not start correctly.
When trying to run dockerd
it will produce the following error log:
...
INFO[2021-09-25T15:06:20.839195000+08:00] Loading containers: start.
INFO[2021-09-25T15:06:20.885624800+08:00] stopping event stream following graceful shutdown error="<nil>" module=libcontainerd namespace=moby
INFO[2021-09-25T15:06:20.885865900+08:00] stopping healthcheck following graceful shutdown module=libcontainerd
INFO[2021-09-25T15:06:20.886012400+08:00] stopping event stream following graceful shutdown error="context canceled" module=libcontainerd namespace=plugins.moby
failed to start daemon: Error initializing network controller: error obtaining controller instance: unable to add return rule in DOCKER-ISOLATION-STAGE-1 chain: (iptables failed: iptables --wait -A DOCKER-ISOLATION-STAGE-1 -j RETURN: iptables v1.8.7 (nf_tables): RULE_APPEND failed (No such file or directory): rule in chain DOCKER-ISOLATION-STAGE-1
(exit status 4))
I noticed that iptables
being used by docker is a nftables
version. This led to an error because starting from version 20.10 Ubuntu switched the firewall system to nftables
(you can read about it on this website). Unfortunately, using nftables
natively requires Linux Kernel 5.8 but the latest Kernel version for the WSL is 5.4.
Luckily, Ubuntu still has the possibility to use a legacy version of iptables
by simply executing:
$ sudo update-alternatives --config iptables
There are 2 choices for the alternative iptables (providing /usr/sbin/iptables).
Selection Path Priority Status
------------------------------------------------------------
* 0 /usr/sbin/iptables-nft 20 auto mode
1 /usr/sbin/iptables-legacy 10 manual mode
2 /usr/sbin/iptables-nft 20 manual mode
Press <enter> to keep the current choice[*], or type selection number: 1
update-alternatives: using /usr/sbin/iptables-legacy to provide /usr/sbin/iptables (iptables) in manual mode
After updating the iptables
just restart the Docker daemon and you will notice that Docker starts working correctly.
Install Docker Compose
Installing Docker Compose can be done within the Ubuntu submodule. Open a PowerShell window and switch to the Ubuntu submodule. Then download the latest release from GitHub:
sudo curl -L https://github.com/docker/compose/releases/download/2.4.1/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose
Next, grant privileges for execution to the docker-compose command:
sudo chmod +x /usr/local/bin/docker-compose
Afterward, you can test the functionality by executing docker-compose -version
within the Ubuntu submodule or wsl docker-compose -version
from any PowerShell window.
How To Integrate Docker And Docker Compose Into Your PowerShell
If you follow the tutorial you should have:
- WSL2 Linux subsystem installed
- Installed & configured Docker on Ubuntu
- Installed Docker Compose
You are able to use all Docker commands inside your Ubuntu submodule and also within a PowerShell by preceding the command with wsl
:
wsl docker ps
wsl docker-compose -version
For convenience, you should be able to use any Docker command without adding wsl
in front of it. To achieve this you can create an alias for your PowerShell. Read about it here and set up everything.
Then find your PowerShell profile
echo $PROFILE
and open this file in an editor and paste this content:
Function Start-WslDocker {
wsl docker $args
}
Function Start-WslDockerCompose {
wsl docker-compose $args
}
Set-Alias -Name docker -Value Start-WslDocker
Set-Alias -Name docker-compose -Value Start-WslDockerCompose
Save the file and restart your PowerShell terminal to test if the alias is working by typing:
docker ps
docker-compose -version
If you don’t get an error it works as expected.
Installing Portainer
To better replace Docker Desktop and have something like a Docker GUI you should install Portainer in your local environment.
Portainer is a powerful, GUI-based Container-as-a-Service solution that helps organizations manage and deploy cloud-native applications easily and securely.
With Portainer you can:
- Deploy applications with defined app templates (Click to Deploy)
- Deploy and Manage Stacks from Compose files, including deploying directly from the git
- Deploy & Manage Containers, including the ability to edit a running container
- Pull/Push/Build Images
- Create Networks
- Create/Delete Volumes
- See a log of Docker Events
- See docker engine (Host) information, and apply security controls should you desire
This Docker Compose file can be used to install Portainer CE as a Docker service that automatically is restarted if it is not running.
version: '3'
services:
portainer:
image: portainer/portainer-ce:latest
container_name: portainer
restart: unless-stopped
security_opt:
- no-new-privileges:true
volumes:
- /etc/localtime:/etc/localtime:ro
- /var/run/docker.sock:/var/run/docker.sock:ro
- ./portainer-data:/data
ports:
- 9000:9000
Save it to any folder and run it in your PowerShell:
docker-compose up -d
Switch to your browser and open http://localhost:9000.
Timing Note: Make sure you log in and create your credentials soon after Portainer is ready, or it will automatically shut down itself for security. If you didn’t create the credentials on time and it shut down automatically, you have to restart the service.
Pros/Cons Of This Solution
Pros
There are multiple advantages compared to the Docker Desktop version:
- The Docker engine is free. So the license update won’t be a problem for your development and production environment.
- Portainer is a production-ready software to manage your Docker environment that also often is used in a server cluster environment.
- You will learn Docker basics much faster and will gain more DevOps competencies.
- Often production environments run in Linux so your development environment comes close to the production environment.
Cons
The only disadvantage for me is that you have to update it manually by yourself instead of pressing an “OK” button if a new version is available.
Closing Notes
Thanks for reading this article!
I hope you enjoyed reading it and are now able to install the Docker environment on your Windows Host within the Ubuntu submodule. Also, I hope that you can now use and install Portainer and Docker Compose on Windows. If it is working for you I would love to get your feedback in the comment section. Also, if you have any questions, please jot them down below. I will answer them if possible.
To make working with the Docker CLI easier I created a cheatsheet with many helpful commands:
Feel free to connect with me on Medium, LinkedIn, Twitter, and GitHub.
Install Docker on Windows 11 with WSL Ubuntu 22.04
This is to install Docker within Ubuntu WSL without using the Windows Docker application.
Follow the below steps.
1. Enable Windows Subsystem for Linux and Virtual Machine platform
Go to Control Panel -> Programs -> Programs and Features -> Turn Windows features on or off
2. Switch to WSL 2
Open Powershell and type in the below command.
wsl —set-default-version 2
3. Install Ubuntu
Open Microsoft Store and search for Ubuntu. Select the version you intend to install. I’d use the latest LTS version Ubuntu 22.04. Click on the Get button.
It will take a couple of minutes to download and install.
4. Open up the installed Ubuntu version that was installed.
If you get an error like the below image, make sure to install the WSL2 Kernel update.
If it’s an older Ubuntu version the error message would be something like the image below.
Error: WSL 2 requires an update to its kernel component.
Installing the WSL2 kernel update should fix this issue. Then close the Ubuntu window and open it up again.
It will ask for the Language, username, and password like below.
In the mount settings, you can leave the defaults.
It will take a minute or two to apply the changes.
Hit enter to reboot Ubuntu WSL.
Now, we have installed the WSL 2.
Install Docker within Ubuntu WSL
5. Run the apt update command to get the updated and install some required packages.
sudo apt-get update
sudo apt-get install \
ca-certificates \
curl \
gnupg \
lsb-release
6. Add CPG keys for the official docker repository.
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg —dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
7. Add Docker repository to APT.
echo \
«deb [arch=$(dpkg —print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu \
$(lsb_release -cs) stable» | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
8. Install Docker
sudo apt-get update
sudo apt-get install docker-ce docker-ce-cli containerd.io docker-compose-plugin
9. Start the docker service
sudo service docker start
10. Check the docker service status
sudo service docker status
If it is Ubuntu 22.04, then it might have an issue with the iptables version. When you are checking the status, it might still show up not running. If that is the case, make sure to switch the iptables to legacy.
Run the below command to change the default iptables version.
sudo update-alternatives —config iptables
Select the iptables-legacy by entering option 1. Then hit enter.
Then start the docker service again by repeating step 9 above.
11. Add the user to the docker user group.
sudo usermod -aG docker ${USER}
su — ${USER}
12. Now, that everything is complete, feel free to use docker!
docker ps
Issues and troubleshooting
If you still can’t run the docker service, check the WSL version in Powershell.
wsl -l -v
If you have version 1, WSL 1 did not support running Docker within the Ubuntu subsystem on its own. The WSL 1 required to use Windows Desktop Docker app to be installed and use windows binaries to run Docker within WSL. This is great if you need to keep the 2 docker services in sync.
If you want to run Docker within WSL without having the windows Docker client, you have to update it to WSL2.
I would uninstall the current Ubuntu installation from Settings -> Apps -> Ubuntu.
Then switch the WSL version as per step 2 above, then install the Ubuntu again.