# Containerization with Docker-3

# What is Docker-Swarm?

Docker Swarm is a **native clustering solution** for Docker. It turns a pool of Docker hosts into a single, virtual Docker host.

It is a tool for creating and managing a cluster of Docker nodes. It allows users to create a swarm(a bunch) of Docker engines, and then deploy and manage services across the swarm. It provides features such as service discovery, load balancing, and rolling updates. It is intended for production use and is a more robust solution for scaling and managing large-scale applications.

# Why Docker-Swarm

As we are all aware of running docker containers and hosting our application inside it, however, there is a downside to it. Docker containers always stay exposed which means anyone who is accessible to the server can perform `docker ps` and can get the container id and can perform `docker kill` and the container is dead.

Due to the above feature of docker containers, it is not directly used in production. So, to fill this gap we have the tool Docker-Swarm. It has the **Auto Healing** capability which removes the fear of **container termination**, whenever any container is terminated or killed due to any *external or internal* reason, it makes the container live again.

**NB:** You do not need to install docker swarm explicitly, it comes as native however if you are going with Kubernetes(A similar tool as Docker Swarm) you need to install it explicitly.

## Docker-Swarm Architecture

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1674354027147/3abbebd5-a1f1-4ec3-ab52-5e05cffa9765.png align="left")

**Docker Node:** It is the Docker Engine instance included in Docker swarm, has  two kinds:

* **Manager Node:** Responsible for all orchestration and container management tasks required to maintain the system in the desired state such as maintaining the cluster state, scheduling the services and servicing the swarm mode HTTP endpoints. It not only manages other nodes, it also runs a container itself as well.
    
* **Worker Node:** There will be multiple worker nodes and only one manager node. The responsibility of these worker nodes is only to execute the task given by the manager node.
    
* **Task:** They are the docker containers that execute commands.
    
* **Docker Service:** It is the task definition that needs to be executed.
    

# Hands-on Illustration of end to end App deployment through Docker-Swarm

### Step-1(Lunching required instance)

Create at least 3 or more EC2 instances naming one of them as Swarm-Manager (you can keep names of your choice but make sure you can differentiate).

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1674361711243/044d07ff-3aa8-4c17-9f00-7f7f76d0f926.png align="left")

`docker --version` : make sure docker is installed in all the servers else install them by `sudo apt install docker.io -y` .

Until now we have just pinned up servers but the swarm is not yet initiated.

### Step-2(Initiating Swarm)

To make the **Swarm-Manager instance** function as a manager, we need to initiate a docker swarm. Without initiating a swarm, it is just an ordinary instance and can't work as Swarm Manager.

`sudo docker swarm init` this command is used to initiate an empty swarm in the manager instance. No services are running yet in the swarm-manager server.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1674362192431/38637805-0714-4947-a32c-d4add51d49be.png align="left")

### Step-3(Checking Node Status)

`sudo docker node ls` this command lets us know how many nodes are currently active along with their hostname, status, availability, manager status, engine version. In the below picture you can see currently is only one node available which is the manager(Leader) node itself because until now we have just initiated a swarm in the manager-named server.

**NB:** In which server swarm is initiated will be stated as **Leader.**

**Manager Status** denotes whether it's leader or worker.

**Engine Version** denotes the version of the docker engine.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1674362620612/d1788b0d-65f0-44ea-8a57-4c668717c114.png align="left")

### Step-4(Setting inbound rule of worker nodes)

As we saw that we have already created the leader node and worker nodes.

However, the worker nodes are not yet allowed to get connected to the leader node and to do so we need to add port ***2377*** to each **worker node** because you can see in the below picture when we initiated the leader node, a token is generated at the port number **2377** via which workers will join the swarm leader.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1674363809410/0b959d67-342a-483e-9714-dcb13b1a7dfa.png align="left")

Now to open port 2377 we need to edit the inbound rule and add a custom TCP port as 2377 in all the worker nodes as below:

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1674364082679/e5baa869-5900-4195-8ed1-c8b76ddc63fb.png align="left")

### Step-5(Joining the Workers with Leader)

`sudo docker swarm join --token SWMTKN-1-00q69wz79mh97xehfahdmt1708kv6f05x9xeqkb4hfqr1h5ctb-b39hpd73cy4hm0z55aw3xymi6 172.31.88.57:2377`

`docker swarm join` followed by `--token` and generated token(in this case `SWMTKN-1-00q69wz79mh97xehfahdmt1708kv6f05x9xeqkb4hfqr1h5ctb-b39hpd73cy4hm0z55aw3xymi6 172.31.88.57:2377` ) is the command that will make the workers join the leader node.

Once you hit the above command in each worker node it will let them join the leader as below.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1674364792865/7d4e5047-9bca-4698-b750-cc5b9d91ac44.png align="center")

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1674364686049/bbbe26ce-5907-47f4-825f-39af5d8f8173.png align="center")

Now both worker servers have joined the leader.

**NB:** `sudo docker swarm join-token worker` can be used to see the token if you missed the token by any chance

### Step-6(Cross checking if workers are added)

Again by commanding `sudo docker node ls` in the **manager** node we can see workers are added as below:

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1674365108217/560b8644-930e-4d7a-82c7-0b9ed5647843.png align="left")

**NB:** `sudo docker info` gives you complete information of the docker engine as below:

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1674365892226/e3322a92-c112-4054-9654-d1425d216a6c.png align="left")

Above you can see `Is Manager: true` because I have shown the docker info of the leader node. Similarly, in the worker servers, it will be `Is Manager: false` .

### Step-7(Service Creation for the web app)

`sudo docker service create --name node-todoApp-Service --replicas 3 --publish 8000:8000 ritesh1999/node-todo:latest`

