Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

Docker decided to charge a per user fee for companies and universities using their Docker Desktop for Windows package. If you are actually developing “Windows Containers”, this is the only way they can be built. If you want to develop Linux Containers using a Windows development platform, there are other fairly simple solutions that are completely free. When this paper was first written, the alternatives were in early stages of development, worked poorly, and required a lot of effort to install and use. Today all those problems have been solved, and there are several options that require almost no effort.

WSL Ubuntu 24.04 Distro

Docker has two components. The user interface is the “docker” command (a.k.a. docker-cli) that the user runs at the command line in a shell. All the work of building images and running tests is done in the background “docker engine” (a.k.a. “dockerd” or “containerd”) that runs as a background service under “systemd”.

The Windows Subsystem for Linux is the Linux-aspect of Windows. It allows a Windows user to run any Linux command from the Windows command line (cmd.exe or PowerShell) just by prefixing it with “wsl “. This runs the wsl.exe program in Windows, which then sends the rest of the command line to the default WSL Linux distribution by a process similar to SSH. Because Windows and WSL share all the Windows disks and files that the user is allowed to access, the current directory and environment variables in Windows are transmitted to Linux and become the default directory in which the Linux command runs.

Originally, WSL simply did not support “systemd” and therefore could not run the Docker Engine service that did all the work. It was possible to create a custom WSL system image that could run background services, and Docker Subsystem for Linux created such an image and depended on it for its operation. Slowly Microsoft added WSL support for “systemd” as a rather technical option you could turn on after Ubuntu-23.04, but even then, Ubuntu would tell anyone trying to install docker that they should get the Docker Subsystem for Windows instead. Starting with the WSL “Ubuntu-24.04” distro installed either using Windows Store or at the command line, “systemd” is turned on by default for everyone, and if you then issue the “sudo install docker.io” command, then the full normal Linux docker-cli and docker engine are installed.

If you configure Ubuntu-24.04 with docker.io installed as the default WSL distro, then in Windows cmd.exe, bat files, or PowerShell you can issue any docker command from Windows by running “wsl docker …” (or if you prefer, “wsl.exe docker …”). While the command is entered from Windows and the current directory is the Windows directory, docker runs in the WSL Ubuntu environment as a Linux command, and the images are stored in the docker engine image library.

The only remaining problem to overcome is understanding the state of networking if you execute an image with “docker run -p 8080:8080”. With Docker Desktop for Windows you run a docker.exe in Windows and there is a lot of effort put into connecting port 8080 in the container running in Linux to a proxy listening on port 8080 in Windows through a lot of special VPN logic written by Docker to make it all work. If you execute “wsl docker run -p:8080:8080” then the docker command runs in WSL Linux. The container port 8080 is then connected by the docker VPN to port 8080 on the WSL Linux distro. Now something lucky happens. Among the network addresses on the WSL Linux system is the “localhost” or loopback address of 127.0.0.1. WSL has a rule that when any program listens on a port on the localhost address, then Windows WSL causes a matching listen to be done on the Windows system localhost address. This means that any program running on the Windows host computer system can connect to localhost:8080 and that will in turn be passed to the program in the container. What would have worked on Docker Desktop for Windows, but won’t work transparently with WSL, is for a program on a different computer, or even on a VM running under Windows Hyper-V to connect to the container. I am not saying it cannot be done at all, but it requires a lot of extra work. So, running Docker under normal WSL without Docker Desktop is fine if all your test applications either run on Windows or in WSL itself.

You can create a PowerShell alias, or you can create a docker.bat file with contents

Code Block
@ECHO OFF
wsl docker %*

If you need it, you can add docker-compose the same way with “wsl sudo apt install docker-compose” and create another bat file for that command.

Alternately, you may decide to work in the WSL Ubuntu system using Visual Studio Code Remote for WSL. The editor runs in Windows, but docker runs in WSL. You can even install the Docker plugin in the Remote VS Code and it connects to the WSL docker.io that you installed above.

