Skip to content

Linux on Windows with WSL2 – Part 4

What are we going to do

It is cool to play with some containers but let’s see how our wsl2/ubuntu can help us to develop efficiently.

Note 1

Docker desktop integration is better for the stuff we will see in that part because it has better integration with the windows os. But like I say, I prefer to use a native docker.

Retrieve the tools we need

Lets go to wsl2/ubuntu machine.

PS C:\Users\tdesa> wsl

I use a folder named “GitLab” inside my wsl2/ubuntu home to store my Workspace. Workspace that we will “mount” inside wsl2/ubuntu and after that in a dev container.

tdesaules@DESKTOP-IVUMN45-wsl:~$ mkdir /home/tdesaules/GitLab
tdesaules@DESKTOP-IVUMN45-wsl:~$ cd GitLab/

Now we can clone the gitlab repo that we will use as an example.

tdesaules@DESKTOP-IVUMN45-wsl:~/GitLab$ git clone https://gitlab.com/thibault.desaules/rust-rocket-hello-world.git
Cloning into ‘rust-rocket-hello-world’…
remote: Enumerating objects: 10, done.
remote: Counting objects: 100% (10/10), done.
remote: Compressing objects: 100% (8/8), done.
remote: Total 10 (delta 0), reused 10 (delta 0), pack-reused 0
Unpacking objects: 100% (10/10), 13.56 KiB | 1.69 MiB/s, done.

We need to install rust dependencies for our rocket.rs webapp inside the wsl2/ubuntu. (take the default options)

tdesaules@DESKTOP-IVUMN45-wsl:~/GitLab$ curl –proto ‘=https’ –tlsv1.2 -sSf https://sh.rustup.rs | sh
info: downloading installer
[…]
Rust is installed now. Great!

To get started you may need to restart your current shell.
This would reload your PATH environment variable to include
Cargo’s bin directory ($HOME/.cargo/bin).

To configure your current shell, run:
source “$HOME/.cargo/env”

And try to launch our rocket webapp.

tdesaules@DESKTOP-IVUMN45-wsl:~/GitLab$ cd rust-rocket-hello-world*
tdesaules@DESKTOP-IVUMN45-wsl:~/GitLab/rust-rocket-hello-world$ cargo run
  Compiling version_check v0.9.4
  Compiling autocfg v1.1.0
  Compiling cfg-if v1.0.0
[…]
  Compiling rust-rocket-hello-world v0.1.0 (/home/tdesaules/GitLab/rust-rocket-hello-world)
    Finished dev [unoptimized + debuginfo] target(s) in 37.75s
    Running `target/debug/rust-rocket-hello-world`
🔧 Configured for debug.
  >> address: 0.0.0.0
  >> port: 8000
  >> workers: 16
  >> ident: Rocket
  >> limits: bytes = 8KiB, data-form = 2MiB, file = 1MiB, form = 32KiB, json = 1MiB, msgpack = 1MiB, string = 8KiB
  >> temp dir: /tmp
  >> http/2: true
  >> keep-alive: 5s
  >> tls: disabled
  >> shutdown: ctrlc = true, force = true, signals = [SIGTERM], grace = 2s, mercy = 3s
  >> log level: normal
  >> cli colors: true
📬 Routes:
  >> (index) GET /
📡 Fairings:
  >> Shield (liftoff, response, singleton)
🛡️  Shield:
  >> X-Frame-Options: SAMEORIGIN
  >> X-Content-Type-Options: nosniff
  >> Permissions-Policy: interest-cohort=()
🚀 Rocket has launched from http://0.0.0.0:8000

Note 1

You can confirm from your windows browser that the rocket webapp is correctly responding : http://localhost:8000/

Note 2

I choose to follow the rocket rust framework to get a basic webapp but you can do the same with any other language.

Map VS Code to WSL2/Ubuntu to Docker Container

First we need to install some vscode plugins : Remote Development, Remote – WSL, Remote – Containers, Remote – SSH

Then we can open the folder from the cloned repository (\\wsl.localhost\…).

To finally reopen it inside wsl2/ubuntu : F1 > Remote-WSL: Reopen Folder in WSL (see the little icon on the bottom left)

From that point we are able to work with the application directly in the wsl2/ubuntu workspace; It should have the needed prerequisites to develop (here I use cargo run command to launch the rocket app)

But we can also extend this to work inside wsl2/ubuntu docker adding a devcontainer template to our workspace : F1 > Remote-Containers: Add Development Container Configuration Files > Rust

It will create a “.devcontainer” folder with a json definition file “devcontainer.json” and a “Dockerfile”. A popup will ask us if we want to reopen the workspace inside the “Dev Container” (say yes of course) :

Note 1

You can confirm from your browser that the rocket webapp is still correctly responding : http://localhost:8000/

Note 2

You can also close the vscode windows, open the folder again “locally” and then : F1 > Remote-Containers: Reopen in Container to directly launch the vscode workspace inside the defined container.

Note 3

You can choose to create your own basic devcontainer or to choose a generic one like : F1 > Remote-Containers: Add Development Container Configuration Files > Alpine > 3.16 and customise the Dockerfile to install the dependencies you need. But keep in mind that you need to be inside wsl2 (on vscode scope) : F1 > Remote-WSL: New WSL Window using Distro > Ubuntu before using the Remote-Containers: Add Development Container Configuration Files command (you will get an error doing this directly from the “local” vscode).

Exposing the devcontainer to Traefik

This one is just an extra chapter to “publish” our devcontainer webapp to our local host with a pretty dns name and port using the coredns and traefik containers.

Inside the .devcontainer folder you have the “Dockerfile” used to build our container image that we need to change. Traefik needs to be able to access the local port and read the labels from the container definition to dynamically generate configurations to expose our devcontainer local port tcp/8000 with a tcp/80 port and a cool name.

# See here for image contents: https://github.com/microsoft/vscode-dev-containers/tree/v0.245.0/containers/rust/.devcontainer/base.Dockerfile

# [Choice] Debian OS version (use bullseye on local arm64/Apple Silicon): buster, bullseye
ARG VARIANT=”buster”
FROM mcr.microsoft.com/vscode/devcontainers/rust:0-${VARIANT}

LABEL traefik.http.routers.rust-rocket-hello-world.entryPoints=web
LABEL traefik.http.routers.rust-rocket-hello-world.rule=Host(`rust-rocket-hello-world.desaules.local`)

EXPOSE 8000/tcp

# [Optional] Uncomment this section to install additional packages.
# RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \
#     && apt-get -y install –no-install-recommends <your-package-list-here>

After changing the Dockerfile we have to rebuild the container : F1 > Remote-Containers: Rebuild Container

Lets go to wsl2/ubuntu machine.

PS C:\Users\tdesa> wsl

And check that our devcontainer had the correct labels and port exposed.

tdesaules@DESKTOP-IVUMN45-wsl:~$ docker ps –format “{{.ID}}: {{.Image}} {{.State}}” | grep vsc-
69cfc8ba82b9: vsc-rust-rocket-hello-world-5f1aa530cd25868e4f7037ca84ca6e9c-uid running

tdesaules@DESKTOP-IVUMN45-wsl:~$ docker inspect 69cfc8ba82b9 | jq -r ‘.[0].Config.Labels, .[0].NetworkSettings.Ports’
{
  “com.visualstudio.code.devcontainers.id”: “rust”,
  “com.visualstudio.code.devcontainers.release”: “v0.245.2”,
  “com.visualstudio.code.devcontainers.source”: “https://github.com/microsoft/vscode-dev-containers/”,
  “com.visualstudio.code.devcontainers.timestamp”: “Mon, 22 Aug 2022 22:49:51 GMT”,
  “com.visualstudio.code.devcontainers.variant”: “buster”,
  “devcontainer.local_folder”: “\\\\wsl.localhost\\Ubuntu\\home\\tdesaules\\GitLab\\rust-rocket-hello-world”,
  “traefik.http.routers.rust-rocket-hello-world.entryPoints”: “web”,
  “traefik.http.routers.rust-rocket-hello-world.rule”: “Host(`rust-rocket-hello-world.desaules.local`)”,
  “version”: “0.202.2”
}
{
  “8000/tcp”: null

On the traefik gui you will find a new http router and service corresponding to our devcontainer.

Now we only have to create a new dns entry in our coredns local zone.

172.31.174.74 rust-rocket-hello-world.desaules.local

Start the rocket webapp (cargo run) and test it on a browser.

Cool right !

Note 1

The most impacting issue comes from the fact that vscode “local” doesn’t have knowledge of the docker inside wsl2/ubuntu. This is why most of the Remote-Containers: […] commands need to be firstly run inside vscode “wsl2”. But if the initialization has been done, most of them will work. Docker desktop gives the ability to run it natively, directly exposing the docker wsl2 machine to the windows host.

Last step

In the “Part 5” we will see some other wsl2 commands or configurations that I found usefull.

Links

https://rocket.rs/

https://rustup.rs/

https://rocket.rs/v0.5-rc/guide/getting-started/#hello-world

https://doc.traefik.io/traefik/providers/docker/

https://gitlab.com/thibault.desaules/rust-rocket-hello-world