Docker Swarn : From Newbie to Master ( part 2 )
Tags: docker, devops, beginners, webdev
Published: 2023-05-28 05:52:49

Welcome to Part 2 of this series on Docker Swarm. If you have not read the previous article, please check out my profile to find it. In this article, we will discuss the remaining Docker Swarm commands.

## **`docker service update`**

The **`docker service update`** command is used to update a running service in a Docker swarm. It can be used to change the configuration of a service, such as the number of replicas, the image used, or the environment variables.

The basic syntax of the command is as follows:

```bash
docker service update [OPTIONS] SERVICE
```

Here are some common options that can be used with the **`docker service update`** command:

- **`-replicas`**: Change the number of replicas for the service
- **`-image`**: Update the image used for the service
- **`-env-add`** and **`-env-rm`**: Add or remove environment variables for the service
- **`-force`**: Force an update of the service even if there are no changes

Here is an example of using the **`docker service update`** command to update the number of replicas for a service:

```bash
docker service update --replicas 3 my-service
```

This will change the number of replicas for the **`my-service`** service to 3.

Here is another example that updates the image used by a service:

```bash
docker service update --image my-image:latest my-service
```

This will update the image used by the **`my-service`** service to **`my-image:latest`**.

You can also use the **`--env-add`** and **`--env-rm`** options to add or remove environment variables for the service:

```bash
docker service update --env-add MY_VAR=my_value my-service
docker service update --env-rm MY_VAR my-service
```

The first command will add an environment variable **`MY_VAR`** with the value **`my_value`** to the **`my-service`** service. The second command will remove the **`MY_VAR`** environment variable from the service.

Finally, you can use the **`--force`** option to force an update of the service even if there are no changes:

```bash
docker service update --force my-service
```

This will force an update of the **`my-service`** service even if there are no changes.

<aside>
💡 The **`--force`** flag is used with the **`docker service update`** command to force the immediate update of a service even if it results in service disruption. By default, Docker Swarm will try to update a service without disrupting it by gradually updating one replica at a time. However, in certain cases, it may be necessary to force an immediate update of all replicas to ensure that the changes are applied quickly. This can be useful in situations where the new changes are critical and need to be implemented as soon as possible, even if it causes temporary service disruption.

It is important to use the **`--force`** flag with caution as it may cause service disruption and should be used only when necessary.

</aside>

## **`docker service scale`**

The **`docker service scale`** command is used to scale the number of replicas of a service in a Docker swarm.

The syntax for the command is:

```bash
docker service scale <service_name>=<replica_count>
```

Here, **`<service_name>`** is the name of the service to be scaled and **`<replica_count>`** is the new number of replicas to be set.

For example, if we have a service named **`web`** with 3 replicas and we want to scale it to 5 replicas, we can use the following command:

```bash
docker service scale web=5
```

This will update the service with the new replica count. Note that this command only works for replicated services and not for global services.

<aside>
💡 Replicated services have a specific number of replicas defined, while global services run one replica on every node in the swarm. Replicated services are useful for running a fixed number of tasks, while global services are useful for tasks that need to run on every node in the swarm, such as logging or monitoring agents.

</aside>

## **`docker service rm`**

**`docker service rm`** is a command used to remove one or more services from a Docker swarm. It stops and removes all tasks associated with the specified services. The command takes one or more service IDs or service names as arguments.

Here is an example of how to use it:

```bash
docker service rm my-service
```

This will remove the service named **`my-service`** from the swarm.

## **`docker stack deploy`**

The **`docker stack deploy`** command is used to deploy a Docker Compose file to a Swarm cluster as a stack. A stack is a group of services that are deployed together as a single unit.

Here is an example command that deploys a stack:

```bash
docker stack deploy -c docker-compose.yml mystack
```

In this command, **`docker-compose.yml`** is the name of the Docker Compose file, and **`mystack`** is the name of the stack.

The options available with the **`docker stack deploy`** command are:

- **`c`**, **`-compose-file`**: Specifies the Docker Compose file to use.
- **`-prune`**: Removes any services or containers that are not defined in the Compose file.
- **`-resolve-image`**: Forces the cluster to resolve the image name to a specific digest, rather than using the default "latest" tag.
- **`-orchestrator`**: Specifies the orchestrator to use, either "swarm" or "kubernetes".

Here is an example of deploying a stack with the **`--prune`** option:

```bash
docker stack deploy --prune -c docker-compose.yml mystack
```

This command removes any services or containers that are not defined in the Compose file.

The **`--resolve-image`** option for the **`docker stack deploy`** command is used to resolve image digest and tag to the corresponding image ID before deploying a stack.

The possible values for **`--resolve-image`** option are:

- **`always`**: This value tells Docker to always attempt to pull the image, even if a local copy exists. This can be useful if you want to make sure you're always using the latest version of an image.
- **`changed`**: This value tells Docker to only pull the image if the image's tag has changed since the last time it was pulled. This can be useful if you want to minimize network traffic and avoid unnecessary pulls.
- **`never`**: This value tells Docker to never attempt to pull the image, and to only use a local copy if it exists. This can be useful if you know that you won't need to update the image, or if you want to avoid network traffic altogether. However, be careful when using this option, as it can result in using an outdated image if a newer one is available.

Here is an example command using the **`--resolve-image`** option with the **`always`** value:

```bash
docker stack deploy --compose-file docker-compose.yml --resolve-image always myapp
```

## `docker stack ls`

The **`docker stack ls`** command is used to list all the stacks that are currently deployed on the swarm. It provides a quick summary of the deployed stack, including the name, the number of services in the stack, and the status of the stack.

Here's an example of how to use the command:

```bash
docker stack ls
```

This will output a table that lists all the deployed stacks, their number of services, and their status. Here's an example output:

```bash
NAME                SERVICES            STATUS             
my_stack            3                   * Running
```

The **`NAME`** column shows the name of the stack. The **`SERVICES`** column shows the number of services in the stack. The **`STATUS`** column shows the current status of the stack. In this example, the stack named **`my_stack`** has 3 services and is currently running.

This command is useful when you need to check the status of your deployed stacks and the number of services running in them.

## **`docker stack ps`**

The **`docker stack ps`** command is used to list the tasks or replicas of a given stack.

Here is the syntax of the command:

```bash
docker stack ps [OPTIONS] STACK_NAME
```

Where **`STACK_NAME`** is the name of the stack.

Here are some options that can be used with the **`docker stack ps`** command:

- **`-filter`**: It can be used to filter the tasks based on various parameters like desired state, node, etc.
- **`-no-trunc`**: It is used to disable truncating the output of the command.
- **`-quiet`**: It is used to display only the task IDs.

Here is an example command to list the tasks of a stack named **`my_stack`**:

```bash
docker stack ps my_stack
```

The output of **`docker stack ps`** command shows the running processes/replicas of the services in the specified stack along with their current status. It displays a table with the following columns:

- **`ID`**: The unique ID of the task.
- **`Name`**: The name of the service the task belongs to.
- **`Image`**: The Docker image used to create the task.
- **`Node`**: The hostname of the node where the task is running.
- **`Desired State`**: The desired state of the task (running or shutdown).
- **`Current State`**: The current state of the task (running, completed, or shutdown).
- **`Error`**: Any error message associated with the task, if applicable.

Here's an example output:

```bash
ID                  NAME                IMAGE                    NODE                DESIRED STATE       CURRENT STATE            ERROR
qn41eabryqw1        myapp_web.1         myapp:latest             swarm-node-1        Running             Running 2 minutes ago    
fb48n1mzsqxd        myapp_web.2         myapp:latest             swarm-node-2        Running             Running 2 minutes ago    
iz4f7ifg5ue5        myapp_worker.1      myapp-worker:latest      swarm-node-1        Running             Running 2 minutes ago    
7nzq44tigzrw        myapp_db.1          postgres:10.1            swarm-node-2        Running             Running 2 minutes ago
```

In this example, there are four tasks running for the `my_stack` stack. Two replicas of the **`myapp_web`** service are running on **`swarm-node-1`** and **`swarm-node-2`**, one replica of the **`myapp_worker`** service is running on **`swarm-node-1`**, and one replica of the **`myapp_db`** service is running on **`swarm-node-2`**.

## **`docker stack rm`**

The **`docker stack rm`** command is used to remove a Docker stack, which includes all the services and networks associated with that stack. Here is the syntax for the command:

```bash
docker stack rm [OPTIONS] STACK_NAME [STACK_NAMES...]
```

Where **`STACK_NAME`** is the name of the stack to be removed.

For example, to remove a stack named **`my_stack`**, the command would be:

```bash
docker stack rm my_stack
```

This command will remove all the services and networks associated with the **`my_stack`** stack.

There are options available for the **`docker stack rm`** command. Here are some commonly used options:

- **`-force`**: This option forces the removal of the stack even if it is currently running.
- **`-orchestrator`**: This option specifies which orchestrator to use for the removal operation. By default, the command uses the swarm mode orchestrator.
- **`-volumes`**: This option removes the volumes associated with the stack along with the stack itself.

Here's an example command that uses the **`--force`** option to forcefully remove a stack:

```bash
docker stack rm --force myapp
```

Note that this command does not remove any volumes that were created by the services in the stack. However, you can use the **`--volumes`** option to remove the volumes as well.

Here is an example command to remove a stack with associated volumes:

```bash
docker stack rm --volumes mystack
```

This will remove the **`mystack`** stack along with its associated volumes. If you do not want to remove the volumes, simply omit the **`--volumes`** option.

<aside>
💡 Just remember that docker is not going to remove any volume except anonymous volumes without your confirmation due to data loss risk

</aside>

## **`docker stack services`**

The **`docker stack services`** command is used to list the services that are running as part of a stack.

Here's the basic syntax:

```bash
docker stack services <stack_name>
```

This will display a table with the following columns:

- ID: The unique identifier of the service
- NAME: The name of the service
- MODE: Whether the service is running in **`replicated`** or **`global`** mode
- REPLICAS: The number of replicas of the service (only applicable for replicated services)
- IMAGE: The Docker image used by the service

Here's an example of how to use the command:

```bash
docker stack services myapp_stack
```

This will display a table of all the services running in the `myapp_stack` stack.

```bash
ID                  NAME                 MODE                REPLICAS            IMAGE                      PORTS
8h1fc2y1ffaz        myapp_stack_web      replicated          3/3                 myapp:latest               *:80->80/tcp
e96fa5zjdt0a        myapp_stack_redis    replicated          1/1                 redis:latest               *:6379->6379/tcp
```

## How to scale services in Docker Swarm stack?

To scale a service in a Docker stack, you can use the **`docker service scale`** command followed by the name of the service and the desired number of replicas. For example, to scale a service named **`web`** in a stack named **`my_stack`** to 5 replicas, you can use the following command:

```bash
docker service scale my_stack_web=5
```

This will create or remove replicas as necessary to ensure that there are 5 replicas of the **`web`** service running.

## Docker swarn secret

Swarm Secrets is a feature in Docker Swarm that allows users to securely store and manage sensitive data, such as passwords, authentication tokens, and other confidential information. It follows a client-server architecture, where the Docker Swarm manager node acts as the server and the worker nodes as clients.

When a secret is created, it is encrypted and stored on the manager node. The encrypted secret is then replicated to all the worker nodes that are part of the Swarm. The workers have access to the secret only when the service that requires the secret is created or updated on the worker node.

Overall, Swarm Secrets provide a secure and convenient way to manage and distribute sensitive data in a Swarm environment.

### How to use swarn secret ?

First, create a Swarm Secret using the **`docker secret create`** command:

```bash
$ echo "mysecretpassword" | docker secret create db_password -
```

This command will create a Swarm Secret named **`db_password`** with the value **`mysecretpassword`**.

When you deploy the Node.js application to a Docker Swarm using the **`docker stack deploy`** command, you can specify the Swarm Secret in the **`docker-compose.yml`** file like this:

```yaml
version: "3.7"
services:
  app:
    image: my-node-app
    secrets:
      - source: db_password
        target: /run/secrets/db_password
        mode: 0400
secrets:
  db_password:
    external: true
    file: ./db_password.txt
```

In this example, the **`secrets`** section is used to specify the **`db_password`** Swarm Secret. The **`external: true`** option tells Docker that this Secret already exists in the Swarm.

The **`secrets`** section in the **`app`** service specifies that the **`db_password`** Secret should be mounted as a file at **`/run/secrets/db_password`** inside the container. The **`mode: 0400`** option sets the permissions of the file to read-only for the owner.

When you deploy the stack using the **`docker stack deploy`** command, Docker Swarm will automatically create the necessary files and mount the Swarm Secret as a file in the container.

Here is an example of a Node.js application that uses the Swarm Secret **`db_password`**:

```bash
const fs = require('fs');

const password = fs.readFileSync('/run/secrets/db_password', 'utf8');

console.log('Database password:', password);
```

In this example, the **`fs.readFileSync`** method is used to read the **`db_password`** Swarm Secret file. The file is mounted in the container at the path **`/run/secrets/db_password`**.

<aside>
💡 In the development env just mark the`external` to `false` inside your `docker-compose.yml` file and put your database password inside the file `db_password.txt` located in the folder of `docker-compose.yml` file.

</aside>