Podman Desktop for Windows

Podman is the Red Hat alternative to the standard Docker system. It is a redesign and reimagining of containers that is nearly 100% compatible with Docker, but with useful improvements and options. It is perfectly fine for building and testing applications.

Red Hat makes a free Podman Desktop for Windows available to anyone who wants to download it. It basically duplicates a lot of the ease-of-use features of Docker Desktop for Windows in terms of a GUI interface that will lead you step by step through the install and configuration process and provides a Windows based tool to display the images, containers, and volumes.

You can install Podman using “winget”. If you don’t want to read any documentation, do a

winget install redhat.podman-desktop

Then run it and it will lead you through the process of installing the podman programs in windows and creating a WSL distro with Fedora 40 and the podman service running in the background.

If you regard the Podman Desktop GUI as unnecessary fluff, you can just “winget install redhat.podman” to get all the programs, but then you have to manually create and start the WSL engine with the commands:

podman machine init
podman machine start

Because there is a podman.exe program running in Windows duplicating the docker.exe program of Docker (and with all the same commands and options), you can either change your existing programs to use “podman” instead, or you can create an alias by going to a directory early in your Path and creating a symlink named “docker.exe” that points to the “podman.exe” program:

mklink docker.exe "C:\Program Files\RedHat\Podman\podman.exe"

Then whenever you enter the “docker” command, path search will find the symlink and run podman.exe instead.

Podman for Windows (History and Design)

The basic “container” support is a standard part of Unix and therefore Linux design. Any Unix program can, when it runs another program and creates a child process, restrict that child program from seeing and therefore accessing any directories, devices, or sources of information visible to the parent. The parent can also create and substitute alternate directories or dummy system objects for the child.

There are billions of ways this could be used. The company named Docker invented the modern Container by creating a standard highly restricted environment that could run almost any application program while restricting visibility to everything else that is going on in the machine.

With limited resources, they created a single environment (the docker engine) that could be used both by developers testing programs and by administrators running production containers on large servers or clusters of servers. To promise stability to their customers, they promised not to change that environment so that production programs would run reliably in the future.

However, since there really was nothing difficult or special about creating a container runtime, other vendors could build their own versions of the same thing. AWS, Microsoft, Google, and IBM/RedHat created optimized container runtimes for their clouds. There are also several tools for developing and testing containers that are completely different from Docker, with different operations as well as different syntax.

Red Hat Podman represents a compromise. It is a plug-in exact substitute for both the docker command and engine, but it deploys them in a way that is much better for developers working on a multi-user Unix compatible development server.

Except that if you are developing containers on a Windows host and running the containers in a WSL distribution environment, the differences between Docker and Podman designs is irrelevant. Both are forced to do about the same thing in about the same way to solve the problem of running in Windows at all. Therefore, the only difference between Docker and Podman in Windows is that Podman has a few extra useful command options when you run the container to test the code, while Docker can do the same thing but with more work.

The Docker plugin in VS Code Remote WSL will not recognize Podman as a docker engine. This is a general problem for third party programs that are specifically designed to use the docker engine admin api.

Podman does give you a Fedora 40 WSL distribution, which Red Hat does not make available any other way.

A Yale developer will see some extra useful commands and options in the following bat/powershell script that runs a container for testing:

Code Block
podman secret create --replace deco.json SANDBOX.json
podman run --replace --rm -it -p 8080:8080 --secret=deco.json --name tomcat iiq:8.4-yale-1.0.52

The “docker secret create” command only works with Swarm, but Podman makes it a normal command. Then they add --secret to the run command so you don’t have to use compose. They add --replace to both commands to delete and replace an existing secret or container with the same name before you create a new one.

Podman supports Dockerfiles, although they allow you to use the alternate name “Containerfile” to avoid brand name confusion.

A Container is just a type of Linux Process

A Linux program “running in a container” is just a program that has been started in a special way. It doesn’t look or behave differently from normal programs.

