Skip to content

Linux on Windows with WSL2 – Part 3

What are we going to do

Now that we have a running wsl2/ubuntu with docker installed and our first container service (coredns) we will run another core container : a small and powerful reverse proxy and load balancer named traefik.

Run an ADC container as a service

We will do the same as our dns service but using traefik to publish an internal docker endpoint to our windows host.

Lets go to wsl2/ubuntu machine.

PS C:\Users\tdesa> wsl

The structure will look like the following (my core containers are hosted on a GitLab repository).

tdesaules@DESKTOP-IVUMN45-wsl:~$ cd ~/GitLab/containers/traefik/
tdesaules@DESKTOP-IVUMN45-wsl:~/GitLab/containers/traefik$ tree
├── config
│   ├── dynamic.yml
│   └── traefik.yml
├── docker-compose.yml
├── traefik-l4.initd
└── traefik-l4.service

So we have : One config folder with the traefik.yml base config file and a dynamic.yml file that is used to configure static reverse rules reloaded dynamically, one docker-compose.yml file to manage the container and the traefik-l4.service systemd service file.

First we need to create a docker-compose file to manage the container. On it, we fix the ip on the development network to be sure it will not change, configure the dns, expose some ports, mount the local config folder and add the command to correctly launch traefik.

version: ‘3’

    container_name: ‘traefik-l4’
    restart: ‘no’
    image: ‘traefik:v2.8’
        ipv4_address: ‘’
    dns: [‘’]
      – ‘–configFile=/etc/traefik/traefik.yml’
      – ’80:80′
      – ‘443:443’
      – ‘8080:8080’
      – ‘9000:9000’
      – ‘/var/run/docker.sock:/var/run/docker.sock:ro’
      – ‘/etc/localtime:/etc/localtime:ro’
      – ‘./config:/etc/traefik’

    external: true

In the traefik config file (config/traefik.yml) we are able to enable the webui, configure some entrypoints (80 for futures webapps and 9000 for the traefik gui) and add providers to autodiscover our container.

  dashboard: true
  insecure: true

    address: :80
    address: :9000

    filename: /etc/traefik/dynamic.yml
  docker: {  }

  level: INFO

The local file (config/dynamic.yml) can be used to configure some endpoints. We will only use it to publish the traefik admin gui with a router based on a hostname rule pointing to the internal gui service api@internal that will allow us to access the traefik gui from our browser using an internal dns name.

      entryPoints: admin
      rule: Host(`traefik-l4.desaules.local`)
      service: api@internal

The systemd file (traefik-l4.service) looks like the one created for the coredns.

Description=Traefik L4 Container Service

ExecStart=/usr/bin/docker-compose –file /home/tdesaules/GitLab/containers/traefik/docker-compose.yml up –detach –remove-orphans –force-recreate
ExecStop=/usr/bin/docker-compose –file /home/tdesaules/GitLab/containers/traefik/docker-compose.yml down
ExecReload=/usr/bin/docker-compose –file /home/tdesaules/GitLab/containers/traefik/docker-compose.yml restart


Now we have all the stuff we need. Let’s configure the systemd service.

tdesaules@DESKTOP-IVUMN45-wsl:~/GitLab/containers/traefik$ sudo ln -s /home/tdesaules/GitLab/containers/traefik/traefik-l4.service /etc/systemd/system/traefik-l4.service

tdesaules@DESKTOP-IVUMN45-wsl:~$ sudo systemctl daemon-reload

tdesaules@DESKTOP-IVUMN45-wsl:~$ sudo systemctl enable traefik-l4

tdesaules@DESKTOP-IVUMN45-wsl:~$ sudo systemctl start traefik-l4

tdesaules@DESKTOP-IVUMN45-wsl:~/GitLab/containers/traefik$ sudo systemctl status traefik-l4
● traefik-l4.service – Traefik L4 Container Service
    Loaded: loaded (/etc/systemd/system/traefik-l4.service; enabled; vendor preset: enabled)

tdesaules@DESKTOP-IVUMN45-wsl:~$ docker ps –format “{{.ID}}: {{.Image}} {{.State}}”
e20bfa634b39: traefik:v2.8 running
5a5d5681bc61: coredns/coredns:1.9.2 running

