As you know containers are a Linux thing. Microsoft introduced its solution but I’ve never seen them used.
To use containers we have mainly two alternatives: docker and podman. I prefer the latter for two reasons. Because it has a daemonless architecture and because it doesn’t need root permission. But using it with docker-compose on Windows is tough. That’s why I decided to write and share this story.
Motivation
I think using Docker Desktop on Windows is the fastest way to use containers. It configures everything by itself. But, excluding the architectural preference, I found two other motivations to avoid it:
- License issue. Docker Desktop requires a per-user license for commercial use in large companies.
- You don’t need it. For example, I’ve never used its GUI. Probably because I’m so accustomed to using it on Linux from cli.
Prerequisites
Using podman on Windows is feasible thanks WSL2. Microsoft provides instructions according your Windows version. You can find them here: https://docs.microsoft.com/en-us/windows/wsl/install.
Podman supports docker-compose from version 3.0.0.
TL;DR
The below paragraphs are about the issues I found on Debian and Ubuntu. So, why we need OpenSUSE Tumbleweed as Linux distribution. For this reason, I summarised in the Conclusion paragraph only the needed steps.
Linux distributions
On the Microsoft Store there are multiple Linux distributions. And that’s where started my journey.
Info: Common solutions about distributions are in the Troubleshooting section
Debian
The current stable distribution of Debian is version 11. It’s codenamed bullseye and it’s the first one I tried to use.
The first thing to check is if podman is in the official repository. Fortunately it is and it’s currently at the version 3.0.1. So, it should work with docker-compose.
So, I updated the system and I installed podman and docker-compose:
$ sudo apt update
$ sudo apt upgrade
$ sudo apt install podman docker-compose
Then I configured podman to avoid using systemd. On WSL2 we cannot rely on it because the init system is a custom Microsoft solution.
To do this I copied /usr/share/containers/containers.conf
to $HOME/.config/containers
. Then I changed the latter.
Specifically, I set cgroup_manager
to cgroupfs
and events_logger
to file
:
...
[engine]
...
cgroup_manager = "cgroupfs"
...
events_logger = "file"
...
I found this tips on https://www.redhat.com/sysadmin/podman-windows-wsl2.
Then I tried to run a simple container:
$ docker run -dp 8080:80 docker.io/httpd
But I got: Error: Error initialising source docker … x509: certificate signed by unkown authority
. To resolve this
issue I installed ca-certificates
. Then I tried to run the container again:
$ sudo apt install ca-certificates
$ docker-run -dp 8080:80 docker.io/httpd
This time it worked! And the host can reach the container.
So, I tried a simple docker-compose to test the communication between two containers:
version: "3.7"
services:
db:
image: docker.io/mariadb
restart: always
environment:
MYSQL_ROOT_PASSWORD: password
phpmyadmin:
image: docker.io/phpmyadmin
restart: always
ports:
- 8080:80
environment:
- PMA_ARBITRARY=1
But I got this error:
$ docker-compose up
ERROR: Couldn't connect to Docker daemon at http+docker://localhost - is it running?
If it's at a non-standard location, specify the URL with the DOCKER_HOST environment variable.
Obviously it’s not running. So, I checked the podman documentation and we need to start the podman socket manually. We should do it manually because we cannot rely on a systemd service. Then we should indicated the socket location to docker-compose.
$ podman system service --time=0 unix:///home/user/podman.sock &
[1] <a number>
$ docker-compose -H unix:///home/user/podman.sock up
Pulling images...
Creating images...
ERROR: for <service name> network connect is not enabled for rootless containers
ERROR: for <service name> network connect is not enabled for rootless containers
I searched the error and I found a GitHub issue about podman. It seems this is a bug fixed in the version 3.2. So, I searched other supported Linux distributions in the hope to find a newer podman version.
Ubuntu
Currently there are three Ubuntu versions:
- 18.04.5 LTS
- 20.04.4 LTS
- 22.04 LTS
But, as Debian, they doesn’t support latest Podman version. For this reason, I didn’t try them at all. And at this moment I was a bit unmotivated. I would have appreciated a rolling distribution. And that’s when I see OpenSUSE Tumbleweed in the Microsoft Store…
OpenSUSE Tumbleweed
OpenSUSE Tumbleweed is a rolling distribution. This means it supports the latest versions of packages. Indeed, the current podman version is the 4.0.3. Another good news is that I used Tumbleweed for some years, and it was great!
So, I updated the system and installed podman and docker-compose:
$ sudo zypper update
$ sudo zypper install podman docker-compose
At this point I configured podman to not use systemd, as Debian.
I tried to run a simple container exposing a port. And it worked.
So, I started the podman socket. Then I launched docker-compose with the same file. And the two containers started!
But, when I tried to connect to the database from phpmyadmin I received the following error:
getaddrinfo failed: Name or service not known
I investigated a bit and I found that containers were unable to communicate through DNS name.
For this reason I researched about networking in Podman 4.x and I found that they changed the network stack. But it should also supports DNS resolution.
Yet, podman continues to support the old network stack (i.e. cni
) for compatibility reason. So, I checked what’s the
enabled stack and it was the old one. So, I research about it and DNS resolution and I found
an official article. The old stack supports
plugins and one of them regards DNS name resolution: dnsname
.
So, I searched it on the Tumbleweed repository and it was there. So, I installed it:
$ sudo zypper install cni-plugin-dnsname
And this time the containers communicated correctly.
Furthermore, I forced the old stack in podman adding to $HOME/.config/containers/containers.conf
:
...
[network]
network_backedn = "cni"
...
Troubleshooting
Unable to resolve DNS in WSL2
On each distribution I was unable to resolve domain names. For example, I got errors like:
Temporary failure resolving ‘<a domain name>’
W: Failed to fetch <a URL>
Error message: Could not resolve host: <a host name>'
So, I read the /etc/resolv.conf
file and there was a bad DNS server. Fortunately Microsoft added a hint:
# This file was automatically generated by WSL. To stop automatic generation of this file, add the following entry to /etc/wsl.conf:
# [network]
# generateResolvConf = false
nameserver <BAD_NAMESERVER>
So, I wrote the /etc/wsl.conf
file:
[network]
generateResolvConf = false
Then, I removed the /etc/resolv.conf
file (it was a link) and I created the correct one:
nameserver <GOOD_NAMESERVER_IP>
Conclusion
As you can see running podman with docker-compose on Window was a journey. We covered a lot of steps. So, to simplify and have them better organised I wrote again here:
- Install WSL2
- Install OpenSUSE Tumbleweed as Linux distribution
- Correct /etc/resolv.conf, if unable to resolve DNS name in the distribution
- Update the distribution
- Install podman, docker-compose and cni-plugin-dnsname
- Configure podman to not use systemd
- Configure podman to use the cni as network backend
- Launch podman socket
- Profit
At this point, you can customize your experience to simplify your workflow. For example command aliases or adding commands at boot.