Code Block
$ docker run --name tomcat -d --rm tomcat:jdk11-tc9
02f58c9115a4b0e35a22ec496cec9d5808e1e4394558a0491650d6e18d179a25
$ ps -ef|grep tomcat
root       11797   11777 11 12:55 ?        00:00:01 /opt/java/openjdk/bin/java ... start

In this example we start a container that runs Tomcat, then display the running tomcat program as an ordinary Linux process. A Tomcat process looks pretty much the same whether it was started as a container, or as a background service under systemd, or interactively by a logged in user running the /bin/startup script.

The system services that create containers have always been part of Unix, but for decades they were obscure technical features. Then Docker released a software package to configure, build, and run application programs in a special configuration that became widely known as “Containers”. However, the Linux environment Docker decided to use to run applications is only one specific configuration of the more general idea of containerization.

A Docker application container appears to be a Linux system running in “single-user” mode. Nothing is running in the system except a single user login with its shell. You can boot any Linux system into single user mode, which is used to do maintenance on the system, but all images in Docker Hub create this appearance.

The original Unix design placed all system information in the structure you normally think of as “/”. While it contains directories and files, it also contains real disks, network disks, network adapters, sockets, the process created when a program runs, shared libraries loaded into memory, and so on.

When one program starts any other program, it can edit this “namespace” structure to remove objects it doesn’t want the new program to access and add synthetic objects. For example, it can remove all real LAN adapters but create an imaginary LAN backed by VPN software, so the new program can only access the VPN and not the real local network.

Containers are built on this capability. Docker invented a particular configuration and file format to create both a specific image of directories and files and a set of VPN dummy networks. This file format was then standardized by an industry working group.

Extra Responsibilities

At Yale, when an application runs on a VM it is the Linux Systems Group that installs and configures Java and Tomcat and installs prerequisite software. The developers only install the WAR into the Tomcat “webapps” subdirectory.

When developers build a container to run the application, they start with a base container from Docker Hub that typically contains a version of Java and Tomcat. They may provide the Yale root CA certificates in a cacerts file and the Yale Kerberos configuration in a krb5.conf file. The Dockerfile may run the package manager to install prerequisite shared libraries.

All containers can then run on a generic minimal Linux system. There is no need to customize a VM for any application. However, developers now need to know the system configuration files and packages that were previously the responsibility of the Systems group.

Alternatives

Docker tries to use a single implementation to work on a single user laptop, a large multiuser corporate server, a cluster of enterprise servers, and a Cloud based SaaS. Larger companies with more resources (Microsoft, Amazon, Red Hat/IBM) provided their own high-end alternatives for production use, while Podman is interesting for the developer’s laptop, which is the focus environment for this article.

At Yale, a developer cannot create production container images. The developer edits a Dockerfile project that generates images. A local image can be built and unit tested on the laptop. The Dockerfile project is then checked into git.yale.edu and a Jenkins job builds the production image and stores it on the Harbor image repository server.

Therefore, the rest of Yale does not know and cannot care what software is used on the laptop to test the Dockerfile project. It has to be compatible with the Dockerfile standard, but it can be Podman or any other compatible tool.

WSL is a different Container Runtime

Windows Subsystem for Linux is a tightly coupled Linux environment that can run Linux commands as if they were a natural part of Windows. Someone familiar with a Linux command like “grep” can use it on the Windows command line by prefixing the command name with “wsl”:

Code Block
C:\Windows\System32>tasklist|wsl grep sql
sqlwriter.exe                 5804 Services                   0      8,504 K
sqlceip.exe                   7780 Services                   0     53,584 K
sqlservr.exe                  7848 Services                   0    199,708 K

Under the covers, cmd.exe is piping the standard output of tasklist.exe to standard input of wsl.exe. The wsl.exe program communicates to the WSL Linux VM passing the current Windows environment (including the current directory), the grep command, and the stream of characters from the pipe. This sets up the environment, runs the Linux program (/bin/grep), and passes it the stream of characters as standard input. The program runs in a Linux system where all the Windows local disks have been mounted with file access permissions on the Windows files inherited from the user who executed the Windows command.

