DEV Community

Mario García
Mario García

Posted on • Edited on

Docker Swarm With Virtual Machines Using Multipass

According to the Docker documentation, Swarm mode is an advanced feature for managing a cluster of Docker daemons. Each instance of Docker Engine participating in the swarm is a node, and act as managers, to manage membership and delegation, and workers, which run swarm services. A given Docker host can be a manager, a worker, or perform both roles. You can run one or more nodes on a single physical computer or cloud server, but production swarm deployments typically include Docker nodes distributed across multiple physical and cloud machines.

In a development environment, where you probably don't have access to multiple physical devices to configure a swarm, a solution would be to create virtual machines (VMs), each of them running an instance of Docker Engine.

Last month, I wrote a tutorial about Multipass, a tool from Canonical that can be used to create Ubuntu virtual machines, and through this article, you will learn how to use it to configure the swarm. I've followed the instructions from this article, but I'll explain the general process and how you can deploy services in a swarm.

Virtual Machines

To create a virtual machine with Multipass, you would run the following command:

$ multipass launch --name node1 lunar 
Enter fullscreen mode Exit fullscreen mode

The above command would create a virtual machine, named node1, with the following characteristics:

  • 1 CPU
  • 5GB of disk
  • 1GB of RAM

Depending on the requirements of your development environment, the default configuration can be limited, and you may want to assign more resources. I suggest creating a VM with the following features if more resources are needed:

  • 2 CPUs
  • 8GB of disk
  • 2GB of RAM

I'm running tests on a computer with 4 CPUs and 12GB of RAM, and assigning the above resources to each node won't affect the normal operation of the host.

Let's create a three-node cluster.

First, create a BASH script (init-instance.sh):

NM=$1 multipass launch --name ${NM} lunar --memory 2G --disk 8G --cpus 2 multipass transfer install-docker.sh ${NM}:/home/ubuntu/install-docker.sh multipass exec ${NM} -- sh -x /home/ubuntu/install-docker.sh 
Enter fullscreen mode Exit fullscreen mode
  1. NM is the variable that will get the name of the VM from the command line
  2. Will launch a VM with custom configuration
  3. The install-docker.sh file will be transfered from the host to the VM
  4. The script that will install Docker Engine on each node

Now create the script for installing Docker Engine on each node of the swarm.

# Add Docker's official GPG key: sudo apt-get update sudo apt-get install -y ca-certificates curl gnupg sudo install -m 0755 -d /etc/apt/keyrings curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg sudo chmod a+r /etc/apt/keyrings/docker.gpg # Add the repository to Apt sources: echo \ "deb [arch="$(dpkg --print-architecture)" signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/u> "$(. /etc/os-release && echo "$VERSION_CODENAME")" stable" | \ sudo tee /etc/apt/sources.list.d/docker.list > /dev/null sudo apt-get update # Install latest version sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin # Manage Docker as a non-root user ## Create the docker group sudo groupadd docker ## Add your user to the docker group sudo usermod -aG docker $USER ## Enable the docker daemon to run on system boot sudo systemctl enable docker 
Enter fullscreen mode Exit fullscreen mode

The script will:

  • Add Docker's official GPG key
  • Add the repository to Apt resources
  • Install latest version of Docker Engine
  • Manage Docker as a non-root user
    • Create the docker group
    • Add your user to the docker group

Docker Swarm uses the overlay driver by default, and it's not supported by the rootless mode. That's why Docker must be configured following the post-installation steps.

Now run the following command to create the manager node:

$ sh -x init-instance.sh manager 
Enter fullscreen mode Exit fullscreen mode

Then, create two worker nodes:

$ sh -x init-instance.sh worker1 
Enter fullscreen mode Exit fullscreen mode
$ sh -x init-instance.sh worker2 
Enter fullscreen mode Exit fullscreen mode

The Docker Engine instances are now running.

Initialize the Swarm

The swarm must be initialized in the manager node, and the worker1 and worker2 VMs must be added to the swarm as worker nodes.

Initialized the swarm:

$ multipass exec manager -- docker swarm init 
Enter fullscreen mode Exit fullscreen mode

You'll get the following output:

