Skip to content

Instantly share code, notes, and snippets.

@sz763
Last active May 31, 2024 17:40
Show Gist options
  • Save sz763/3b0a5909a03bf2c9c5a057d032bd98b7 to your computer and use it in GitHub Desktop.
Save sz763/3b0a5909a03bf2c9c5a057d032bd98b7 to your computer and use it in GitHub Desktop.
How to run tests with TestContainers in WSL2 without Docker Desktop

Install docker

in case you haven't docker installed, please follow this instruction https://docs.docker.com/engine/install/ubuntu/

Expose docker port

First way

Create daemon.json file in /etc/docker, with content:

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

Second way suggested by @maireadmccabe-fire

sudo mkdir -p /etc/systemd/system/docker.service.d
sudo vim /etc/systemd/system/docker.service.d/override.conf

# add the below to the override.conf file
[Service]
ExecStart=
ExecStart=/usr/bin/dockerd --host=tcp://0.0.0.0:2375 --host=unix:///var/run/docker.sock

Restart docker daemon

sudo systemctl daemon-reload and then sudo systemctl restart docker or sudo service docker restart

or just restart WSL2 by calling wsl --shutdown  in windows CMD/PowerShell and just open linux terminal once again

if you have run docker as sudo dockerd - stop it, and run sudo dockerd once again.

Check that port are exposed