WSL is implemented as a single Linux VM running the Microsoft Linux kernel, on top of which a Microsoft container runtime supports multiple Linux “distribution” containers. You can install these WSL containers using Windows Store or wsl.exe. A subset of the available containers is:

Code Block
>wsl -l --online
The following is a list of valid distributions that can be installed.
Install using 'wsl.exe --install <Distro>'.
NAME                                   FRIENDLY NAME
Ubuntu                                 Ubuntu
Debian                                 Debian GNU/Linux
kali-linux                             Kali Linux Rolling
Ubuntu-22.04                           Ubuntu 22.04 LTS
OracleLinux_9_1                        Oracle Linux 9.1
openSUSE-Leap-15.5                     openSUSE Leap 15.5

Microsoft tries to keep things simple, so they use the term “distro” to mean two different things that they assume the reader will not have to distinguish. In a list of install options, “OracleLinux_9_1” refers to an image tar file prepared by Oracle and submitted to Microsoft for distribution. When you do a “wsl --install”, this image file is used to create a WSL container, and the container is also given the name “OracleLinux_9_1”. After that, when the wsl documentation refers to running a program or an interactive shell in a “distro” they are talking about the container and not the image used to build it.

Over time the vendor may provide an updated image file under the same name. The “Ubuntu-22.04” name has been used for two years, but if you install it today and then display the /etc/lsb-release file you find it has “DISTRIB_DESCRIPTION="Ubuntu 22.04.3 LTS”, so this is probably the fourth refresh update of the image.

A WSL container is different from a Docker container. Docker containers are intended to be short term and lose all their disk data when the system shuts down. WSL containers have a Microsoft virtual hard drive file (a VHDX, like a VM disk), so changes are permanent until you discard the container.

WSL containers shut down and restart. Traditionally they run in single-user mode, but Microsoft changed the rules and today many of them, notably Ubuntu, will run in “systemd” mode if you add “[boot] systemd=true” to the /etc/wsl.conf file in the image file system disk and restart the container.

“wsl docker”

When WSL Ubuntu runs in the default single-user mode, it cannot install and run a Docker Engine. However, if you enable systemd, then Ubuntu will let you “sudo apt install docker.io” or even install docker as a snap. This puts a docker command in WSL Linux, and like any other command you can run from Windows by adding the wsl.exe prefix.

Since the primary topic of this paper is building Docker images, the specific Windows command of interest is

wsl docker build .

You execute this command from a Windows directory containing a Dockefile project. Windows invokes the Linux docker command in the same current directory, but in the Linux system. There it transfers data to the Docker Engine, which executes the operations in the Dockerfile, builds the image and stores it in the Engine’s local image repository.

If you don’t like typing “wsl docker”, you can create a docker.bat file in your path with the line:

wsl docker %*

This is the simplest way to install and run Docker on Windows without using any licensed material. You get Ubuntu from the Windows Store. You get docker from the Ubuntu package libraries. There is no docker.exe, but there is no need for one.

...

What We Are Replacing (Docker Desktop for Windows)

Docker Desktop for Windows installs a set of Windows programs including docker.exe in the Windows executable path. It also creates a custom Windows Subsystem for Linux “distro” containing a version of the Moby Linux system optimized for running containers and a preinstalled version of the “docker engine” component (dockerd/containerd).

While WSL has its own private virtual network and its own protocol for communication between Windows and Linux programs, Docker already had its own mechanism through which the “docker” command talks to the “docker engine” running in the background. Rather than converting to an entirely different approach, Docker tries to maintain in Windows/WSL as much of the same code and protocol as it used in Linux, with a local “unix socket” or through the network from one machine to another. The result is something that is not exactly the same as Linux but is also completely different from any other WSL package.

