DEV Community

Mario García
Mario García

Posted on • Updated 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)