On the coredns local zone file we need to add a new entry to resolve the traefik gui. (Remember the ip used is the one hosted by the wsl2/ubuntu machine because our traefik service is exposing its entrypoints using the docker compose ports entry) traefik-l4.desaules.local

And check that the traefik gui is correctly responding over the dns configured on the coredns local zone (traefik-l4.desaules.local) and port defined in the traefik entrypoints (admin with port 9000).

Note 1: On the traefik webui we can see that the file rule is correctly working because we have access to the admin gui from the dns configured on coredns. Our browser can access it with port tcp/9000 that we configured on traefik and exposed with our docker compose file. 

We also see that our docker provider automatically discovers our two containers (coredns and traefik-l4).

Expose the whoami web application with Traefik

Traefik gives us a small container acting as a whoami webapp. We will use it with docker compose to start and scale it to see if traefik follows our moves.

The important part in this docker compose file is the labels entries that is used by traefik when reading the docker socket to expose a docker service with the rules configured. Here is a simple router named whoami with a host rule to respond over whoami.desaules.local dns and exposed over the traefik entrypoints named web over tcp/80.

version: ‘3’

    restart: ‘no’
    image: ‘traefik/whoami’
    dns: [‘’]
      – ‘/var/run/docker.sock:/var/run/docker.sock:ro’
      – ‘/etc/localtime:/etc/localtime:ro’
      – “traefik.http.routers.whoami.rule=Host(`whoami.desaules.local`)”
      – “traefik.http.routers.whoami.entryPoints=web”

    external: true

On the coredns local zone file we need to add a new entry to resolve the whoami webapp. whoami.desaules.local

Launch the service.

tdesaules@DESKTOP-IVUMN45-wsl:~/GitLab/containers/whoami$ docker-compose up
[+] Running 1/0
⠿ Container whoami  Created                                                                                                                                                                                                  0.1s
Attaching to whoami
whoami  | 2022/06/20 19:27:49 Starting up on port 80

We can see that the whoami container is running.

tdesaules@DESKTOP-IVUMN45-wsl:~$ docker ps –format “{{.ID}}: {{.Image}} {{.State}}”
e20bfa634b39: traefik:v2.8 running
5a5d5681bc61: coredns/coredns:1.9.2 running
695a0d48466d: traefik/whoami running

We can check on the traefik gui that our whoami is correctly exposed.

And finally open the webapp in a browser.

Scale the whoami web application

Now that we confirm that the web application is working, we can try to scale it to see what happens.

tdesaules@DESKTOP-IVUMN45-wsl:~/GitLab/containers/whoami$ docker-compose up –scale whoami=5
[+] Running 5/0
⠿ Container whoami-whoami-5  Created                                                                       0.1s
⠿ Container whoami-whoami-2  Created                                                                              0.1s
⠿ Container whoami-whoami-3  Created                                                                              0.1s
⠿ Container whoami-whoami-4  Created                                                                              0.1s
⠿ Container whoami           Recreated                                                                            0.1s
Attaching to whoami-whoami-1, whoami-whoami-2, whoami-whoami-3, whoami-whoami-4, whoami-whoami-5
whoami-whoami-5  | 2022/07/05 19:27:09 Starting up on port 80
whoami-whoami-2  | 2022/07/05 19:27:09 Starting up on port 80
whoami-whoami-4  | 2022/07/05 19:27:10 Starting up on port 80
whoami-whoami-3  | 2022/07/05 19:27:10 Starting up on port 80
whoami-whoami-1  | 2022/07/05 19:27:10 Starting up on port 80

On traefik we can see if the service is correctly distributed over the 5 containers.

Note 1: If you try to refresh the http://whoami.desaules.local/ web page on the browser you will see that the targeted server ip changes based on the round robin load balancing algorithm.

Clean whoami

tdesaules@DESKTOP-IVUMN45-wsl:~/GitLab/containers/whoami$ docker-compose down
[+] Running 5/0
⠿ Container whoami-whoami-5  Removed                                                                              0.0s
⠿ Container whoami-whoami-4  Removed                                                                              0.0s
⠿ Container whoami-whoami-1  Removed                                                                              0.0s
⠿ Container whoami-whoami-2  Removed                                                                              0.0s
⠿ Container whoami-whoami-3  Removed                                                                              0.0s

Next steps

In the “Part 4” we will see how to use our wsl2/ubuntu machine to do some vscode remote development with and without containers.