The alternatives to Docker Desktop also install in WSL, but either they use a completely standard WSL distribution and standard Windows to WSL communication, or else they also create a custom distribution with their own Linux-of-choice image (Fedora instead of Moby for example) but after that using standard WSL networking.

WSL Networking

There is a detailed section below under the heading “Plumbing” that contains more details on WSL networking and communication. The short version is that all WSL instances run in non-standard containers under a single Microsoft Linux Kernel VM. Windows communicates to WSL to share files and transfer commands using an old Bell Labs protocol called 9P. There is a virtual LAN between Windows and the Linux Kernel shared by all the WSL instances. However, any Container runtime has to create its own VPN that is separate from the host network.

There is one extra trick that needs to be understood. All virtual machines run under the Hyper-V system and are connected to the Windows Kernel by a low-level high performance virtual bus. The Microsoft Linux Kernel has a special driver for its “localhost” or “loopback” virtual device with IP address 127.0.0.1. The loopback “adapter” on all the different Linux distributions that you install in WSL share the same loopback adapter, and the Microsoft Linux Kernel loopback communicates directly to the corresponding loopback driver in the Windows Kernel.

As a result, any program running in Windows or any WSL Linux environment can reserve a loopback port number by being the first program in any environment to list to, for example, port 9876. Then any client program on Windows or any WSL system can connect to 127.0.0.1:9876 and communicate to that program. This communication is done by a direct Windows Kernel to Linux Kernel driver level communication over the Hyper-V service bus and has nothing to do with any of the virtual LAN networks that Hyper-V creates. It also only works for WSL and does not apply to any other virtual machine.

This trick is important because while Docker has decided to convert its standard internal VPN from Linux-Linux to Linux-Windows, most of the alternative solutions only offer “localhost” networking. A test client program in Windows (or any other WSL distribution) can connect to a containerized application listening to a port number redirected by the equivalent to “docker run -p 9876:9876” which in turn ends up as “localhost:9876” on Windows and throughout the WSL environment.

WSL Ubuntu 24.04 Distro

Containers run under a runtime engine. The Docker engine runs as a Linux background service under the “systemd” supervisor. After WSL 2 introduced the Microsoft Linux Kernel, it was possible to run systemd in a WSL Linux instance, but none of the standard WSL systems you could get from Microsoft supported this. Then WSL Linux distributions began to support an option to turn on systemd using a configuration file /etc/wsl.conf in the image file system. Starting with later versions of Ubuntu 23.04.3 or 23.10, systemd was turned on by default. Once that happened, the Ubuntu package libraries were changed so you could install the docker.io package into WSL Ubuntu in the same way you install it on an ordinary computer or VM. Just run “sudo apt install docker.io” (or type “docker” into the command line of an Ubuntu that doesn’t have it and get a list of installation options).

This creates a WSL that has a “docker” command and a docker engine running in the background. However, you probably want to edit in Windows and only use this command to build and run the containers. There are two easy to use solutions.

In any Windows command line (cmd.exe, terminal, or PowerShell) you can run a Linux command in the default WSL environment by just typing “wsl“ in front of the command (or “wsl. exe” if you want to be more explicit). The Linux command inherits the current Windows directory and many environment variables. So to build an image type “wsl docker build …” in the directory containing the Dockerfile project, and to run a container type “wsl docker run …”.

Alternately, you can use Visual Studio Code Remote (WSL). The GUI editor in VS Code connects to a directory in the WSL Linux image, edits files, and with the Docker plugin can build images and run containers.

The one restriction is that client programs can only connect to the container from Windows or a WSL environment, and they must connect through the localhost trick. So if you start the container with

wsl docker run -p 8080:8080

then the client program, which can be a Windows browser, is going to connect to it as “http://localhost:8080/…”.

You can create a docker.bat file with contents

Code Block
@ECHO OFF
wsl docker %*

