Skip to content

Technical Dive : Linux on Windows with WSL2 – Part 2

What are we going to do

I already introduced wsl2 in the first part, why I like it and how to install and configure it. In this part 2 we will use docker, docker compose and systemd to configure a dns service to serve a local zone.

Install Docker and Docker Compose

Now that we have a working wsl2/ubuntu, go inside it.

Let’s install docker to start playing with some containers.

Retrieve the docker compose binary.

Add our local user to the docker group.

Create a docker network on which we can configure statics ip and to our futures containers.

Configure docker to start on boot with systemd.

Finally check that we have all we need. 👉👽

Run a small DNS container as a service

Lets see how to create a small dns server container as a service. We will play with coredns. It is a nice dns server with a lot of plugins available. I use it in the most simple way possible : serving a local dns zone configured in a file and forward the rest on google dns. 🤗

So we have : one config folder with the coredns config file and a desaules.local zone file, one docker-compose file to manage my container, the systemd service file and a small script to dynamically update the wsl2/ubuntu ip in the dns zone.

First we need to create a docker-compose file to manage the container. On it we fix the ip on the development network (created before) to be sure it will not change. We expose the dns ports and mount the local config folder. 😎 (ez)

In the coredns config file (config/corefile) we are able to add a local zone with an auto-reload option and the path to the zone configuration file. The second part of the file is used to forward the other request to the google’s dns servers.

The zone configuration file (config/desaules.local) has a classic ip / host structure where we can add a local dns name. (The ip used is owned by the wsl2/ubuntu machine). Here we will add one entry to test coredns.

The systemd file (coredns.service) is simple. We have a pre-script (that will be explained below) and the docker compose start / stop / restart command mapped to the systemd steps.

The small script (pre.sh) will be used to update the wsl2/ubuntu’s ip inside the zone file. (the ip hosted by wsl2/ubuntu will change each time wsl2 is restarted so we need to update all our dns entry each time windows or wsl2/ubuntu is restated) 😔

Now that we have all the stuff we need. Let’s configure the systemd service. First we need to create a symlink to the systemd file and make our script executable.

Then we will configure and start our daemon.

Check if the service is correctly running.

And finally make dns queries to be sure that our dns server correctly responds.


Note 1
Agreed we can do almost all that stuff with docker compose (restart option) but it is cool to see how to use a container as a service with systemd even if it will probably never be used

Configure this container to be our DNS resolver

Now that we have a running local dns server, we need to add it to be the default dns server on wsl2/ubuntu.

We want to configure it to be able to have this kind of communication.

For that we need a small configuration on the windows host to be able to contact that dns server. It will allow windows to resolve a “desaules.local” service register on the dns server and exposed inside wsl2/ubuntu. For that we have to set the current wsl2/ubuntu’s ip as dns server on the windows wsl2 network interface (vEthernet (WSL)) that is used to root the network requests to the wsl2 host. (use an elevated admin powershell terminal)

Test if a ping is working over the dns entry we created earlier.

Note 1

Remember that wsl2/ubuntu’s ip changes each time windows is rebooted. We will see at the end how to evolve the windows scheduled task to start wsl2/ubuntu with systemd. Systemd will start docker and our new coredns container service (updating the local “desaules.local” zone with the current wsl2/ubuntu’s ip). Finally run the “small” powershell command, retrieve wsl2/ubuntu’s ip and configure it to be the dns server on the windows wsl2 network interface. Interface that is used to communicate with the wsl2 machine allowing us to expose future containers or services.

Just some details about the powershell command.

A powershell command is called to retrieve the wsl2 network interface index.

A wsl2 command is used to retrieve the current wsl2/ubuntu’s ip address.

And both are combined to the Set-DnsClientServerAddress that takes the index of the network adapter and the dns server ip to set.

Update the Windows Scheduled task to start all the stuff

For this we will use the previous powershell command in a small script named Set-DNS.ps1.

We are able to add a new exec step in our scheduled task to call that script.

Note 1

The interesting part in the scheduled task is the “exec” field that will launch the powershell script updating the network dns configuration on windows host.

Next steps

In the “Part 3” we will see how to configure a reverse proxy container systemd service to expose our future containers.

Links

https://docs.docker.com/engine/install/ubuntu/

https://docs.docker.com/compose/

https://coredns.io/

Authors

Thibault DESAULES

DevOps Engineer - Devoteam Innovative Tech France

I have loved "IT" since I was a kid :) building computers, compiling kernels, lighting up Arduino's led, launching containers and deploying infras on cloud. But my real concern: Supporting developers in their infra issues, giving them the tools to develop their applications efficiently and promoting the Cloud because it opens so many possibilities.