Swarm initialized: current node (fgjgd7qr4yg0dnlk8nurrqk9q) is now a manager. To add a worker to this swarm, run the following command: docker swarm join --token SWMTKN-1-5d9bj8wua4wy812hzl7vqc2r54yroy227i2oqkl27k3vzxdk7e-7na4j9souwf0s2yf6tmw5daiq 10.81.157.203:2377 To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions. 
Enter fullscreen mode Exit fullscreen mode

It will give you the token and command needed to add the worker nodes to the swarm. 10.81.157.203 is the IP address assigned by Multipass to the manager VM.

Add the worker1 VM to the swarm as worker:

$ multipass exec worker1 -- docker swarm join --token SWMTKN-1-5d9bj8wua4wy812hzl7vqc2r54yroy227i2oqkl27k3vzxdk7e-7na4j9souwf0s2yf6tmw5daiq 10.81.157.203:2377 
Enter fullscreen mode Exit fullscreen mode

Add the worker2 VM to the swarm as worker:

$ multipass exec worker2 -- docker swarm join --token SWMTKN-1-5d9bj8wua4wy812hzl7vqc2r54yroy227i2oqkl27k3vzxdk7e-7na4j9souwf0s2yf6tmw5daiq 10.81.157.203:2377 
Enter fullscreen mode Exit fullscreen mode

The swarm is now configured. You can list the nodes in the swarm by running:

$ multipass exec manager -- docker node ls 
Enter fullscreen mode Exit fullscreen mode

Deploy a Service to the Swarm

Now that the swarm is configured, you can run standalone containers on each node but they won't be managed by the manager node, only services deployed to the swarm.

Let's deploy the first service, an Nginx server with three replicas.

$ multipass exec manager -- docker service create --name nginx --replicas 3 -p 80:80 nginx 
Enter fullscreen mode Exit fullscreen mode
  • The docker service create command creates the service
  • The --name flag is used to assing a name to the service, nginx
  • The --replicas flag specifies the number of replicas
  • The -p flag is used to open the port 80 in the host to receive and redirect requests to the port 80 in the container

You can check the running services with the following command:

$ multipass exec manager -- docker service ls 
Enter fullscreen mode Exit fullscreen mode

You'll get the following output:

ID NAME MODE REPLICAS IMAGE PORTS 5rflc7yq4pyg nginx replicated 3/3 nginx:latest *:80->80/tcp 
Enter fullscreen mode Exit fullscreen mode

To see which nodes are running the service, run the following command:

$ multipass exec manager -- docker service ps nginx 
Enter fullscreen mode Exit fullscreen mode

You'll get the following output:

ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS ysp4p3ut581a nginx.1 nginx:latest worker1 Running Running 6 minutes ago 7zozyfe4s8a5 nginx.2 nginx:latest worker2 Running Running 6 minutes ago njdou1bmh4tm nginx.3 nginx:latest manager Running Running 6 minutes ago 
Enter fullscreen mode Exit fullscreen mode

To display details about a service in an easily readable format, run:

$ multipass exec manager -- docker service inspect --pretty nginx 
Enter fullscreen mode Exit fullscreen mode

It will display:

ID: 5rflc7yq4pygo7kxu8pq7ev7l Name: nginx Service Mode: Replicated Replicas: 3 Placement: UpdateConfig: Parallelism: 1 On failure: pause Monitoring Period: 5s Max failure ratio: 0 Update order: stop-first RollbackConfig: Parallelism: 1 On failure: pause Monitoring Period: 5s Max failure ratio: 0 Rollback order: stop-first ContainerSpec: Image: nginx:latest@sha256:2bdc49f2f8ae8d8dc50ed00f2ee56d00385c6f8bc8a8b320d0a294d9e3b49026 Init: false Resources: Endpoint Mode: vip Ports: PublishedPort = 80 Protocol = tcp TargetPort = 80 PublishMode = ingress 
Enter fullscreen mode Exit fullscreen mode

If you want to delete the service, just type:

$ multipass exec manager -- docker service rm nginx 
Enter fullscreen mode Exit fullscreen mode

Conclusion

Through this article, you learned how to configure a swarm using virtual machines and you deploy your first service.


Support me on Buy Me A Coffee

Top comments (0)