In my previous blog I demonstrated how to setup a lightweight docker swarm environment with docker-machine. When you run this environment in the internet with real virtual machines, there can be some issues you need to take care. Anyway, these issues have cost me a lot of time. Therefore, I would like to give some hints on how to run Docker Swarm on public VMs.
The Hostname and Public IPv4
According to my previous blog, I assume that you have at least two VMs:
- VM1 will become my swarm manager node
- VM2 will become my first swarm worker node
Each of these VMs has its own public IPv4 address, [manager-ip-address] for VM1 and [worker-ip-address] for VM2. So I can ping both machines from each other and also my own local machine.
If you have a new VM, this machine maybe has no unique hostname. In this case you should first give each of your VMs a unique hostname. In my example I choose the name ‘manager1’ for VM1 and ‘worker1’ for VM2.
This change should be done in a root shell or in recovery mode, otherwise there is a risk of being locked out of the computer. The machine name must be changed in two files in a specific order. First you need to change the hostname in the/etc/hosts file:
# IPv4 127.0.0.1 localhost.localdomain localhost 172.31.1.100 manager1 .....
The IP address here (172.31.1.100) is a private address assigned to the VM. Do NOT change this IP address. Both VMs can have the same IP address here. This is typical for hosted VMs.
Now (then!) the file/etc/hostname must be adjusted. Simply enter the machines hostname here:
manager1
If this is done as a first step, you possible lock yourself out and programs can no longer start by default, because the hostname cannot be resolved!
Finally, the computer name is set by the following command:
sudo hostname -F /etc/hostname
The same changes need to be done for the worker-node with the hostname ‘worker1’.
Now you can start to setup the docker swarm.
Init the Swarm on VMs
To init the docker swarm you need the public IP addresses for the manager-node and the worker-node. You can init the docker swarm on the manager-node with the following command:
docker swarm init --advertise-addr [manager-ip-address]
where [manager-ip-address] is the public IPv4 from my VM1 running as a manager. The option ‘–advertise-add‘ is important here. The outcome of this command gives you the complete command to join VM2 from your worker-node. This command can be run on the worker-node and it will look something like this:
docker swarm join --token SWMTKN-1-xxxxxxxxxxxxxxxxxxxx-xxxxxxxx [manager-ip-address]:2377
SWMTKN is the swarm manger token and [manager-ip-address] is the public IPv4 address of my manager-node.
Now working with VMs the problem can be, that this command will register the worker node with its private IP. So as a result the swarm may not run correctly, specially in relation with overlay networks. To solve those problems you must add the public IPv4 address of your worker-node when you join the worker-node to the swarm using again the option –advertise-addr.
So the full command would look like this:
docker swarm join \ --token SWMTKN-1-xxxxxxxxxxxxxxxxxxxx-xxxxxxxx \ --advertise-addr [worker-ip-address]\ [manager-ip-address]:2377
Where [worker-ip-address] is the public IPv4 address of my VM2.
Now the worker-node has correctly joined the swarm. You can run the following command on the manage-node to list your swarm :
$ docker node ls ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS niskvdwg34551otrrnpzvgbdn * manager1 Ready Active Leader c54zgxn452225r78qp5q2vq2c worker1 Ready Active
You can now take a deeper look into the worker node with the command:
$ docker node inspect worker1
You will see the complete description of your worker-node as it is registered on the manager-node. There are two interesting parts:
.... "Description": { "Hostname": "worker1", ..... "Status": { "State": "ready", "Addr": "xx.yy.zz.zz" } ...
The Hostname and the IPv4 address should now match the name and IPv4 of your corresponding VM.
So finally the docker-swarm is up and running and docker overlay networks for cross-host communication should work.
If you have any notes or additional information, let me know.