[WSL/Swarm] Fail to Join Docker Swarm as Worker
1. Problem
I was trying to set up a Docker Swarm environment in my home network. My plan was to run the Docker Swarm manager node in a WSL2 Ubuntu distro on my Windows laptop, and run the Docker Swarm worker node on my MacMini. Both of them have Docker Desktop installed.
When I tried to add a worker to the Swarm, I received the following error:
Error response from daemon: rpc error: code = Unavailable desc = connection error: desc = "transport: Error while dialing dial tcp 192.168.65.3:2377: connect: connection refused"
My operation is as followed below
- In WSL2 Ubuntu distro, run the command
docker swarm init
. And the output was
Swarm initialized: current node (801sn3yg746dq2h6t9isfe89x) is now a manager.
To add a worker to this swarm, run the following command:
docker swarm join --token SWMTKN-1-1c0ih56l2etekc6m4ymv7hqltala6wyxo2fmxez07m5rrr37rz-23v1bn533dzv1dxtuv2hl4h4w 192.168.65.3:2377
To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions.
- On MacMini, run the command
docker swarm join --token SWMTKN-1-1c0ih56l2etekc6m4ymv7hqltala6wyxo2fmxez07m5rrr37rz-23v1bn533dzv1dxtuv2hl4h4w 192.168.65.3:2377
. The error appeared at this step.
2. Analysis
I found that the IP addresses of each device and environment were important to understanding the problem. Here is a list of the IP addresses:
- Windows Host: 192.168.0.106
- WSL2 Ubuntu distro: 172.25.91.12
- MacMini: 192.168.0.102
Wait, the docker swarm join ...
command shows that the manager node IP address should be 192.168.65.3
. Where is it?
I realized that 192.168.65.3 is one of the IP addresses in the Docker subnet 192.168.65.0/24, which is the default setting in the Docker engine. This can be modified in Docker Desktop.
I then performed some investigations to understand the issue. I found that:
- Windows host could ping the WSL Ubuntu distro
- The command
docker node ls
on WSL Ubuntu distro showed that it could connect to the Docker subnet and the Swarm was running correctly. The output is like
ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS ENGINE VERSION
801sn3yg746dq2h6t9isfe89x * docker-desktop Ready Active Leader 20.10.21
- The command
docker node ls
on Windows host also showed that it could connect to the Docker subnet - MacMini could ping the Windows host IP
In my case, the result after above investigation can be illustrated as below:
From these investigations, I could see that the issue was that MacMini could not reach the Docker subnet.
You may wonder why both Windows host and WSL ubuntu distro can connect to the docker subnet, but it does not work for Macmini. It is because docker node ls
is a command based on docker engine and docker engine can definitely reach docker subnet. However, if you ping 192.168.65.3
on Windows host or WSL2 ubuntu distro, it will not work either.
The solution is port forwarding.
3. Solution
3.1 Solution 1: MacMini -> Windows host -> WSL Ubuntu distro -> Docker subnet
- On Windows host, open Powershell with Administrator privileges and execute the following command
netsh interface portproxy add v4tov4 listenport=2378 listenaddress=0.0.0.0 connectport=2378 connectaddress=172.25.91.12
This command creates a port proxy to forward incoming traffic on port 2378 of the Windows host to port 2378 of the WSL Ubuntu distro.
It’s important to check that the port 2378 is not being used by any application or service, before adding a proxy on it.
- In Ubuntu distro, run
docker run --rm -d -p 2378:2378 --name swarm-manager-proxy alpine/socat tcp-l:2378,fork,reuseaddr tcp:192.168.65.3:2377
This command creates a new container with the name “swarm-manager-proxy” using the alpine/socat
image, that listens on port 2378 of the host machine, and forwards any incoming traffic to port 2377 on IP address 192.168.65.3. It runs in detached mode and will be removed automatically when it exits. This command did final port forward to docker swarm interface in docker subnet
- On MacMini, run the command to join the Swarm
docker swarm join --token SWMTKN-1-1c0ih56l2etekc6m4ymv7hqltala6wyxo2fmxez07m5rrr37rz-23v1bn533dzv1dxtuv2hl4h4w 192.168.0.106:2378
Note that the ip:port
is different original one.
4. Solution 2: MacMini -> Windows Host -> Docker subnet
Another solution would be to use socat, a command-line utility that establishes two bidirectional byte streams and transfers data between them only.
- On Windows host, open the default shell and run the command
docker run --rm -d -p 0.0.0.0:2378:2378 --name swarm-manager-proxy alpine/socat tcp-l:2378,fork,reuseaddr tcp:192.168.65.3:2377
This command acts almost similar as the above one. But it’s important to notice that by using the IP 0.0.0.0, it makes the port accessible from any IP address, not just the localhost.
- On MacMini, run the join command on the MacMini
docker swarm join --token SWMTKN-1-1c0ih56l2etekc6m4ymv7hqltala6wyxo2fmxez07m5rrr37rz-23v1bn533dzv1dxtuv2hl4h4w 192.168.0.106:2378
It would make the MacMini connect to the swarm manager through the socat container running on the Windows host and join the swarm successfully.
These are the two possible solutions that I found to solve the problem of MacMini not being able to reach the Docker subnet and join the Swarm. It’s important to note that for both solution you would have to check the IP addresses and ports, and adjust them accordingly to your network configuration.
If this post helped you to solve a problem or provided you with new insights, please upvote it and share your experience in the comments below. Your comments can help others who may be facing similar challenges. Thank you!