after restart docker daemon or restart wsl, run in linux terminal netstat -nl | grep 2375 (install net-tools if you haven't it). You should see that port are open.

Add environment variables

add the following properties in Windows Env Variables:

Name Value
DOCKER_HOST tcp://localhost:2375
DOCKER_TLS_VERIFY 0
DOCKER_CERT_PATH \\wsl$\home\$USER_NAME\.docker

⚠️ seems like there is kind of an issue in WSL, sometimes tcp://localhost:2375 should be replaced with tcp://$wsl_ip:2375, where $wsl_ip is IP of ifconfig eth0 ⚠️

✔️ There is a workaround suggest by @tacascer

@echo off
set port=:2375
set
(for /f "tokens=2" %%f in ('wsl ifconfig eth0 ^| findstr /c:"inet "') do (
    set dockerhost=tcp://%%f%port%
))
@REM echo %dockerhost%
setx DOCKER_HOST %dockerhost%

⚠️ port in DOCKER_HOST variable must be same as exposed above

⚠️ $USER_NAME -replace this placeholder with your linux user

⚠️ .testcontainers.properties - were empty

Restart IDE

To apply environment variables you need restart IDE (in my case is Intellij Idea) OR just specify in Run/Debug Configuration these env variables directly.

Protect the Docker daemon socket

If you are looking for secure access to docker follow the guide suggested by @gim-

@jordisilvazup
Copy link

Thanks for sharing, it helped me a lot to solve the problem, but that alone was not enough. I got more information and managed to solve it by following the steps: https://gist.github.com/jordisilvazup/a2863c06399c4f00940fa933772d426a

@gladhiola
Copy link

Many thanks for sharing this! To me it worked as a charm. One addition to this, I need to change my WSL2 environment variable DOCKER_HOST also to the new one: export DOCKER_HOST=tcp://localhost:2375

@ivan-zaitsev
Copy link

To solve issue with using IP from ifconfig eth0 you need to disable IPv6

sudo sysctl -w net.ipv6.conf.default.disable_ipv6=1
sudo sysctl -w net.ipv6.conf.all.disable_ipv6=1

@sz763
Copy link
Author

sz763 commented Dec 26, 2022

@jordisilvazup @gladhiola @ivan909020 thanks for contribution!

@maireadmccabe-fire
Copy link

Instead of adding the hosts to daemon.json which conflicted in docker for me and failed to start (Docker version 23.0.1, build a5ee5b1). I added the hosts in the override.conf see commands below.

sudo mkdir -p /etc/systemd/system/docker.service.d
sudo vim /etc/systemd/system/docker.service.d/override.conf

# add the below to the override.conf file
[Service]
ExecStart=
ExecStart=/usr/bin/dockerd --host=tcp://0.0.0.0:2375 -- host=unix:///var/run/docker.sock

sudo systemctl daemon-reload and then sudo systemctl restart docker

@Jehan-dF
Copy link

In my case I had to run sudo dockerd after changing the environment variables in order to restart the daemon

@di-ma-git
Copy link

di-ma-git commented Jul 8, 2023

In my case I had to run sudo dockerd after changing the environment variables in order to restart the daemon

Thanks, it helped me!

@tacascer
Copy link

seems like there is kind of an issue in WSL, sometimes tcp://localhost:2375 should be replaced with tcp://$wsl_ip:2375, where $wsl_ip is IP of ifconfig eth0

I wrote a batch script to set the Windows environment variable DOCKER_HOST to the ifconfig eth0 address

@echo off
set port=:2375
set
(for /f "tokens=2" %%f in ('wsl ifconfig eth0 ^| findstr /c:"inet "') do (
    set dockerhost=tcp://%%f%port%
))
@REM echo %dockerhost%
setx DOCKER_HOST %dockerhost%

@AliakseiBaryliuk-E
Copy link

Thanks, this works for me!

@ivaylo-mi
Copy link

When IPv6 is enabled, its loopback address can be used too:
DOCKER_HOST tcp://[::1]:2375
May be not every container will work with this, but in my case (opensearch 2.6.0) it works.

@Fredrik00
Copy link

Instead of adding the hosts to daemon.json which conflicted in docker for me and failed to start (Docker version 23.0.1, build a5ee5b1). I added the hosts in the override.conf see commands below.

sudo mkdir -p /etc/systemd/system/docker.service.d
sudo vim /etc/systemd/system/docker.service.d/override.conf

# add the below to the override.conf file
[Service]
ExecStart=
ExecStart=/usr/bin/dockerd --host=tcp://0.0.0.0:2375 -- host=unix:///var/run/docker.sock

sudo systemctl daemon-reload and then sudo systemctl restart docker

This worked for me, just had to correct "-- host" to"--host" by removing the whitespace for the final argument.

@werto165
Copy link

werto165 commented Mar 6, 2024

Instead of adding the hosts to daemon.json which conflicted in docker for me and failed to start (Docker version 23.0.1, build a5ee5b1). I added the hosts in the override.conf see commands below.

sudo mkdir -p /etc/systemd/system/docker.service.d
sudo vim /etc/systemd/system/docker.service.d/override.conf

# add the below to the override.conf file
[Service]
ExecStart=
ExecStart=/usr/bin/dockerd --host=tcp://0.0.0.0:2375 -- host=unix:///var/run/docker.sock

sudo systemctl daemon-reload and then sudo systemctl restart docker

This worked for me, just had to correct "-- host" to"--host" by removing the whitespace for the final argument.

I had to add an additional --tls=false for it to work for me. Maybe a recent change?

@spyro2000
Copy link

spyro2000 commented Apr 29, 2024

Unfortunately none of this is working for me anymore (Windows 10 22H2), even with network_mode=mirrored. Netstat shows only a "tcp6" port (2375), no IPv4 version (should be "tcp" only).

Why I can reach http://localhost:2375/version via a browser, running containers from bashand DOCKER_HOST pointing to 'tcp://localhost:2375', testcontainers only logs it infamous 'no valid docker environment found' :(

@sz763
Copy link
Author

sz763 commented Apr 30, 2024

@spyro2000 I've faced with similar behavior, when Cisco Anyconnect was running. After disconnect from VPN - everything worked fine.

@gim-
Copy link

gim- commented May 18, 2024

@spyro2000 @sz763 I had exactly the same problem and managed to make it work by changing the dockerd arguments.
I replaced --host=tcp://0.0.0.0:2375 with --host=tcp://
Result:

$ netstat -nl | grep 2375
tcp        0      0 127.0.0.1:2375          0.0.0.0:*               LISTEN

Also, it seems like unencrypted HTTP connections are deprecated and, in the future, Docker engine will fail to start with disabled TLS:

WARN[2024-05-18T20:51:48.269981050+03:00] [DEPRECATION NOTICE]: API is accessible on http://localhost:2375 without encryption.
Access to the remote API is equivalent to root access on the host. Refer
to the 'Docker daemon attack surface' section in the documentation for
more information: https://docs.docker.com/go/attack-surface/
In future versions this will be a hard failure preventing the daemon from starting! Learn more at: https://docs.docker.com/go/api-security/

To make the guide more future-proof, I suggest updating it by adding additional steps to set up server certificate and client mTLS certificate.

# Set up CA
# Make sure to set Common Name (CN) to "localhost" or any other hostname you use to connect to Docker
mkdir -p /tmp/docker-certs; cd /tmp/docker-certs
openssl genrsa -aes256 -out ca-key.pem 2048
openssl req -new -x509 -days 9999 -key ca-key.pem -sha256 -out ca.pem

# Generate server certificate, CN and subject must contain a hostname you use to connect to Docker - in this example it's localhost
echo 'subjectAltName = DNS:localhost, IP:0.0.0.0, IP:127.0.0.1' > extfile.cnf
openssl genrsa -out server-key.pem 2048
openssl req -subj "/CN=localhost" -new -key server-key.pem -out server.csr
openssl x509 -req -days 9999 -in server.csr -CA ca.pem -CAkey ca-key.pem -CAcreateserial -out server-cert.pem -extfile extfile.cnf

# Generate client certificate
echo 'extendedKeyUsage = clientAuth' > extfile.cnf
openssl genrsa -out key.pem 2048
openssl req -subj '/CN=client' -new -key key.pem -out client.csr
openssl x509 -req -days 9999 -in client.csr -CA ca.pem -CAkey ca-key.pem -CAcreateserial -out cert.pem -extfile extfile.cnf

# Copy all keys and certs to /etc/docker
sudo mkdir -p /etc/docker
sudo cp *pem /etc/docker

# Make client key and certificate accessible from outside
sudo chmod 644 /etc/docker/key.pem /etc/docker/cert.pem

After all that, my Windows environment variables look like:

Name Value
DOCKER_HOST tcp://localhost:2375
DOCKER_TLS_VERIFY 1
DOCKER_CERT_PATH \\wsl$\DISTRO\etc\docker

Where DISTRO is the name of a WSL distribution you're using. You can check it by running wsl -l -v from PowerShell.

My dockerd command looks like this:

dockerd -H unix:///var/run/docker.sock -H tcp:// --tlsverify --tlscacert=/etc/docker/ca.pem --tlscert=/etc/docker/server-cert.pem --tlskey=/etc/docker/server-key.pem

You can put the same arguments to your ExecStart or daemon.json. I personally prefer running dockerd explicitly using custom executable or an alias.
With this setup, both Windows-native docker client and testcontainers work for me 🎉

Tested on:

  • Windows 10 build 19045
  • Docker version: 26.1.3
  • WSL version: 2.0.14.0

@sz763
Copy link
Author

sz763 commented May 31, 2024

@gim- thanks for contribution!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment