Docker Swarn : From Newbie to Master ( part 1 )
Tags: beginners, docker, kubernetes, tutorial
Published: 2023-05-17 06:29:22

Docker Swarm is a container orchestration tool provided by Docker that allows you to create a cluster of Docker hosts and deploy services to the cluster. It allows you to manage and scale your Docker containers and services across a cluster of hosts, providing high availability and load balancing for your applications. With Docker Swarm, you can create a highly available and scalable infrastructure that can handle a large number of containerized applications.

## Why docker swarn ?

![https://media4.giphy.com/media/3cXmze4Y8igXdnkc3U/giphy.gif?cid=7941fdc6lwd7cq9cr2xfv7yfzxlae7qsv3igz4ls7kgmw9k8&ep=v1_gifs_search&rid=giphy.gif&ct=g](https://media4.giphy.com/media/3cXmze4Y8igXdnkc3U/giphy.gif?cid=7941fdc6lwd7cq9cr2xfv7yfzxlae7qsv3igz4ls7kgmw9k8&ep=v1_gifs_search&rid=giphy.gif&ct=g)

Docker Swarm provides several benefits that make it useful in certain scenarios. Here are a few reasons why someone might choose to use Docker Swarm:

1. **High availability**: Docker Swarm is designed to provide high availability of applications by automatically distributing containers across multiple nodes.
2. **Scalability**: Docker Swarm allows you to easily scale your application by adding or removing nodes.
3. **Load balancing**: Docker Swarm provides built-in load balancing to distribute traffic across multiple containers.
4. **Security**: Docker Swarm provides security features such as mutual TLS authentication and encryption for network communication.
5. **Ease of use**: Docker Swarm is easy to set up and use, especially if you are already familiar with Docker.

Overall, Docker Swarm provides an efficient and convenient way to manage and scale containerized applications in a distributed environment.

## Architecture of Docker Swarm

Docker Swarm follows a distributed and decentralized architecture with a manager-worker model. The basic components of the Swarm architecture are:

1. **Manager Nodes**: The manager nodes are responsible for managing the cluster state, scheduling tasks, and maintaining the desired state of the services. There can be multiple manager nodes in a Swarm cluster, but only one manager node is the leader at a time.
2. **Worker Nodes**: The worker nodes are responsible for running the tasks and services assigned to them by the manager nodes. There can be multiple worker nodes in a Swarm cluster.
3. **Service**: A service is a group of containers that perform the same task or function. The service is defined by a Docker Compose file or Docker service create command.
4. **Task**: A task is a container running on a worker node, which is part of a service. Each task runs a specific instance of a container image.
5. **Overlay Network**: An overlay network is a virtual network that connects the containers across different nodes in the Swarm cluster. This network allows the containers to communicate with each other seamlessly, even if they are running on different hosts.
6. **Swarm Secret**: A Swarm secret is a way to securely store sensitive data such as passwords, certificates, or API keys. The Swarm secrets are encrypted and only accessible by authorized containers in the Swarm cluster.

The Swarm manager nodes handle the orchestration of tasks and services and make sure that the desired state of the services is maintained. The worker nodes execute the tasks and services assigned to them by the manager nodes. The overlay network connects the containers across the Swarm cluster, and Swarm secrets provide a secure way to store sensitive data.

## How to create Swarn cluster ?

![https://media4.giphy.com/media/1zjfPChMwq6u6NQkSY/giphy.gif?cid=7941fdc6vhqocxf8x7dmmp4fyfyukxd770qv2e1htmj2644s&ep=v1_gifs_search&rid=giphy.gif&ct=g](https://media4.giphy.com/media/1zjfPChMwq6u6NQkSY/giphy.gif?cid=7941fdc6vhqocxf8x7dmmp4fyfyukxd770qv2e1htmj2644s&ep=v1_gifs_search&rid=giphy.gif&ct=g)

To create a Docker Swarm, you need to initialize a Swarm on one or more nodes. You can do this by running the **`docker swarm init`** command on a manager node. Here are the steps to create a Docker Swarm:

1. Choose one or more nodes to act as manager nodes. These nodes will be responsible for managing the Swarm cluster.
2. On one of the manager nodes, run the following command to initialize the Swarm:
    
    ```bash
    docker swarm init --advertise-addr <MANAGER-IP-ADDRESS>
    ```
    
    Replace **`<MANAGER-IP-ADDRESS>`** with the IP address of the manager node.
    
3. After the Swarm is initialized, the command will output a **`docker swarm join`** command that you can use to add worker nodes to the Swarm. Copy this command and run it on each worker node to join them to the Swarm.
4. Once all nodes are part of the Swarm, you can start deploying services and managing them using Docker Swarm commands.

<aside>
💡 Note: In a production environment, you should use secure communication channels and encryption for communication between the Swarm nodes. You can use TLS certificates for this purpose.

</aside>

## Some common Docker Swarm commands

Here are some of the commonly used Docker Swarm commands:

- **`docker swarm init`**: Initializes a new Swarm.
- **`docker swarm join`**: Join an existing Swarm as a node.
- **`docker node ls`**: List all the nodes in the Swarm.
- **`docker service create`**: Create a new service.
- **`docker service ls`**: List all the services running in the Swarm.
- **`docker service ps`**: List all the tasks (replicas) of a service.
- **`docker service update`**: Update an existing service.
- **`docker service scale`**: Scale a service up or down.
- **`docker service rm`**: Remove a service.
- **`docker stack deploy`**: Deploy a new stack.
- **`docker stack ls`**: List all the stacks running in the Swarm.
- **`docker stack ps`**: List all the tasks (replicas) of a stack.
- **`docker stack rm`**: Remove a stack.
- `**docker stack services**`: List all the services of given stack.

<aside>
💡 In this article, I will only discuss five Swarm commands. The remaining commands will be discussed in upcoming articles. I have invested a lot of time in this Docker Swarm series. If you find this article helpful, please consider liking and sharing it with others, and saving it for future reference.

</aside>

## `docker swarm init`

![https://media4.giphy.com/media/v9qXDRYrzhLmIPvtBs/giphy.gif?cid=7941fdc6vhqocxf8x7dmmp4fyfyukxd770qv2e1htmj2644s&ep=v1_gifs_search&rid=giphy.gif&ct=g](https://media4.giphy.com/media/v9qXDRYrzhLmIPvtBs/giphy.gif?cid=7941fdc6vhqocxf8x7dmmp4fyfyukxd770qv2e1htmj2644s&ep=v1_gifs_search&rid=giphy.gif&ct=g)

The **`docker swarm init`** command initializes a new Docker Swarm. This command should be executed on the node that you want to become the Swarm Manager. Once the Swarm Manager is initialized, you can add other nodes as Swarm Workers to the Swarm.

Here's an example command to initialize a new Docker Swarm:

```bash
$ docker swarm init --advertise-addr <MANAGER-IP-ADDRESS>
```

Here, **`<MANAGER-IP-ADDRESS>`** should be replaced with the IP address of the node that will act as the Swarm Manager. The **`--advertise-addr`** flag specifies the address that other nodes should use to communicate with the Swarm Manager.

After running the above command, you should see output similar to the following:

```bash
Swarm initialized: current node <NODE-ID> is now a manager.

To add a worker to this swarm, run the following command:

    docker swarm join --token <TOKEN> <MANAGER-IP-ADDRESS>:<MANAGER-PORT>

To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions.
```

This output indicates that the Swarm Manager has been initialized successfully. It also provides instructions on how to add other nodes as Workers or Managers to the Swarm.

The **`docker swarm init`** command generates a unique token that is used to authenticate nodes when they join the Swarm. The token is displayed in the output of the **`docker swarm init`** command and is required when joining new nodes to the Swarm.

### Here's how to reprint the join command for both worker and manager nodes.

To reprint the join command for a Docker Swarm node, you can use the following command on the manager node:

```bash
docker swarm join-token worker
```

This will print the join command for a worker node. If you want to add a manager node, you can run:

```bash
docker swarm join-token manager
```

This will print the join command for a manager node. You can copy and paste this command to the node you want to join the Swarm.

## **`docker swarm join`**

![https://media0.giphy.com/media/ckriP6xNplIXUA2CBU/giphy.gif?cid=7941fdc6mfek1aucnu15ywafffy5hlqkzub7ez0k6lmm1rxm&ep=v1_gifs_search&rid=giphy.gif&ct=g](https://media0.giphy.com/media/ckriP6xNplIXUA2CBU/giphy.gif?cid=7941fdc6mfek1aucnu15ywafffy5hlqkzub7ez0k6lmm1rxm&ep=v1_gifs_search&rid=giphy.gif&ct=g)

**`docker swarm join`** is a command used to add a worker node or a manager node to an existing swarm. The command requires a token generated by a **`docker swarm init`** command from an existing manager node. The syntax of the command is as follows:

```bash
docker swarm join --token <token> <ip-address>:<port>
```

Here, **`<token>`** is the token generated by **`docker swarm init`** command and **`<ip-address>`** and **`<port>`** is the IP address and port of the existing manager node.

Once the command is executed successfully, the node will join the swarm and can be listed using the **`docker node ls`** command.

## **`docker node ls`**

![https://media1.giphy.com/media/YLHwkqayc1j7a/giphy.gif?cid=7941fdc6a9g5gnbduk9s3b2kv2bptpi9du5w7lk53xxnuvt5&ep=v1_gifs_search&rid=giphy.gif&ct=g](https://media1.giphy.com/media/YLHwkqayc1j7a/giphy.gif?cid=7941fdc6a9g5gnbduk9s3b2kv2bptpi9du5w7lk53xxnuvt5&ep=v1_gifs_search&rid=giphy.gif&ct=g)

The **`docker node ls`** command is used to list all the nodes in the Docker Swarm. It provides information about the nodes such as their ID, hostname, status, availability, and number of running and stopped containers.

To use the **`docker node ls`** command, you need to have a Docker Swarm initialized and have at least one node joined to the Swarm

Once you have one or more nodes joined to the Swarm, you can use the **`docker node ls`** command to list all the nodes in the Swarm:

```bash
$ docker node ls
```

The output of the command includes information such as the hostname, the status of the node, the availability, the type of the node, and the number of running containers on the node. Here's an example output:

```bash
ID                            HOSTNAME            STATUS              AVAILABILITY        MANAGER STATUS      ENGINE VERSION
a95syht99niz6h15xy5gry0mp *   node-1              Ready               Active              Leader              20.10.5
9mijxl5b5nb3d2a3qzsdtnyho     node-2              Ready               Active                                  20.10.5
0xarz8pya5z5vmpgolcqd00tx     node-3              Ready               Active                                  20.10.5
```

In this example, there are three nodes in the Docker Swarm cluster, with **`node-1`** being the leader. All nodes are ready and active, and are running Docker Engine version 20.10.5.

## **`docker service create`**

![https://media3.giphy.com/media/VF7Cfau1vDMJ6cDwy1/giphy.gif?cid=7941fdc6vhqocxf8x7dmmp4fyfyukxd770qv2e1htmj2644s&ep=v1_gifs_search&rid=giphy.gif&ct=g](https://media3.giphy.com/media/VF7Cfau1vDMJ6cDwy1/giphy.gif?cid=7941fdc6vhqocxf8x7dmmp4fyfyukxd770qv2e1htmj2644s&ep=v1_gifs_search&rid=giphy.gif&ct=g)

The **`docker service create`** command is used to create a new service in a Docker Swarm. A service is a group of containers that are all running the same image and configuration, working together to provide a single application. The **`docker service create`** command allows you to specify the image, number of replicas, and other configuration options for the service.

Here is the basic syntax for the **`docker service create`** command:

```bash
docker service create [OPTIONS] IMAGE [COMMAND] [ARG...]
```

Here are some of the most commonly used options:

- **`-name`**: Sets the name of the service
- **`-replicas`**: Specifies the number of replicas of the service to create
- **`-publish`**: Publishes a container's port to the host
- **`-mount`**: Mounts a volume to the service
- **`-env`**: Sets environment variables for the service
- **`-network`**: Specifies the network to use for the service
- `**-label**` :  Sets the label of the service

Here is an example command that creates a new service called **`web`**:

```bash
docker service create --name web --replicas 3 --label mylabel=myvalue --publish published=8080,target=80 nginx:latest
```

This command creates a new service called **`web`** that runs the **`nginx:latest`** image with 3 replicas, publishes port 80 in the container to port 8080 on the host, and uses the default network for the service with label **`mylabel`** as the label key, and **`myvalue`** as the label value.

### How to add env variables from the file ?

To add environment variables from a file while creating a Docker service, you can use the **`--env-file`** option with the **`docker service create`** command.

Here's an example command that creates a service and sets environment variables from a file named **`myenv.list`**:

```bash
docker service create --name myservice --env-file myenv.list myimage:tag
```

The **`myenv.list`** file should contain one environment variable per line, in the format **`VARNAME=value`**. For example:

```bash
DB_HOST=db.example.com
DB_PORT=5432
```

These environment variables will be passed to the container when it is started as part of the service.

## **`docker service ls`**

![https://media4.giphy.com/media/SRkVigbErPKC5KW2VG/giphy.gif?cid=7941fdc6a9g5gnbduk9s3b2kv2bptpi9du5w7lk53xxnuvt5&ep=v1_gifs_search&rid=giphy.gif&ct=g](https://media4.giphy.com/media/SRkVigbErPKC5KW2VG/giphy.gif?cid=7941fdc6a9g5gnbduk9s3b2kv2bptpi9du5w7lk53xxnuvt5&ep=v1_gifs_search&rid=giphy.gif&ct=g)

The **`docker service ls`** command is used to list all the services running in the swarm. It provides a tabular view of the services, including the service ID, name, mode, replicas, image, and ports.

Here's an example output of the command:

```bash
ID             NAME          MODE         REPLICAS   IMAGE                 PORTS
bwv5f5m5wmlz   web           replicated   3/3        nginx:latest          *:80->80/tcp
ui01bmy5ue5m   api           replicated   2/2        myapp/api:latest      *:8080->8080/tcp
3bxq77hqlfjf   db            replicated   1/1        mysql:latest          *:3306->3306/tcp
```

This output shows three services running in the swarm: **`web`**, **`api`**, and **`db`**. The **`REPLICAS`** column shows the number of replicas for each service, and the **`PORTS`** column shows the published ports for each service. 

To check the current number of replicas for a service, you can look at the **`REPLICAS`** column. In the example above, the `web` service has been configured to run 3 replicas, and all 3 are currently running and also**`PORTS`** column shows that the container's port 80 is being published on the host's port 80.

There are several options available for the **`docker service ls`** command. Here are some commonly used ones:

- **`-filter`**: Allows you to filter the services based on various criteria such as service name, label, mode, etc.
    
    Suppose we want to filter the list of services by the label **`com.example.description=web service`**. We can use the **`--filter`** option as follows:
    
    ```bash
    $ docker service ls --filter label=com.example.description=web service
    ```
    
    This command will list all the services that have the label **`com.example.description`** set to **`web service`**.
    
- **`-format`**: Specifies the format of the output. You can choose from several predefined formats or create your own custom format.
    
    Suppose we want to display only the service name and the number of replicas, and we want to use a custom output format. We can use the **`--format`** option as follows:
    
    ```bash
    $ docker service ls --format "table {{.Name}}\t{{.Replicas}}"
    ```
    
    This command will list all the services and display the service name and the number of replicas in a table format. The output will look something like this:
    
    ```bash
    NAME        REPLICAS
    web         3/3
    api         2/2
    database    1/1
    ```
    
    In the **`--format`** option, we use the **`table`** format and specify the columns we want to display using the Go template syntax (**`{{.Name}}`** and **`{{.Replicas}}`**). The **`\t`** character is used to separate the columns with a tab.
    
- **`-quiet`** or **`q`**: Only displays the IDs of the services.
- **`-no-trunc`**: Displays the full service ID instead of truncating it.

## **`docker service ps`**

![https://media0.giphy.com/media/EqHkOQNczxpPRYNq6F/giphy.gif?cid=7941fdc6cxeq087hyziizq06hmek7d548zcg6v01h5ya6cr5&ep=v1_gifs_search&rid=giphy.gif&ct=g](https://media0.giphy.com/media/EqHkOQNczxpPRYNq6F/giphy.gif?cid=7941fdc6cxeq087hyziizq06hmek7d548zcg6v01h5ya6cr5&ep=v1_gifs_search&rid=giphy.gif&ct=g)

The **`docker service ps`** command shows the running tasks for a given service. Each task represents a container running a service on a swarm node.

Here's how to use the **`docker service ps`** command:

```bash
docker service ps <service_name>
```

For example, if we have a service named **`webapp`**, we can list its tasks using the following command:

```bash
docker service ps webapp
```

The output will show information about the tasks running for the service, including the container ID, the node it's running on, the service replica number, and its current status.

Here's an example output:

```bash
ID                  NAME                IMAGE               NODE                DESIRED STATE       CURRENT STATE           ERROR               PORTS
e9y2pr5z6nca        webapp.1            nginx:latest        node1               Running             Running 5 minutes ago                       
6f9cgm91swxc        webapp.2            nginx:latest        node2               Running             Running 5 minutes ago                       
3f6ap9q6ghor        webapp.3            nginx:latest        node3               Running             Running 5 minutes ago
```

We can also use the **`--format`** option to display specific information about each task in a custom format. For example, to display the task ID and the node it's running on, we can use the following command:

```bash
docker service ps --format "Task ID: {{.ID}} Node: {{.Node}} " webapp
```

The output will show the task ID and the node it's running on for each task in the **`webapp`** service:

```bash
Task ID: e9y2pr5z6nca Node: node1 
Task ID: 6f9cgm91swxc Node: node2 
Task ID: 3f6ap9q6ghor Node: node3
```

We can also use the **`--filter`** option to display only the tasks that match certain criteria. For example, to display only the tasks that are currently running, we can use the following command:

```bash
docker service ps --filter "desired-state=running" webapp
```

The output will show only the tasks that are currently running for the **`webapp`** service:

```bash
ID                  NAME                IMAGE               NODE                DESIRED STATE       CURRENT STATE            ERROR               PORTS
e9y2pr5z6nca        webapp.1            nginx:latest        node1               Running             Running 5 minutes ago                        
6f9cgm91swxc        webapp.2            nginx:latest        node2               Running             Running 5 minutes ago                        
3f6ap9q6ghor        webapp.3            nginx:latest        node3               Running             Running 5 minutes ago
```

There are many values that can be used with the **`--filter`** flag in the **`docker service ps`** command to filter the output. Here are some common ones:

- `id` : The `id` filter matches on all or a prefix of a task’s ID.
    
    ```bash
    docker service ps -f "id=8" redis
    ```
    
    Output of this command will look something like this  : 
    
    ```bash
    
    ID             NAME      IMAGE        NODE      DESIRED STATE  CURRENT STATE      ERROR  PORTS
    8ryt076polmc   redis.4   redis:3.0.6  worker1   Running        Running 9 seconds
    8eaxrb2fqpbn   redis.10  redis:3.0.6  manager1  Running        Running 8 seconds
    ```
    
- name : The `name` filter matches on task names
    
    ```bash
    docker service ps -f "name=redis.1" redis
    ```
    
    Output of this command will look something like this  : 
    
    ```bash
    
    ID            NAME     IMAGE        NODE      DESIRED STATE  CURRENT STATE      ERROR  PORTS
    qihejybwf1x5  redis.1  redis:3.0.6  manager1  Running        Running 8 seconds
    ```
    
- node : The `node` filter matches on a node name or a node ID.
    
    ```bash
    docker service ps -f "node=manager1" redis
    ```
    
    Output of this command will look something like this :
    
    ```bash
    
    ID            NAME      IMAGE        NODE      DESIRED STATE  CURRENT STATE      ERROR  PORTS
    0qihejybwf1x  redis.1   redis:3.0.6  manager1  Running        Running 8 seconds
    1x0v8yomsncd  redis.5   redis:3.0.6  manager1  Running        Running 8 seconds
    3w1wu13yupln  redis.9   redis:3.0.6  manager1  Running        Running 8 seconds
    8eaxrb2fqpbn  redis.10  redis:3.0.6  manager1  Running        Running 8 seconds
    ```
    
- desired-state : The `desired-state` filter can take the values `running`, `shutdown`, or `accepted`

That's it for this article. If you found it useful, please share it with your friends and save it for future reference. In the next article, we will discuss remaining command. See you in the next one!