Through the above command, we are creating a service named as `node-todo-appService` with `--replicas 3` 3 replicas were created for 3 servers including the leader.

Exposing port 8001 by `--publish 8000:8000`

Now, you can see in the below picture that a service named `node-todoApp-Service` has been created as well as respective containers

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1674367829775/7881e61d-2f2e-4c66-bac7-6e7c9780aff0.png align="left")

`sudo docker service ls` gives the number of active services along with their details such as name, mode and replica count in the leader node as below. Here 3/3 replica means that 3 services are created in the linked worker including the leader:

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1674368026302/3bd467d2-18ef-468e-a0c9-24ce505ad422.png align="center")

### Step-8(Verifying in worker nodes)

Using the command `sudo docker ps` in the **worker nodes,** we can see that a container is running with the name **node-todoApp-Service**

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1674368386257/46dda60e-9d5b-4db0-9fd9-4b21ffc18f59.png align="left")

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1674368457621/84ed2095-4e80-400c-89fd-77c76bf09da1.png align="left")

### Step-9(Accessing the application from browser)

**Manager Server:**

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1674368902036/9a94c6bc-5ae4-421c-afc3-89804aa53f9e.png align="left")

**Worker-1 Server:**

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1674368953552/9c59eb9c-1df1-4ee2-844a-7622158eff76.png align="left")

**Worker-2 Server**

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1674369016979/8dd6ddcf-6538-4d40-8320-ace87ffa5b48.png align="left")

**Important: Killing the container doesn't impact it because the service will auto-heal it but Killing the Service impacts it.**

## Leaving the Swarm

`sudo docker swarm leave` will detach a node from the swarm along with it all the container and running services will be erased and the app on that particular IP will be terminated.

**NB:** The leader can remove any worker and the worker can remove by itslef.

**Worker-1 Leaving the Swarm**

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1674369676360/3c7be912-932b-4186-831f-ee0593f05773.png align="left")

**Application on the IP 54.152.114.206 will shut down**

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1674369770399/8ca94025-2703-4565-90a0-37dcb53c2814.png align="left")

### Removing the Service

`sudo docker service rm wj6t2w0spj3u(service ID)` is used to remove the service which will kill all the containers in all the nodes.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1674373999568/b435ec56-d750-4654-88dc-4eaa6bdd40b3.png align="left")

# Docker Stack

Docker Stack is a feature in Docker that allows you to deploy and manage multi-container applications using a single command. It uses a Compose file, which is a YAML file that defines the services, networks, and volumes for the application. The `docker stack deploy` the command is used to deploy the application to a swarm, which is a group of Docker engines that are configured to work together as a single virtual system. This allows you to easily scale and manage the application in a production environment.

# Creating the Stack from YAML

### Step-1(Writing a YAML file for deployment configuration)

The below YAML file contains all the details of services, versions and ports that we generally require to run a docker service.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1674374404548/187759e3-e702-4630-9058-4e1435135ca6.png align="left")

The above YAML file should be stored in **the Leader** node as the build will start from the leader.

### Step-2(Running the deployment file to build the stack)

`sudo docker stack deploy -c todoAppCluster.yaml todo-Stack` this command is used to build the stack from the file

Here `todoAppCluster.yaml` refers to the deployment configuration file and `todo-Stack` refers to the name of the stack.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1674375112304/f0728d38-d381-4ac5-8b1c-82c07002a604.png align="left")

Now, as the above picture shows :

`Creating network` : it means a connection is being established among the containers to communicate.

`Creating service` : All the services mentioned in the **YAML** file such as todo-***Stack\_todo-app*** and ***todo-Stack\_mysql-db*** are being created.

### Step-3(Verifying if the list of services)

`sudo docker service ls` will show the list of services. In the below picture, we can see both the service todo-app and mysql-db have been running successfully.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1674375400500/70f21ffb-7b15-4786-9fa4-2fc97f7421f5.png align="center")

### Step-4(Verifying if the services are running properly)

Below you can see, we ran the YAML in the manager server but the containers are up on **worker 1.** This is the beauty.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1674376096727/d20a3a58-a550-4064-9948-ef16bfd60d2c.png align="center")

## Scaling a particular service(Replicating a particular service)

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1674378717076/a0a0f8c4-56b9-492d-9a3f-4b93f52e937c.png align="center")

Let's consider the above scenario, where mysql-db is unable to scale properly as the replicas are not formed.

In some scenarios, if a server is down and we want to scale the service up then or if our customer base increases and we want to scale a service we can do it as follows:

`sudo docker service scale todo-Stack_mysql-db=3` helps to scale the sql-db and `sudo docker service scale todo-Stack_todo-app=3` helps to scale todo-app. And each service will have 3 replicas.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1674377223335/3094f749-c0f3-43ef-94b8-a985de1a5edf.png align="left")

### Service Logs

`sudo docker service logs todo-Stack_mysql-db(ServiceName)` : it gives the logs of a particular service which helps you to debug any issue, provisioning services etc as below where our SQL-db failed due to missing environment variables which we will debug by removing the entire stack going forward.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1674377688616/cb528ec5-cd67-4d83-b0db-c81b4a25c5f5.png align="left")

## Removing a Stack

`sudo docker stack rm todo-Stack` : Is used to remove a complete stack which will erase everything that was built with that stack.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1674378235041/855c9368-a620-4303-bc51-ed5fb8743177.png align="left")

Now, if we do `sudo docker service ls` it will show nothing because all the services has been removed as we removed the stack as below:

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1674378327909/0434e53a-f277-4c9e-9e2d-be6f9f773fb0.png align="left")
