Featured image of post Lightweight Docker in WSL without Docker Desktop

Lightweight Docker in WSL without Docker Desktop

How to run Docker without Docker Desktop

Follow me

Introduction Link to this section

Docker Desktop provides many features, but it also is heavy and takes a lot of time to start. This made me remove it and install only Docker Engine directly in WSL and reduced the startup time from minutes to seconds.

In this post I’ll show how to do it and some configurations to better the experience.

Quick definition Link to this section

A quick definition of the terms:

  • Docker Engine: It is the core component of Docker, providing orchestration of the container runtime, image management and networking and storage capabilities;
  • Docker CLI: The command line interface to interact with the Docker API;

Installing Docker Engine on WSL Link to this section

To install Docker Engine in WSL, first we follow the official docs for the distro we are using. I use Ubuntu, so I’ll give instructions for it in this post, but for other distros, click here.

We need to add the docker repository to apt’s sources and install its components (Docker Engine, Docker CLI, Containerd, BuildX and Docker Compose):

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
# Add Docker's official GPG key:
sudo apt-get update
sudo apt-get install ca-certificates curl
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc

# Add the repository to Apt sources:
echo \
  "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu \
  $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \
  sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt-get update

sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

To be able to use the docker CLI command without root permissions, we need to create a docker group and add our user it:

1
2
3
sudo groupadd docker
sudo usermod -aG docker $USER
newgrp docker

Then we can start the Docker service:

sudo service docker start

And run the hello-world image to test:

docker run hello-world

How to auto start Docker in WSL starts Link to this section

There are two ways to auto start Docker in WSL

With systemd Link to this section

For WSL version 0.67.6 or newer, we can enable the use of systemd:

In the WSL distro, edit the /etc/wsl.conf file and add the following lines:

1
2
[boot]
systemd=true

Then, from Windows, run the following command to kill WSL:

wsl --shutdown

Open the WSL distro shell and run a docker ps to validate that Docker has auto-started.

With a profile script Link to this section

I recommend using systemd, but it adds a bit of latency in the startup (14 seconds in my machine).

If this is a problem, Docker can be started with the following script in the profile script (.zshrc, .bashrc, etc):

1
2
3
4
5
6
if grep -q "microsoft" /proc/version > /dev/null 2>&1; then
    if service docker status 2>&1 | grep -q "is not running"; then
        wsl.exe --distribution "${WSL_DISTRO_NAME}" --user root \
            --exec /usr/sbin/service docker start > /dev/null 2>&1
    fi
fi

It checks if the distro is a WSL distro (in case you share your profile script between machines) and start the docker service if its not running.

Source: https://github.com/nickjj/dotfiles/commit/badd3265e5c8f6eca90d3b57df29292545332500

How to access Docker from Windows Link to this section

To access the Docker socket from outside the WSL distro, we have to add an extra configuration to Docker Daemon.s

If using systemd: Link to this section

Edit the /lib/systemd/system/docker.service and add -H tcp://0.0.0.0:2375 in the ExecStart as shown below:

1
2
3
[Service]
Type=notify
ExecStart=/usr/bin/dockerd -H fd:// -H tcp://0.0.0.0:2375 --containerd=/run/containerd/containerd.sock

And restart Docker:

sudo service docker restart

If starting with a profile script Link to this section

Edit the /etc/docker/daemon.json and add the hosts configuration as shown below:

1
2
3
{
  "hosts": ["unix:///var/run/docker.sock", "tcp://0.0.0.0:2375"]
}

And restart Docker:

sudo service docker restart

Then, on Windows, configure the DOCKER_HOST environment variable to tcp://localhost:2375 (or tcp://[::1]:2375 if using IPv6).

With this environment variable set, tools like Testcontainers and Localstack will work using the Docker engine installed in WSL.

💡 I wrote some posts about Testcontainer and Localstack.

Access from the command line Link to this section

I prefer to run commands from the shell in WSL, but if needed, there are some options:

  • Install the Docker CLI on Windows (It will respect the DOCKER_HOST set above);
  • Run with the wsl command: wsl -d Ubuntu docker ps

I won’t dive into details about this though.

Possible errors Link to this section

Invalid credsStore config Link to this section

If Docker Desktop was installed, the credentials store may have been set to to docker-credential-desktop and the following error will be shown:

1
error getting credentials - err: exec: "docker-credential-desktop": executable file not found in $PATH, out: ``

To fix the error, edit the file ~/.docker/config.json and remove the credsStore property.

Duplicated hosts configuration Link to this section

If Docker initialization was setup using systemd and the following error occur when starting Docker service, it can be because of duplicated host configuration.

1
2
3
4
5
6
7
8
> sudo service docker restart
Job for docker.service failed because the control process exited with error code.
See "systemctl status docker.service" and "journalctl -xeu docker.service" for details.

> systemctl status docker.service
Aug 29 06:18:04 DanielPC systemd[1]: docker.service: Main process exited, code=exited, status=1/FAILURE
Aug 29 06:18:04 DanielPC systemd[1]: docker.service: Failed with result 'exit-code'.
Aug 29 06:18:04 DanielPC systemd[1]: Failed to start Docker Application Container Engine.

systemd will use the docker.service configuration, that passes the hosts as arguments in with the -H parameter and this error will happen if you also set the hosts in /etc/docker/daemon.json.

To fix, remove the hosts parameter from /etc/docker/daemon.json and follow the configuration here.

References Link to this section

💬 Like or have something to add? Leave a comment below.
Ko-fi
GitHub Sponsor
Licensed under CC BY-NC-SA 4.0
Built with Hugo
Theme Stack designed by Jimmy