If you need it, you can add docker-compose the same way with “wsl sudo apt install docker-compose” and create another bat file for that command.

Podman Desktop for Windows

Podman is the Red Hat alternative to the standard Docker system. It is a redesign and reimagining of containers that is nearly 100% compatible with Docker syntax, but not with the API for third party utility programs. It is perfectly fine for building and testing applications.

Red Hat makes a free Podman Desktop for Windows available to anyone who wants to download it. It basically duplicates a lot of the ease-of-use features of Docker Desktop for Windows in terms of a GUI interface that will lead you step by step through the install and configuration process and provides a Windows based tool to display the images, containers, and volumes.

You can install Podman using “winget”. If you don’t want to read any documentation, do a

winget install redhat.podman-desktop

Then run it and it will lead you through the process of installing the podman programs in windows and creating a WSL distro with Fedora 40 and the podman service running in the background.

If you regard the Podman Desktop GUI as unnecessary fluff, you can just “winget install redhat.podman” (without the -desktop suffix) to get all the command programs. Then you have to manually create and start the WSL engine with the commands:

podman.exe machine init
podman.exe machine start

Because there is a podman.exe program running in Windows duplicating the docker.exe program of Docker (and with all the same commands and options), you can either change your existing programs to use “podman” instead, or you can create an alias by going to a directory early in your Path and creating a symlink named “docker.exe” that points to the “podman.exe” program:

mklink docker.exe "C:\Program Files\RedHat\Podman\podman.exe"

Then whenever you enter the “docker” command, path search will find the symlink and run podman.exe instead.

Podman for Windows relies on the same WSL “localhost” trick. A container that has been mapped to use port 8080 is available to client test programs in Windows or WSL as “localhost:8080”, but no client can run from another computer or even another VM on the same Hyper-V system.

Podman for Windows (History and Design)

Docker provided open-source code that could be distribute for any Linux system. Red Hat could and did distribute the docker package if you wanted to install it on RHEL.

However, none of the other vendors was stuck with the original decisions made by the Docker group when they built the first system and then decided to maintain its limitations and design problems in all future versions.

Red Hat is a Linux company, so they were mostly interested in solving the problems of Linux developers. The most serious problem with Docker on Linux is that it runs a single Engine in the background under root and all of the image files that it builds and runs are stored in a single repository with no individual ownership or permissions. Anyone who can run docker commands on a machine can change any image file created by any other user.

No programming language works this way. Developers login under their own userid and store files in their home directory. Each user owns his own files and permits other users to access them selectively. Podman is a complete replacement of the “docker” command that builds and runs containers under the developer’s userid in the developer’s login and home directory. To make this work, the “podman” executable program includes its own container engine that runs in the login rather than in the background.

There are many advantages to Podman if you have Linux developers sharing a large development server machine, but that doesn’t happen anymore. Today each developer has his own personal machine, and if you have one person who is the only user and administrator of a machine, then the major design different between Docker and Podman goes away. More importantly, if you have to run a command in Windows (docker.exe or podman.exe) and then run the containers in a WSL environment, then you end up configuring Podman Desktop to run exactly the same way that Docker Desktop runs.

So, the only really important differences are that Podman Desktop is absolutely free and Podman has a few extra command options that Docker doesn’t make available in the same way.

Podman builds Dockerfiles with the same syntax. A Podman Image can be pushed to a network image repository and then run under Docker on another system. However, at Yale production images have to be rebuilt by Jenkins from the Dockerfile and developers are not allowed to push images from a development machine.

The Podman engine does not speak the same protocol as the docker engine, so the VS Code Docker Plugin does not recognize it and cannot display useful information.

A Yale developer will see some extra useful commands and options in the following bat/powershell script that runs a container for testing:

Code Block
podman secret create --replace deco.json SANDBOX.json
podman run --replace --rm -it -p 8080:8080 --secret=deco.json --name tomcat iiq:8.4-yale-1.0.52

The “docker secret create” command only works with Swarm, but Podman makes it a normal command for end users. Then they add --secret to the run command so you don’t have to use compose. They add --replace to both commands to delete and replace an existing secret or container with the same name before you create a new one. These are all options you wish Docker made available, but Docker will not change decisions it made long ago or add convenience features to new releases.

Podman build supports Dockerfiles, although it also allows you to use the alternate name “Containerfile” to avoid brand name confusion.

WSL is a different Container Runtime Tightly Integrated in Windows

Windows Subsystem for Linux is a tightly coupled Linux environment that can run Linux commands as if they were a natural part of Windows. Someone familiar with a Linux command like “grep” can use it on the Windows command line by prefixing the command name with “wsl”:

Code Block
C:\Windows\System32>tasklist|wsl grep sql
sqlwriter.exe                 5804 Services                   0      8,504 K
sqlceip.exe                   7780 Services                   0     53,584 K
sqlservr.exe                  7848 Services                   0    199,708 K

The normal processing of cmd.exe sees “tasklist | wsl" and pipes the standard output of tasklist.exe to the standard input of wsl.exe. Then wsl.exe connects to the default WSL Linux environment using a P9 substitute for SSH and sends the standard input it is getting through to a WSL Linux command of “grep sql”. Grep runs in Linux and generates standard output, which WSL then grabs and like SSH sends back to Windows where the output is typed on the screen by cmd.exe.

With WSL a Windows user can mix in Linux commands with Windows commands whenever it is convenient.

WSL is implemented as a single Linux VM running the Microsoft Linux kernel, on top of which a Microsoft container runtime supports multiple Linux “distribution” containers. You can install these WSL containers using Windows Store or wsl.exe. A subset of the available containers is:

Code Block
>wsl -l --online
The following is a list of valid distributions that can be installed.
Install using 'wsl.exe --install <Distro>'.
NAME                                   FRIENDLY NAME
Ubuntu                                 Ubuntu
Debian                                 Debian GNU/Linux
kali-linux                             Kali Linux Rolling
Ubuntu-22.04                           Ubuntu 22.04 LTS
OracleLinux_9_1                        Oracle Linux 9.1
openSUSE-Leap-15.5                     openSUSE Leap 15.5

Microsoft tries to keep things simple, so they use the term “distro” to mean two different things that they assume the reader will not have to distinguish. In a list of install options, “OracleLinux_9_1” refers to an image tar file prepared by Oracle and submitted to Microsoft for distribution. When you do a “wsl --install”, this image file is used to create a WSL container, and the container is also given the name “OracleLinux_9_1”. After that, when the wsl documentation refers to running a program or an interactive shell in a “distro” they are talking about the container and not the image used to build it.

Over time the vendor may provide an updated image file under the same name. The “Ubuntu-22.04” name has been used for two years, but if you install it today and then display the /etc/lsb-release file you find it has “DISTRIB_DESCRIPTION="Ubuntu 22.04.3 LTS”, so this is probably the fourth refresh update of the image.

A WSL container is different from a Docker container. Docker containers are intended to be short term and lose all their disk data when the system shuts down. WSL containers have a Microsoft virtual hard drive file (a VHDX, like a VM disk), so changes are permanent until you discard the container.

WSL containers shut down and restart. Traditionally they run in single-user mode, but Microsoft changed the rules and today many of them, notably Ubuntu, will run in “systemd” mode if you add “[boot] systemd=true” to the /etc/wsl.conf file in the image file system disk and restart the container.

Special Purpose WSL “distro” Images

...

Docker Desktop for Windows includes a tar file for their Moby Linux and creates a WSL container named “docker-desktop-data”.

Podman includes a Fedora 38 40 tar file and creates a container named “podman-machine-default”. You can then create additional WSL Fedora containers with different names using the “podman machine init” command.

...

ExecStart=/usr/bin/dockerd -H fd:// -H 192.168.2.204 --containerd=/run/containerd/containerd.sock

...