# Docker Swarm

# Docker Swarm vs Kubernetes: A Practical Comparison

<div class="dark bg-primary-hero" id="bkmrk-link%3A-https%3A%2F%2Fbetter" style="text-align: justify;"><div class="mx-auto pt-4 pb-8 px-7 max-w-[1130px]"><div class="pt-10 md:pt-16 lg:pt-20"><div class="mt-4 flex justify-center text-base flex-wrap">Link: [https://betterstack.com/community/guides/scaling-docker/docker-swarm-kubernetes/](https://betterstack.com/community/guides/scaling-docker/docker-swarm-kubernetes/)</div><div class="mt-4 flex justify-center text-base flex-wrap"></div><div class="mt-4 flex justify-center text-base flex-wrap">[Docker](https://betterstack.com/tag/docker?utm_content&utm_medium=guides&utm_source=community&utm_term=docker-swarm-kubernetes)[Docker Swarm](https://betterstack.com/tag/docker-swarm?utm_content&utm_medium=guides&utm_source=community&utm_term=docker-swarm-kubernetes)[Kubernetes](https://betterstack.com/tag/kubernetes?utm_content&utm_medium=guides&utm_source=community&utm_term=docker-swarm-kubernetes)</div><div class="mt-10 md:mt-16 mt-20 text-center"><div class="text-white">Donald Le</div><div class="mt-1 uppercase whitespace-nowrap text-xs font-medium text-neutral-300 tracking-[1.56px]">Updated on December 22, 2023</div></div></div></div></div>###### Contents

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-what-is-docker-swarm" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="sticky hidden xl:block mr-12 shrink-0 w-[190px]" data-toc-target="toc"><div class="text-base text-secondary sticky scroll-smooth overflow-y-auto pretty-scrollbars max-h-screen top-[100px] pb-40"><div class="table-of-contents flat">- [What is Docker Swarm?](https://betterstack.com/community/guides/scaling-docker/docker-swarm-kubernetes/#what-is-docker-swarm)
- [What is Kubernetes?](https://betterstack.com/community/guides/scaling-docker/docker-swarm-kubernetes/#what-is-kubernetes)
- [Comparing Docker Swarm and Kubernetes](https://betterstack.com/community/guides/scaling-docker/docker-swarm-kubernetes/#comparing-docker-swarm-and-kubernetes)
- [Prerequisites](https://betterstack.com/community/guides/scaling-docker/docker-swarm-kubernetes/#prerequisites)
- [Setting up the demo application](https://betterstack.com/community/guides/scaling-docker/docker-swarm-kubernetes/#setting-up-the-demo-application)
- [Deploying the application with Docker Swarm](https://betterstack.com/community/guides/scaling-docker/docker-swarm-kubernetes/#deploying-the-application-with-docker-swarm)
- [Deploying the application with Kubernetes](https://betterstack.com/community/guides/scaling-docker/docker-swarm-kubernetes/#deploying-the-application-with-kubernetes)
- [Use cases of Kubernetes vs. Docker Swarm](https://betterstack.com/community/guides/scaling-docker/docker-swarm-kubernetes/#use-cases-of-kubernetes-vs-docker-swarm)
- [Final thoughts](https://betterstack.com/community/guides/scaling-docker/docker-swarm-kubernetes/#final-thoughts)

</div></div></div><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content">  
</div></div></div></div>In the world of container orchestration, two prominent platforms have emerged as leaders: [Docker Swarm](https://betterstack.com/community/guides/scaling-docker/ha-docker-swarm/) and [Kubernete](https://kubernetes.io/). As organizations increasingly adopt containerization to achieve scalability, resilience, and efficient resource utilization, choosing between these two solutions becomes crucial.

This article will compare both platforms, exploring their features, strengths, and trade-offs. By understanding their differences and use cases, you will gain valuable insights to select the ideal container orchestration tool for your specific needs.

We will examine various aspects, including installation and setup, container compatibility, scalability, high availability, networking, ease of use, ecosystem, and security. Through practical hands-on example, you will get a taste of how each platform tackles common challenges in deploying and managing containerized applications.

Whether you are new to container orchestration or seeking to transition from one platform to another, this article aims to provide comprehensive knowledge to make an educated choice. By the end, you be well-equipped to decide which option aligns best with your requirements and goals.

Without any further ado, let's learn what Docker Swarm is first.

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-centralize-%26-visuali" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content">Centralize &amp; visualize your logs. Query everything with SQL. <div>[<button class="block px-3 py-2 bg-neutral-700 rounded font-medium text-white leading-none whitespace-nowrap">Explore more</button>](https://betterstack.com/telemetry?utm_content=upsell&utm_medium=guides&utm_source=community&utm_term=docker-swarm-kubernetes)</div></div></div></div></div>## What is Docker Swarm?

Docker Swarm is a container orchestration tool for managing and deploying applications using a containerization approach. It allows you to create a cluster of Docker nodes (known as a Swarm) and deploy services to the cluster. Docker Swarm is lightweight and straightforward, allowing you to [containerize and deploy your software project in minutes](https://betterstack.com/community/guides/scaling-docker/ha-docker-swarm/).

To manage and deploy applications efficiently, Docker Swarm offers the following capabilities:

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-cluster-management%3A-" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content">- **Cluster Management**: You can create a cluster of nodes to manage the application containers. A node can be a manager or a worker (or both).
- **Service Abstraction**: Docker Swarm introduces the "Service" component, which lets you set the network configurations, resource limits, and number of container replicas. By managing the services, Docker Swarm ensures the application's desired state is maintained,
- **Load Balancing**: Swarm offers built-in load balancing, which allows services inside the cluster to interact without the need for you to define the load balancer file manually.
- **Rolling Back**: Rolling back to a specific service to its previous version is fully supported in case of a failed deployment.
- **Fault Tolerance**: Docker Swarm automatically checks for failures in nodes and containers to generate new ones to allow users to keep using the application without noticing any problems.
- **Scalability**: With Docker Swarm, you have the flexibility to adjust the number of replicas for your containers easily. This allows you to scale your application up or down based on the changing demands of your workload.

</div></div></div></div>### Docker Swarm architecture

Below is the diagram representing Docker Swarm Architecture:

[![image.png](https://capacita.multiautomacoes.com.br/uploads/images/gallery/2026-03/scaled-1680-/image.png)](https://capacita.multiautomacoes.com.br/uploads/images/gallery/2026-03/image.png)

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk--1" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"></div></div></div></div>In summary, the Swarm cluster consists of several vital components that work together to manage and deploy containers efficiently:

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-manager-nodes-are-re" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content">1. Manager nodes are responsible for receiving client commands and assigning tasks to worker nodes. Inside each manager node, we have the Service Discovery and Scheduler component. The former is responsible for collecting information on the worker nodes, while the latter finds suitable worker nodes to assign tasks to.
2. Worker nodes are solely responsible for executing the tasks assigned by a manager node.

</div></div></div></div>In the above diagram, the deployment steps typically work like this:

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-the-client-machines-" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content">- The client machines send commands to a manager node, let's say to deploy a new PostgreSQL database to the Swarm cluster.
- The Swarm manager finds the appropriate worker node to assign tasks for creating the new deployment.
- Finally, the worker node will create new containers for the PostgreSQL database and manage the containers' states.

</div></div></div></div>Now that you've understood what Docker Swarm is and how it works let's learn about Kubernetes.

## What is Kubernetes?

Kubernetes is a container orchestration tool for managing and deploying containerized applications. It supports a wide variety of container runtimes, including Docker, Containerd, Mirantis, and others, but the most commonly used runtime is Docker. Kubernetes is feature-rich and highly configurable, which makes it ideal for deploying complex applications, but it requires a steep learning curve.

Some of the key features of Kubernetes are listed below:

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-container-orchestrat" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content">- **Container Orchestration with Pods**: A pod is the smallest and simplest deployment unit. Kubernetes allows you to deploy applications by creating and managing one or more containers in pods.
- **Service Discovery**: Kubernetes allows containers to interact with each other easily within the same cluster.
- **Load Balancing**: Kubernetes' load balancer allows access to a group of pods via an external network. Clients from outside the Kubernetes cluster can access the pods running inside the Kubernetes cluster via the balancer's external IP. If any of the pods in the group goes down, client requests will automatically be forwarded to other pods, allowing the deployed applications to be highly available.
- **Automatic Scaling**: [You can scale-in or scale-out your application](https://betterstack.com/community/guides/scaling-docker/administer-docker-swarm/) by adjusting number of deployed containers based on resource utilization or custom-defined metrics.
- **Self-Healing**: If one of your pods goes down, Kubernetes will try to recreate that pod automatically so that normal operation is restored.
- **Persistent Storage**: It provides support for various storage options, allowing you to persist data beyond the lifecycle of individual pods.
- **Configuration and Secrets Management**: Kubernetes allows you to store and manage configuration data and secrets securely, decoupling sensitive information from the application code.
- **Rolling back**: If there's a problem with your deployment, you can easily transition to a previous version of the application.
- **Resource Management**: With Kubernetes, you can flexibly set the resource constraints when deploying your application.
- **Extensibility**: Kubernetes has a vast ecosystem and can be extended with numerous plugins and tools for added functionality. You can also interact with Kubernetes components using Kubernetes APIs to deploy your application programmatically.

</div></div></div></div>### Kubernetes architecture

[![image.png](https://capacita.multiautomacoes.com.br/uploads/images/gallery/2026-03/scaled-1680-/zSnimage.png)](https://capacita.multiautomacoes.com.br/uploads/images/gallery/2026-03/zSnimage.png)

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk--3" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"></div></div></div></div>The above diagram illustrates the Kubernetes architecture. It contains the following components:

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-control-plane%3A-this-" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content">- **Control Plane**: This is a set of components responsible for managing the operation of a Kubernetes cluster. The main components of the Kubernetes control plane are: 
    - Kube API Server: Provides an interface to interact with the Kubernetes cluster. It exposes the Kubernetes API so that clients from outside the cluster can communicate and control it.
    - Etcd: It is a distributed key-value store for storing configuration data and the desired state of the cluster.
    - Scheduler: It decides where to place newly created pods within the cluster based on resource requirements, node availability, and other defined rules. It also continuously monitors the cluster's resources to balance the workload across nodes.
    - Kube Controller Manager: It is responsible for managing and maintaining the desired state of various Kubernetes components such as pods, services, or volumes. It continuously checks the state of Kubernetes components, whether they match expectations or not. If they don't, the controller-manager will take action to restore order to the problematic components.
- **Kubernetes node**: The Kubernetes node (which could be a physical or virtual machine) is responsible for executing the tasks assigned by the control plane. Here are the main components and concepts related to Kubernetes' nodes:
    
    
    - Kubelet: The Kubelet is an agent that runs on each node and manages the containers and their lifecycle. It communicates with the control plane, receives instructions about which containers to run, and ensures that the containers are in the desired state. The Kubelet also monitors the health of the containers and reports their status back to the control plane.
    - Pod: Kubernetes pod is the smallest component of Kubernetes cluster. It represents a single instance of a running process in the cluster. Inside a pod you have the container runtime, which is responsible for pulling container images from a registry, creating container instances, and managing their execution.

</div></div></div></div>In the Kubernetes architecture diagram above, the execution steps work like this:

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-the-client-from-outs" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content">- The client from outside the Kubernetes cluster will interact with the cluster by executing `kubectl` command to the Kubernetes controller plane.
- The controller plane will assign deployment tasks to the Kubernetes Node.
- The Kubernetes node will create new pods with container runtime for the container execution.
- To allow users outside the cluster to interact with the deployed app, the client sends requests to the Kubernetes control plane to create a load balancer.
- Finally, users can interact with the deployed application via the load balancer IP Address.

</div></div></div></div>Now that you understand what Kubernetes is, let's continue to the next section to learn the differences between Docker Swarm and Kubernetes.

## Comparing Docker Swarm and Kubernetes

Although Docker Swarm and Kubernetes offer the capabilities to orchestrate containers, they are fundamentally different and serve different use cases.

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-criteria-docker-swar" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="table-container"><table><thead><tr><th>Criteria</th><th>Docker Swarm</th><th>Kubernetes</th></tr></thead><tbody><tr><td>Installation and setup</td><td>Easy to set up using the `docker` command</td><td>Complicated to manually set up the Kubernetes cluster</td></tr><tr><td>Types of containers they support</td><td>Only works with Docker containers</td><td>Supports Containerd, Docker, CRI-O, and others</td></tr><tr><td>High Availability</td><td>Provides basic configuration to support high availability</td><td>Offers feature-rich support for high availability</td></tr><tr><td>Popularity</td><td>Popular</td><td>Popular</td></tr><tr><td>Networking</td><td>Support basic networking features</td><td>Advanced features support for networking</td></tr><tr><td>GUI support</td><td>Yes</td><td>Yes</td></tr><tr><td>Learning curve</td><td>Easy to get started</td><td>Requires a steeper learning curve</td></tr><tr><td>Complexity</td><td>Simple and lightweight</td><td>Complicated and offer a lot of features</td></tr><tr><td>Load balancing</td><td>Automatic load-balancing</td><td>Manual load-balancing</td></tr><tr><td>CLIs</td><td>Do not need to install other CLI</td><td>Need to install other CLIs such as `kubectl`</td></tr><tr><td>Scalability</td><td>Does not support automatic scaling</td><td>Supports automatic scaling</td></tr><tr><td>Security</td><td>Only supports TLS</td><td>Supports RBAC, SSL/TLS, and secret management</td></tr></tbody></table>

</div></div></div></div></div>### Setup and installation

Regarding installation and setup, Docker Swarm is easier to set up than Kubernetes. Assuming Docker is already installed, you only need to run `docker swarm init` to create the cluster, then attach a node to the cluster using `docker swarm join`.

The steps for setting up a Kubernetes cluster are not as straightforward without using cloud platforms. However, there are some tools ease the process such as Kubeadm, or Kubespray. For example, to create a new cluster using Kubeadm you need to:

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-set-up-the-docker-ru" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content">- Set up the Docker runtime on all the nodes.
- Install Kubeadm on all the nodes.
- Initiate Kubernetes Control Plane on the master node.
- Install the network plugin.
- Join the worker node to the master node.
- Using `kubectl get node` to check whether all the nodes are added to the Kubernetes cluster.

</div></div></div></div>### Types of containers they support

Docker Swarm only supports Docker containers, but Kubernetes supports any container runtime that implements its [Container Runtime Interface<span class="whitespace-nowrap"><svg class="relative -top-[1px] ml-1  w-4 h-4 inline"></svg></span>](https://github.com/kubernetes/community/blob/master/contributors/devel/sig-node/container-runtime-interface.md), including Docker, Containerd, CRI-O, Mirantis, and others, giving you many options to choose the one that best fits your use cases.

### High availability

Docker Swarm provides built-in high availability for services. It automatically replicates services across multiple nodes in the Swarm cluster, ensuring that containers are distributed and balanced for fault tolerance.

On the other hand, Kubernetes provides a comprehensive set of features to achieve high availability, such as advanced scheduling to define pod placement based on node availability or resource utilization. Factors such as node health, resource constraints, and workload demands are also considered when distributing pods across the cluster.

### Popularity

Both Docker Swarm and Kubernetes are popular in the industry and have been battle-tested for a wide variety of use cases. Docker Swarm is often used where simplicity and fast deployment are the primary considerations, while Kubernetes is well-suited for complex applications that demand advanced features and capabilities. It excels in scenarios where high availability, scalability, and flexibility are crucial requirements.

### Networking

Both Docker Swarm and Kubernetes offer networking support. Docker Swarm provides simpler built-in overlay networking capabilities, while Kubernetes supports a more extensive and flexible networking model through its wide range of plugins and advanced networking features.

### GUI support

Both Docker Swarm and Kubernetes have GUI tools to help you easily interact with them. With Docker Swarm, you have [Swarmpit<span class="whitespace-nowrap"><svg class="relative -top-[1px] ml-1  w-4 h-4 inline"></svg></span>](https://swarmpit.io/) or [Shipyard<span class="whitespace-nowrap"><svg class="relative -top-[1px] ml-1  w-4 h-4 inline"></svg></span>](https://shipyard.run/). For Kubernetes, you have [Kubernetes Lens<span class="whitespace-nowrap"><svg class="relative -top-[1px] ml-1  w-4 h-4 inline"></svg></span>](https://k8slens.dev/), [Kube-dashboard<span class="whitespace-nowrap"><svg class="relative -top-[1px] ml-1  w-4 h-4 inline"></svg></span>](https://github.com/kubernetes/dashboard), or [Octant<span class="whitespace-nowrap"><svg class="relative -top-[1px] ml-1  w-4 h-4 inline"></svg></span>](https://octant.dev/).

### Learning curve

Docker Swarm is easy to learn and start with since it is lightweight and provides a simple approach to managing Docker containers. Kubernetes, however, has a much steeper learning curve since it offers more features and flexibility for deploying and managing containers.

### Complexity

Docker Swarm is designed to be lightweight and easy to use while Kubernetes is designed to have a lot of features and support to deploy complex applications. Thus, Kubernetes is much more complicated to operate compared to Docker Swarm.

### Load Balancing

Docker Swarm offers an automatic load balancing mechanism, ensuring seamless communication and interaction between containers within the Docker Swarm cluster. The load balancing functionality is built-in, requiring minimal configuration.

In contrast, Kubernetes provides a more customizable approach to load balancing. It allows you to define and configure load balancers based on your specific requirements. While this requires some manual setup, it grants you greater control over the load balancing configuration within the Kubernetes cluster.

### Command-line tools

When working with Docker Swarm, there is no need to install an additional command line tool specifically for cluster management. The standard `docker` command is sufficient to create and interact with the Swarm cluster.

However, Kubernetes requires the installation of the `kubectl` command line tool to work with the cluster. `kubectl` is the primary way to interact with a Kubernetes cluster and it provides extensive functionality for managing deployments, services, pods, and other resources within the Kubernetes environment.

### Scalability

Kubernetes allows you to automatically scale in or scale out the containers based on resource utilization or other factors. Docker Swarm, on the other hand, [does not support auto-scaling ability](https://betterstack.com/community/guides/scaling-docker/horizontally-scaling-swarm/).

### Security

Docker Swarm and Kubernetes were built with security in mind, and they both provide several features and mechanisms to deploy applications safely. However, Kubernetes supports more authentication and authorization mechanisms such as Role-Based Access Control (RBAC), secure access layers (SSL), TLS protocol, and secret management.

Now that you have a clearer understanding of the distinctions between Docker Swarm and Kubernetes, we will now focus on deploying a sample Go application to both platforms. This hands-on experience will provide you with practical insights into the deployment process, showcasing the unique features and considerations of each platform.

## Prerequisites

Before following through with the rest of this tutorial, you need to meet the following requirements:

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-a-ready-to-use-linux" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content">1. A ready-to-use Linux machine, such as an [Ubuntu version 22.04<span class="whitespace-nowrap"><svg class="relative -top-[1px] ml-1  w-4 h-4 inline"></svg></span>](https://releases.ubuntu.com/jammy/) server.
2. [A recent version of Go<span class="whitespace-nowrap"><svg class="relative -top-[1px] ml-1  w-4 h-4 inline"></svg></span>](https://go.dev/doc/install) installed on your machine.
3. A ready-to-use [Git<span class="whitespace-nowrap"><svg class="relative -top-[1px] ml-1  w-4 h-4 inline"></svg></span>](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git) command line for cloning the sample application from its GitHub repo.
4. [A recent version of Docker<span class="whitespace-nowrap"><svg class="relative -top-[1px] ml-1  w-4 h-4 inline"></svg></span>](https://docs.docker.com/engine/install/) installed and accessible without using `sudo`.
5. A free [DockerHub<span class="whitespace-nowrap"><svg class="relative -top-[1px] ml-1  w-4 h-4 inline"></svg></span>](https://hub.docker.com/) account for storing and sharing Docker images.
6. An already installed [PostgreSQL<span class="whitespace-nowrap"><svg class="relative -top-[1px] ml-1  w-4 h-4 inline"></svg></span>](https://www.postgresql.org/download/) instance.

</div></div></div></div>## Setting up the demo application

To fully understand how Docker Swarm and Kubernetes work and how they differ, you will deploy a demo application using both tools. This application is a blog service that allows users to create, update, retrieve, and delete blog posts. It is built using the Go programming language, and its data is stored in PostgreSQL.

However, you don't need to be familiar with Go or PostgreSQL to follow through. If you prefer, you can use an application stack that you're more familiar with and just follow the deployment steps to practice using Docker Swarm and Kubernetes.

To test out the application's functionality, let's try to run it directly on the local machine before deploying it through Docker Swarm and Kubernetes.

### 1. Cloning the GitHub repository

In this step, you will clone the [this GitHub repository<span class="whitespace-nowrap"><svg class="relative -top-[1px] ml-1  w-4 h-4 inline"></svg></span>](https://github.com/betterstack-community/docker-swarm-kubernetes) to your machine using the commands below:

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%C2%A0-2" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="px-4 py-[6px] bg-white dark:bg-[#0B0C14] flex items-center rounded-t-md border-b border-neutral-50 dark:border-neutral-800"><div class="text-[15px] font-medium inline align-middle grow"><span class="text-app-small"> </span></div><div class="copy-button hidden sm:flex sm:items-center" data-clipboard-target="confirmation"><button class="text-sm p-1" data-action="click->clipboard#copy"><svg alt="copy code to clipboard" class="m-0 text-neutral-200" height="18" width="18"></svg></button></div></div><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded command" data-clipboard-target="content" data-controller="code"></div></div></div></div></div></div>```command
git clone https://github.com/betterstack-community/docker-swarm-kubernetes

```

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%C2%A0-3" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded command" data-clipboard-target="content" data-controller="code"></div></div><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="px-4 py-[6px] bg-white dark:bg-[#0B0C14] flex items-center rounded-t-md border-b border-neutral-50 dark:border-neutral-800"><div class="text-[15px] font-medium inline align-middle grow"><span class="text-app-small"> </span></div><div class="copy-button hidden sm:flex sm:items-center" data-clipboard-target="confirmation"><button class="text-sm p-1" data-action="click->clipboard#copy"><svg alt="copy code to clipboard" class="m-0 text-neutral-200" height="18" width="18"></svg></button></div></div><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded command" data-clipboard-target="content" data-controller="code"></div></div></div></div></div></div>```command
cd betterstack-swarm-kubernetes

```

The structure of the directory should look like this:

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%C2%A0-4" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="px-4 py-[6px] bg-white dark:bg-[#0B0C14] flex items-center rounded-t-md border-b border-neutral-50 dark:border-neutral-800"><div class="text-[15px] font-medium inline align-middle grow"><span class="text-app-small"> </span></div><div class="copy-button hidden sm:flex sm:items-center" data-clipboard-target="confirmation"><button class="text-sm p-1" data-action="click->clipboard#copy"><svg alt="copy code to clipboard" class="m-0 text-neutral-200" height="18" width="18"></svg></button></div></div><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded text" data-clipboard-target="content" data-controller="code"></div></div></div></div></div></div>```text
├── config
├── Dockerfile
├── go.mod
├── go.sum
├── handler
├── kubernetes
├── main.go
└── swarm

```

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-the%C2%A0swarm%C2%A0and%C2%A0kubern" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded text" data-clipboard-target="content" data-controller="code"></div></div>- The `swarm` and `kubernetes` directories, along with the `Dockerfile` file are for deploying the app to Docker Swarm and Kubernetes platform. You will temporarily skip them for now.
- The rest of the directories and files constitute the Go application.

</div></div></div></div>### 2. Creating a PostgreSQL database in the local environment

Assuming PostgreSQL is installed on your machine, you can go ahead and access the `psql` command-line using the default `postgres` user by running the following command:

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%C2%A0-5" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="px-4 py-[6px] bg-white dark:bg-[#0B0C14] flex items-center rounded-t-md border-b border-neutral-50 dark:border-neutral-800"><div class="text-[15px] font-medium inline align-middle grow"><span class="text-app-small"> </span></div><div class="copy-button hidden sm:flex sm:items-center" data-clipboard-target="confirmation"><button class="text-sm p-1" data-action="click->clipboard#copy"><svg alt="copy code to clipboard" class="m-0 text-neutral-200" height="18" width="18"></svg></button></div></div><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded command" data-clipboard-target="content" data-controller="code"></div></div></div></div></div></div>```command
sudo -u postgres psql

```

In the `psql` interface, create a new user named "blog\_user":

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%C2%A0-6" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="px-4 py-[6px] bg-white dark:bg-[#0B0C14] flex items-center rounded-t-md border-b border-neutral-50 dark:border-neutral-800"><div class="text-[15px] font-medium inline align-middle grow"><span class="text-app-small"> </span></div><div class="copy-button hidden sm:flex sm:items-center" data-clipboard-target="confirmation"><button class="text-sm p-1" data-action="click->clipboard#copy"><svg alt="copy code to clipboard" class="m-0 text-neutral-200" height="18" width="18"></svg></button></div></div><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded sql" data-clipboard-target="content" data-controller="code"></div></div></div></div></div></div>```sql
CREATE USER blog_user;

```

Run the following command to list all existing users in the PostgreSQL database. You should see the `blog_user` user there.

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%C2%A0-7" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="px-4 py-[6px] bg-white dark:bg-[#0B0C14] flex items-center rounded-t-md border-b border-neutral-50 dark:border-neutral-800"><div class="text-[15px] font-medium inline align-middle grow"><span class="text-app-small"> </span></div><div class="copy-button hidden sm:flex sm:items-center" data-clipboard-target="confirmation"><button class="text-sm p-1" data-action="click->clipboard#copy"><svg alt="copy code to clipboard" class="m-0 text-neutral-200" height="18" width="18"></svg></button></div></div><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded sql" data-clipboard-target="content" data-controller="code"></div></div></div></div></div></div>```sql
\du

```

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%C2%A0output" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded sql" data-clipboard-target="content" data-controller="code"></div></div><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="px-4 py-[6px] bg-white dark:bg-[#0B0C14] flex items-center rounded-t-md border-b border-neutral-50 dark:border-neutral-800"><div class="text-[15px] font-medium inline align-middle grow"><span class="text-app-small"><svg alt="" class="m-0 -mt-1 inline fill-neutral-200" height="20" width="20"></svg> Output</span></div></div><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded text" data-clipboard-target="content" data-controller="code"></div></div></div></div></div></div>```text
                                   List of roles
 Role name |                         Attributes                         | Member of
-----------+------------------------------------------------------------+-----------
 blog_user      |                                                         | {}
 postgres  | Superuser, Create role, Create DB, Replication, Bypass RLS | {}

```

Next, change the password of the `blog_user` user to "blog\_password":

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%C2%A0-8" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="px-4 py-[6px] bg-white dark:bg-[#0B0C14] flex items-center rounded-t-md border-b border-neutral-50 dark:border-neutral-800"><div class="text-[15px] font-medium inline align-middle grow"><span class="text-app-small"> </span></div><div class="copy-button hidden sm:flex sm:items-center" data-clipboard-target="confirmation"><button class="text-sm p-1" data-action="click->clipboard#copy"><svg alt="copy code to clipboard" class="m-0 text-neutral-200" height="18" width="18"></svg></button></div></div><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded sql" data-clipboard-target="content" data-controller="code"></div></div></div></div></div></div>```sql
ALTER ROLE blog_user WITH PASSWORD 'blog_password';

```

Afterward, create a new `blog_db` database by running the following command:

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%C2%A0-9" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="px-4 py-[6px] bg-white dark:bg-[#0B0C14] flex items-center rounded-t-md border-b border-neutral-50 dark:border-neutral-800"><div class="text-[15px] font-medium inline align-middle grow"><span class="text-app-small"> </span></div><div class="copy-button hidden sm:flex sm:items-center" data-clipboard-target="confirmation"><button class="text-sm p-1" data-action="click->clipboard#copy"><svg alt="copy code to clipboard" class="m-0 text-neutral-200" height="18" width="18"></svg></button></div></div><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded sql" data-clipboard-target="content" data-controller="code"></div></div></div></div></div></div>```sql
CREATE DATABASE blog_db;

```

Finally, quit the current session using `\q`, and then log in again to `blog_db` database using `blog_user` user. Enter the password for the blog user if prompted:

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%C2%A0-10" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="px-4 py-[6px] bg-white dark:bg-[#0B0C14] flex items-center rounded-t-md border-b border-neutral-50 dark:border-neutral-800"><div class="text-[15px] font-medium inline align-middle grow"><span class="text-app-small"> </span></div><div class="copy-button hidden sm:flex sm:items-center" data-clipboard-target="confirmation"><button class="text-sm p-1" data-action="click->clipboard#copy"><svg alt="copy code to clipboard" class="m-0 text-neutral-200" height="18" width="18"></svg></button></div></div><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded sql" data-clipboard-target="content" data-controller="code"></div></div></div></div></div></div>```sql
psql -U blog_user -d blog_db -h localhost

```

At this stage, you can create a new `posts` table within the `blog_db` database by running the following command:

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%C2%A0-11" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="px-4 py-[6px] bg-white dark:bg-[#0B0C14] flex items-center rounded-t-md border-b border-neutral-50 dark:border-neutral-800"><div class="text-[15px] font-medium inline align-middle grow"><span class="text-app-small"> </span></div><div class="copy-button hidden sm:flex sm:items-center" data-clipboard-target="confirmation"><button class="text-sm p-1" data-action="click->clipboard#copy"><svg alt="copy code to clipboard" class="m-0 text-neutral-200" height="18" width="18"></svg></button></div></div><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded sql" data-clipboard-target="content" data-controller="code"></div></div></div></div></div></div>```sql
CREATE TABLE IF NOT EXISTS posts (
   ID         SERIAL NOT NULL PRIMARY KEY,
   BODY       TEXT   NOT NULL,
   CREATED_AT TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
   UPDATED_AT TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

```

Now that you've successfully set up the database let's go ahead and run the application in the local environment.

### 3. Starting the application

To bring up the app in the local environment, you need to install the required dependencies first:

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%C2%A0-12" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="px-4 py-[6px] bg-white dark:bg-[#0B0C14] flex items-center rounded-t-md border-b border-neutral-50 dark:border-neutral-800"><div class="text-[15px] font-medium inline align-middle grow"><span class="text-app-small"> </span></div><div class="copy-button hidden sm:flex sm:items-center" data-clipboard-target="confirmation"><button class="text-sm p-1" data-action="click->clipboard#copy"><svg alt="copy code to clipboard" class="m-0 text-neutral-200" height="18" width="18"></svg></button></div></div><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded command" data-clipboard-target="content" data-controller="code"></div></div></div></div></div></div>```command
go mod tidy

```

Then run the following commands to set the necessary environment variables for the Go application to access the PostgreSQL database:

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%C2%A0-13" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="px-4 py-[6px] bg-white dark:bg-[#0B0C14] flex items-center rounded-t-md border-b border-neutral-50 dark:border-neutral-800"><div class="text-[15px] font-medium inline align-middle grow"><span class="text-app-small"> </span></div><div class="copy-button hidden sm:flex sm:items-center" data-clipboard-target="confirmation"><button class="text-sm p-1" data-action="click->clipboard#copy"><svg alt="copy code to clipboard" class="m-0 text-neutral-200" height="18" width="18"></svg></button></div></div><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded command" data-clipboard-target="content" data-controller="code"></div></div></div></div></div></div>```command
export POSTGRES_PASSWORD=blog_password

```

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%C2%A0-14" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded command" data-clipboard-target="content" data-controller="code"></div></div><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="px-4 py-[6px] bg-white dark:bg-[#0B0C14] flex items-center rounded-t-md border-b border-neutral-50 dark:border-neutral-800"><div class="text-[15px] font-medium inline align-middle grow"><span class="text-app-small"> </span></div><div class="copy-button hidden sm:flex sm:items-center" data-clipboard-target="confirmation"><button class="text-sm p-1" data-action="click->clipboard#copy"><svg alt="copy code to clipboard" class="m-0 text-neutral-200" height="18" width="18"></svg></button></div></div><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded command" data-clipboard-target="content" data-controller="code"></div></div></div></div></div></div>```command
export POSTGRES_DB=blog_db

```

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%C2%A0-15" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded command" data-clipboard-target="content" data-controller="code"></div></div><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="px-4 py-[6px] bg-white dark:bg-[#0B0C14] flex items-center rounded-t-md border-b border-neutral-50 dark:border-neutral-800"><div class="text-[15px] font-medium inline align-middle grow"><span class="text-app-small"> </span></div><div class="copy-button hidden sm:flex sm:items-center" data-clipboard-target="confirmation"><button class="text-sm p-1" data-action="click->clipboard#copy"><svg alt="copy code to clipboard" class="m-0 text-neutral-200" height="18" width="18"></svg></button></div></div><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded command" data-clipboard-target="content" data-controller="code"></div></div></div></div></div></div>```command
export POSTGRES_USER=blog_user

```

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%C2%A0-16" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded command" data-clipboard-target="content" data-controller="code"></div></div><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="px-4 py-[6px] bg-white dark:bg-[#0B0C14] flex items-center rounded-t-md border-b border-neutral-50 dark:border-neutral-800"><div class="text-[15px] font-medium inline align-middle grow"><span class="text-app-small"> </span></div><div class="copy-button hidden sm:flex sm:items-center" data-clipboard-target="confirmation"><button class="text-sm p-1" data-action="click->clipboard#copy"><svg alt="copy code to clipboard" class="m-0 text-neutral-200" height="18" width="18"></svg></button></div></div><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded command" data-clipboard-target="content" data-controller="code"></div></div></div></div></div></div>```command
export POSTGRES_HOST=localhost

```

Afterward, run the following command to start the Go application:

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%C2%A0-17" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="px-4 py-[6px] bg-white dark:bg-[#0B0C14] flex items-center rounded-t-md border-b border-neutral-50 dark:border-neutral-800"><div class="text-[15px] font-medium inline align-middle grow"><span class="text-app-small"> </span></div><div class="copy-button hidden sm:flex sm:items-center" data-clipboard-target="confirmation"><button class="text-sm p-1" data-action="click->clipboard#copy"><svg alt="copy code to clipboard" class="m-0 text-neutral-200" height="18" width="18"></svg></button></div></div><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded command" data-clipboard-target="content" data-controller="code"></div></div></div></div></div></div>```command
go run main.go

```

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%C2%A0output-1" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded command" data-clipboard-target="content" data-controller="code"></div></div><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="px-4 py-[6px] bg-white dark:bg-[#0B0C14] flex items-center rounded-t-md border-b border-neutral-50 dark:border-neutral-800"><div class="text-[15px] font-medium inline align-middle grow"><span class="text-app-small"><svg alt="" class="m-0 -mt-1 inline fill-neutral-200" height="20" width="20"></svg> Output</span></div></div><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded text" data-clipboard-target="content" data-controller="code"></div></div></div></div></div></div>```text
You are connected to the database

```

Once the application is up and running open a separate terminal and run the following command to create a new blog entry:

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%C2%A0-18" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="px-4 py-[6px] bg-white dark:bg-[#0B0C14] flex items-center rounded-t-md border-b border-neutral-50 dark:border-neutral-800"><div class="text-[15px] font-medium inline align-middle grow"><span class="text-app-small"> </span></div><div class="copy-button hidden sm:flex sm:items-center" data-clipboard-target="confirmation"><button class="text-sm p-1" data-action="click->clipboard#copy"><svg alt="copy code to clipboard" class="m-0 text-neutral-200" height="18" width="18"></svg></button></div></div><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded command" data-clipboard-target="content" data-controller="code"></div></div></div></div></div></div>```command
curl --location 'http://localhost:8081/blog' \
    --header 'Content-Type: application/json' \
    --data '{
        "body":"this is a great blog"
    }'

```

Then run the following command to get the entry with an id of `1`:

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%C2%A0-19" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="px-4 py-[6px] bg-white dark:bg-[#0B0C14] flex items-center rounded-t-md border-b border-neutral-50 dark:border-neutral-800"><div class="text-[15px] font-medium inline align-middle grow"><span class="text-app-small"> </span></div><div class="copy-button hidden sm:flex sm:items-center" data-clipboard-target="confirmation"><button class="text-sm p-1" data-action="click->clipboard#copy"><svg alt="copy code to clipboard" class="m-0 text-neutral-200" height="18" width="18"></svg></button></div></div><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded command" data-clipboard-target="content" data-controller="code"></div></div></div></div></div></div>```command
curl --location 'http://localhost:8081/blog/1'

```

You should see the result below:

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%C2%A0output-2" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="px-4 py-[6px] bg-white dark:bg-[#0B0C14] flex items-center rounded-t-md border-b border-neutral-50 dark:border-neutral-800"><div class="text-[15px] font-medium inline align-middle grow"><span class="text-app-small"><svg alt="" class="m-0 -mt-1 inline fill-neutral-200" height="20" width="20"></svg> Output</span></div></div><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded json" data-clipboard-target="content" data-controller="code"></div></div></div></div></div></div>```json
{"id":1,"body":"this is a great blog","created_at":"2023-05-13T15:03:40.461732Z","updated_at":"2023-05-13T15:03:40.461732Z"}

```

At this point, you've successfully set up the app in the local environment and interacted with its APIs to confirm that it's in working order. Let's now move on to the next section where you will deploy the application using Docker Swarm.

## Deploying the application with Docker Swarm

Since you no longer need the PostgreSQL database service to run, you can stop it by running the following command:

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%C2%A0-20" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="px-4 py-[6px] bg-white dark:bg-[#0B0C14] flex items-center rounded-t-md border-b border-neutral-50 dark:border-neutral-800"><div class="text-[15px] font-medium inline align-middle grow"><span class="text-app-small"> </span></div><div class="copy-button hidden sm:flex sm:items-center" data-clipboard-target="confirmation"><button class="text-sm p-1" data-action="click->clipboard#copy"><svg alt="copy code to clipboard" class="m-0 text-neutral-200" height="18" width="18"></svg></button></div></div><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded command" data-clipboard-target="content" data-controller="code"></div></div></div></div></div></div>```command
sudo service postgresql stop

```

You can also stop the current application by pressing `CTRL+C` in the terminal.

### 1. Create a Docker Swarm cluster

In a Docker Swarm cluster, you will have one or more manager nodes to distribute tasks to one or more worker nodes. To simplify this demonstration, you will only create the manger node responsible for deploying the services and handling the application workload.

To create a Docker Swarm cluster, run the following command:

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%C2%A0-21" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="px-4 py-[6px] bg-white dark:bg-[#0B0C14] flex items-center rounded-t-md border-b border-neutral-50 dark:border-neutral-800"><div class="text-[15px] font-medium inline align-middle grow"><span class="text-app-small"> </span></div><div class="copy-button hidden sm:flex sm:items-center" data-clipboard-target="confirmation"><button class="text-sm p-1" data-action="click->clipboard#copy"><svg alt="copy code to clipboard" class="m-0 text-neutral-200" height="18" width="18"></svg></button></div></div><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded command" data-clipboard-target="content" data-controller="code"></div></div></div></div></div></div>```command
docker swarm init

```

You should see the following output confirming that the current node is a manager and relevant instructions to add a worker node to the cluster:

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%C2%A0output-3" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="px-4 py-[6px] bg-white dark:bg-[#0B0C14] flex items-center rounded-t-md border-b border-neutral-50 dark:border-neutral-800"><div class="text-[15px] font-medium inline align-middle grow"><span class="text-app-small"><svg alt="" class="m-0 -mt-1 inline fill-neutral-200" height="20" width="20"></svg> Output</span></div></div><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded text" data-clipboard-target="content" data-controller="code"></div></div></div></div></div></div>```text
Swarm initialized: current node (rpuk92y8wypwqwnv5kqzk5fik) is now a manager.

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

    docker swarm join --token <token> <ip_address>

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

```

Since we won't be adding a worker node to the Swarm cluster, let's move on to the next section and push the Docker image to DockerHub. If you'd like to see a full demonstration of [running a highly available Docker Swarm setup in production](https://betterstack.com/community/guides/scaling-docker/ha-docker-swarm/), please see the linked article.

### 2. Building the application Docker image

Inside the application directory, you have a `Dockerfile` which has the following contents:

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-dockerfile" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="px-4 py-[6px] bg-white dark:bg-[#0B0C14] flex items-center rounded-t-md border-b border-neutral-50 dark:border-neutral-800"><div class="text-[15px] font-medium inline align-middle grow"><span class="text-app-small">Dockerfile</span></div><div class="copy-button hidden sm:flex sm:items-center" data-clipboard-target="confirmation"><button class="text-sm p-1" data-action="click->clipboard#copy"><svg alt="copy code to clipboard" class="m-0 text-neutral-200" height="18" width="18"></svg></button></div></div><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded dockerfile" data-clipboard-target="content" data-controller="code"></div></div></div></div></div></div>```dockerfile
FROM golang:1.20

WORKDIR /app
COPY go.mod go.sum ./
RUN go mod download
COPY main.go ./
COPY config/db.go ./config/db.go
COPY handler/handlers.go ./handler/handlers.go
RUN CGO_ENABLED=0 GOOS=linux go build -o /out/main ./
EXPOSE 8081

# Run
ENTRYPOINT ["/out/main"]

```

These commands inside the `Dockerfile` instructs Docker to pull the Go version 1.20 image, then copy the files from our project directory into the Docker image and build an application executable named `main` in the /out directory. It also specifies that the Docker container will listen on port 8081 and that the `/out/main` binary is executed when the container is started.

To build the application image, run the following command. Remember to replace the `<username>` placeholder with your DockerHub username:

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%C2%A0-22" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="px-4 py-[6px] bg-white dark:bg-[#0B0C14] flex items-center rounded-t-md border-b border-neutral-50 dark:border-neutral-800"><div class="text-[15px] font-medium inline align-middle grow"><span class="text-app-small"> </span></div><div class="copy-button hidden sm:flex sm:items-center" data-clipboard-target="confirmation"><button class="text-sm p-1" data-action="click->clipboard#copy"><svg alt="copy code to clipboard" class="m-0 text-neutral-200" height="18" width="18"></svg></button></div></div><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded command" data-clipboard-target="content" data-controller="code"></div></div></div></div></div></div>```command
docker build -t <username>/blog .

```

You should observe the following output at the end of the process:

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%C2%A0output-4" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="px-4 py-[6px] bg-white dark:bg-[#0B0C14] flex items-center rounded-t-md border-b border-neutral-50 dark:border-neutral-800"><div class="text-[15px] font-medium inline align-middle grow"><span class="text-app-small"><svg alt="" class="m-0 -mt-1 inline fill-neutral-200" height="20" width="20"></svg> Output</span></div></div><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded text" data-clipboard-target="content" data-controller="code"></div></div></div></div></div></div>```text
. . .
Successfully built 222ca8bc81b8
Successfully tagged <username>/blog:latest

```

Now that you have successfully built the application image, log into your DockerHub account from the current session so that you can push the image to your account:

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%C2%A0-23" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="px-4 py-[6px] bg-white dark:bg-[#0B0C14] flex items-center rounded-t-md border-b border-neutral-50 dark:border-neutral-800"><div class="text-[15px] font-medium inline align-middle grow"><span class="text-app-small"> </span></div><div class="copy-button hidden sm:flex sm:items-center" data-clipboard-target="confirmation"><button class="text-sm p-1" data-action="click->clipboard#copy"><svg alt="copy code to clipboard" class="m-0 text-neutral-200" height="18" width="18"></svg></button></div></div><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded command" data-clipboard-target="content" data-controller="code"></div></div></div></div></div></div>```command
docker login

```

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%C2%A0output-5" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded command" data-clipboard-target="content" data-controller="code"></div></div><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="px-4 py-[6px] bg-white dark:bg-[#0B0C14] flex items-center rounded-t-md border-b border-neutral-50 dark:border-neutral-800"><div class="text-[15px] font-medium inline align-middle grow"><span class="text-app-small"><svg alt="" class="m-0 -mt-1 inline fill-neutral-200" height="20" width="20"></svg> Output</span></div></div><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded text" data-clipboard-target="content" data-controller="code"></div></div></div></div></div></div>```text
WARNING! Your password will be stored unencrypted in /home/<user>/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credentials-store

Login Succeeded

```

Once login is successful, run the following command to push the image to DockerHub:

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%C2%A0-24" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="px-4 py-[6px] bg-white dark:bg-[#0B0C14] flex items-center rounded-t-md border-b border-neutral-50 dark:border-neutral-800"><div class="text-[15px] font-medium inline align-middle grow"><span class="text-app-small"> </span></div><div class="copy-button hidden sm:flex sm:items-center" data-clipboard-target="confirmation"><button class="text-sm p-1" data-action="click->clipboard#copy"><svg alt="copy code to clipboard" class="m-0 text-neutral-200" height="18" width="18"></svg></button></div></div><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded command" data-clipboard-target="content" data-controller="code"></div></div></div></div></div></div>```command
docker push <username>/blog

```

Now that you've successfully pushed the image to your DockerHub account, let's move on to the next section and deploy the application to the Swarm cluster.

### 3. Deploying the application to the Swarm cluster

In this section, you will deploy the Go application and the PostgreSQL database to the Swarm cluster. Within the `swarm` directory, you have the two following files:

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-initdb.sql%C2%A0is-for-in" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content">- `initdb.sql` is for initializing the database state by creating a new table named "posts" when deploying the PostgreSQL database to the Swarm cluster
- `docker-compose.yml` is for creating the PostgreSQL database and the application services to the Swarm cluster

</div></div></div></div>Open the `docker-compose.yml` file in your text editor and update the `<username>` placeholder to your Docker username:

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-swarm%2Fdocker-compose" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="px-4 py-[6px] bg-white dark:bg-[#0B0C14] flex items-center rounded-t-md border-b border-neutral-50 dark:border-neutral-800"><div class="text-[15px] font-medium inline align-middle grow"><span class="text-app-small">swarm/docker-compose.yml</span></div><div class="copy-button hidden sm:flex sm:items-center" data-clipboard-target="confirmation"><button class="text-sm p-1" data-action="click->clipboard#copy"><svg alt="copy code to clipboard" class="m-0 text-neutral-200" height="18" width="18"></svg></button></div></div><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded yaml" data-clipboard-target="content" data-controller="code"></div></div></div></div></div></div>```yaml
# Use postgres/example user/password credentials
version: '3.6'

services:
  db:
    image: postgres
    environment:
      - POSTGRES_DB=blog_db
      - POSTGRES_USER=blog_user
      - POSTGRES_PASSWORD=blog_password
    ports:
      - '5432:5432'
    volumes:
      - ./initdb.sql:/docker-entrypoint-initdb.d/initdb.sql
    networks:
      - blog-network

  blog:

```

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-image%3A-%3Cusername%3E%2Fbl" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded yaml" data-clipboard-target="content" data-controller="code"><div class="code-highlight top bottom"><span class="token key atrule">image</span><span class="token punctuation">:</span> &lt;username<span class="token punctuation">&gt;</span>/blog</div></div></div></div></div></div></div>```yaml

    environment:
      - POSTGRES_DB=blog_db
      - POSTGRES_USER=blog_user
      - POSTGRES_PASSWORD=blog_password
      - POSTGRES_HOST=db:5432
    ports:
      - '8081:8081'
    volumes:
      - .:/app
    networks:
      - blog-network

networks:
  blog-network:
    name: blog-network

```

This file instructs Docker Swarm to create three services called `db`, `blog`, and `networks`:

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-the%C2%A0db%C2%A0service-is-fo" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content">- The `db` service is for creating a PostgreSQL database using the specified configuration. Its state is initialized using the `initdb.sql` file, and it uses the `blog-network` network.
- The `blog` service creates the blog application using the Docker image you previously pushed to DockerHub. You also need to provide environment variables for this service so that the application can access the PostgreSQL database. This service will also use the `blog-network` network allowing interaction with the `db` service through the host URL: `db:5432`.
- The `networks` service creates a network named `blog-network` so the two services can communicate via this network.

</div></div></div></div>To deploy these three services to the running Swarm cluster, run the following commands in turn:

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%C2%A0-25" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="px-4 py-[6px] bg-white dark:bg-[#0B0C14] flex items-center rounded-t-md border-b border-neutral-50 dark:border-neutral-800"><div class="text-[15px] font-medium inline align-middle grow"><span class="text-app-small"> </span></div><div class="copy-button hidden sm:flex sm:items-center" data-clipboard-target="confirmation"><button class="text-sm p-1" data-action="click->clipboard#copy"><svg alt="copy code to clipboard" class="m-0 text-neutral-200" height="18" width="18"></svg></button></div></div><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded command" data-clipboard-target="content" data-controller="code"></div></div></div></div></div></div>```command
cd swarm

```

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%C2%A0-26" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded command" data-clipboard-target="content" data-controller="code"></div></div><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="px-4 py-[6px] bg-white dark:bg-[#0B0C14] flex items-center rounded-t-md border-b border-neutral-50 dark:border-neutral-800"><div class="text-[15px] font-medium inline align-middle grow"><span class="text-app-small"> </span></div><div class="copy-button hidden sm:flex sm:items-center" data-clipboard-target="confirmation"><button class="text-sm p-1" data-action="click->clipboard#copy"><svg alt="copy code to clipboard" class="m-0 text-neutral-200" height="18" width="18"></svg></button></div></div><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded command" data-clipboard-target="content" data-controller="code"></div></div></div></div></div></div>```command
docker stack deploy --compose-file docker-compose.yml blogapp

```

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%C2%A0output-6" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded command" data-clipboard-target="content" data-controller="code"></div></div><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="px-4 py-[6px] bg-white dark:bg-[#0B0C14] flex items-center rounded-t-md border-b border-neutral-50 dark:border-neutral-800"><div class="text-[15px] font-medium inline align-middle grow"><span class="text-app-small"><svg alt="" class="m-0 -mt-1 inline fill-neutral-200" height="20" width="20"></svg> Output</span></div></div><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded text" data-clipboard-target="content" data-controller="code"></div></div></div></div></div></div>```text
Creating network blog-network
Creating service blogapp_db
Creating service blogapp_blog

```

Afterward, run the following command to verify that the services are running:

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%C2%A0-27" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="px-4 py-[6px] bg-white dark:bg-[#0B0C14] flex items-center rounded-t-md border-b border-neutral-50 dark:border-neutral-800"><div class="text-[15px] font-medium inline align-middle grow"><span class="text-app-small"> </span></div><div class="copy-button hidden sm:flex sm:items-center" data-clipboard-target="confirmation"><button class="text-sm p-1" data-action="click->clipboard#copy"><svg alt="copy code to clipboard" class="m-0 text-neutral-200" height="18" width="18"></svg></button></div></div><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded command" data-clipboard-target="content" data-controller="code"></div></div></div></div></div></div>```command
docker stack services blogapp

```

You should see the following results:

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%C2%A0output-7" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="px-4 py-[6px] bg-white dark:bg-[#0B0C14] flex items-center rounded-t-md border-b border-neutral-50 dark:border-neutral-800"><div class="text-[15px] font-medium inline align-middle grow"><span class="text-app-small"><svg alt="" class="m-0 -mt-1 inline fill-neutral-200" height="20" width="20"></svg> Output</span></div></div><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded text" data-clipboard-target="content" data-controller="code"></div></div></div></div></div></div>```text
ID             NAME           MODE         REPLICAS   IMAGE                  PORTS
uptqkx630zpy   blogapp_blog   replicated   1/1        username/blog:latest   *:8081->8081/tcp
jgb19lcx32y6   blogapp_db     replicated   1/1        postgres:latest        *:5432->5432/tcp

```

You should also be able to interact with the application endpoints now. Run the following command to create a new blog post:

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%C2%A0-28" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="px-4 py-[6px] bg-white dark:bg-[#0B0C14] flex items-center rounded-t-md border-b border-neutral-50 dark:border-neutral-800"><div class="text-[15px] font-medium inline align-middle grow"><span class="text-app-small"> </span></div><div class="copy-button hidden sm:flex sm:items-center" data-clipboard-target="confirmation"><button class="text-sm p-1" data-action="click->clipboard#copy"><svg alt="copy code to clipboard" class="m-0 text-neutral-200" height="18" width="18"></svg></button></div></div><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded command" data-clipboard-target="content" data-controller="code"></div></div></div></div></div></div>```command
curl --location 'http://localhost:8081/blog' \
    --header 'Content-Type: application/json' \
    --data '{
        "body":"this is a great blog"
    }'

```

Then run the command below to retrieve the newly created post:

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%C2%A0-29" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="px-4 py-[6px] bg-white dark:bg-[#0B0C14] flex items-center rounded-t-md border-b border-neutral-50 dark:border-neutral-800"><div class="text-[15px] font-medium inline align-middle grow"><span class="text-app-small"> </span></div><div class="copy-button hidden sm:flex sm:items-center" data-clipboard-target="confirmation"><button class="text-sm p-1" data-action="click->clipboard#copy"><svg alt="copy code to clipboard" class="m-0 text-neutral-200" height="18" width="18"></svg></button></div></div><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded command" data-clipboard-target="content" data-controller="code"></div></div></div></div></div></div>```command
curl --location 'http://localhost:8081/blog/1'

```

You should observe the same output as before:

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%C2%A0output-8" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="px-4 py-[6px] bg-white dark:bg-[#0B0C14] flex items-center rounded-t-md border-b border-neutral-50 dark:border-neutral-800"><div class="text-[15px] font-medium inline align-middle grow"><span class="text-app-small"><svg alt="" class="m-0 -mt-1 inline fill-neutral-200" height="20" width="20"></svg> Output</span></div></div><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded json" data-clipboard-target="content" data-controller="code"></div></div></div></div></div></div>```json
{"id":1,"body":"this is a great blog","created_at":"2023-05-13T08:56:26.140815Z","updated_at":"2023-05-13T08:56:26.140815Z"}

```

Now that you've successfully deployed the blog application using Docker Swarm. Let's move on to the next section and learn how to deploy the application using Kubernetes.

## Deploying the application with Kubernetes

To simplify the setup for the Kubernetes cluster, you will use the [minikube tool<span class="whitespace-nowrap"><svg class="relative -top-[1px] ml-1  w-4 h-4 inline"></svg></span>](https://github.com/kubernetes/minikube) which allows you to create an run a local Kubernetes cluster on your machine.

Start by following [these instructions<span class="whitespace-nowrap"><svg class="relative -top-[1px] ml-1  w-4 h-4 inline"></svg></span>](https://minikube.sigs.k8s.io/docs/start/) to install the `minikube` binary on your machine, then launch the minikube service by running the following command:

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%C2%A0-30" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="px-4 py-[6px] bg-white dark:bg-[#0B0C14] flex items-center rounded-t-md border-b border-neutral-50 dark:border-neutral-800"><div class="text-[15px] font-medium inline align-middle grow"><span class="text-app-small"> </span></div><div class="copy-button hidden sm:flex sm:items-center" data-clipboard-target="confirmation"><button class="text-sm p-1" data-action="click->clipboard#copy"><svg alt="copy code to clipboard" class="m-0 text-neutral-200" height="18" width="18"></svg></button></div></div><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded command" data-clipboard-target="content" data-controller="code"></div></div></div></div></div></div>```command
minikube start

```

Afterwards, run the following command to check whether the minikube service is up and running:

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%C2%A0-31" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="px-4 py-[6px] bg-white dark:bg-[#0B0C14] flex items-center rounded-t-md border-b border-neutral-50 dark:border-neutral-800"><div class="text-[15px] font-medium inline align-middle grow"><span class="text-app-small"> </span></div><div class="copy-button hidden sm:flex sm:items-center" data-clipboard-target="confirmation"><button class="text-sm p-1" data-action="click->clipboard#copy"><svg alt="copy code to clipboard" class="m-0 text-neutral-200" height="18" width="18"></svg></button></div></div><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded command" data-clipboard-target="content" data-controller="code"></div></div></div></div></div></div>```command
minikube kubectl -- get node

```

You should see the output below:

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%C2%A0output-9" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="px-4 py-[6px] bg-white dark:bg-[#0B0C14] flex items-center rounded-t-md border-b border-neutral-50 dark:border-neutral-800"><div class="text-[15px] font-medium inline align-middle grow"><span class="text-app-small"><svg alt="" class="m-0 -mt-1 inline fill-neutral-200" height="20" width="20"></svg> Output</span></div></div><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded text" data-clipboard-target="content" data-controller="code"></div></div></div></div></div></div>```text
NAME       STATUS   ROLES           AGE    VERSION
minikube   Ready    control-plane   188d   v1.25.3

```

For ease of use, you should alias the `minukube kubectl --` command to `kubectl` as follows:

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%C2%A0-32" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="px-4 py-[6px] bg-white dark:bg-[#0B0C14] flex items-center rounded-t-md border-b border-neutral-50 dark:border-neutral-800"><div class="text-[15px] font-medium inline align-middle grow"><span class="text-app-small"> </span></div><div class="copy-button hidden sm:flex sm:items-center" data-clipboard-target="confirmation"><button class="text-sm p-1" data-action="click->clipboard#copy"><svg alt="copy code to clipboard" class="m-0 text-neutral-200" height="18" width="18"></svg></button></div></div><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded command" data-clipboard-target="content" data-controller="code"></div></div></div></div></div></div>```command
alias kubectl="minikube kubectl --"

```

Now that the minikube service is up and running, you will can proceed with deploying the Go application and PostgreSQL database to the Kubernetes cluster. Let's start by deploying the PostgreSQL database in the next section.

### 1. Deploying the PostgreSQL database to the Kubernetes cluster

To deploy the PostgreSQL database to the Kubernetes cluster, you need to:

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-create-a-kubernetes-" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content">- Create a Kubernetes Persistent Volume (Kubernetes PV) so that you don't lose the application data when the Kubernetes cluster is down.
- Create the Kubernetes Persistent Volume Claim (Kubernetes PVC) to request storage inside the Kubernetes PV.
- Create the Kubernetes Config Map with initializing SQL query to create a table named `posts` when deploying the PostgreSQL database.
- Create the Kubernetes Deployment to deploy the PostgreSQL database to the Kubernetes cluster.
- Create the Kubernetes Service, which allows the blog application to access to the PostgreSQL database.

</div></div></div></div>From the current terminal, navigate to the `kubernetes` directory:

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%C2%A0-33" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="px-4 py-[6px] bg-white dark:bg-[#0B0C14] flex items-center rounded-t-md border-b border-neutral-50 dark:border-neutral-800"><div class="text-[15px] font-medium inline align-middle grow"><span class="text-app-small"> </span></div><div class="copy-button hidden sm:flex sm:items-center" data-clipboard-target="confirmation"><button class="text-sm p-1" data-action="click->clipboard#copy"><svg alt="copy code to clipboard" class="m-0 text-neutral-200" height="18" width="18"></svg></button></div></div><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded command" data-clipboard-target="content" data-controller="code"></div></div></div></div></div></div>```command
cd ../kubernetes

```

Next, create a `postgres/docker-pg-vol/data` directory inside the `kubernetes` directory to store the persistent data:

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%C2%A0-34" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="px-4 py-[6px] bg-white dark:bg-[#0B0C14] flex items-center rounded-t-md border-b border-neutral-50 dark:border-neutral-800"><div class="text-[15px] font-medium inline align-middle grow"><span class="text-app-small"> </span></div><div class="copy-button hidden sm:flex sm:items-center" data-clipboard-target="confirmation"><button class="text-sm p-1" data-action="click->clipboard#copy"><svg alt="copy code to clipboard" class="m-0 text-neutral-200" height="18" width="18"></svg></button></div></div><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded command" data-clipboard-target="content" data-controller="code"></div></div></div></div></div></div>```command
mkdir postgres/docker-pg-vol/data -p

```

Update the `path` inside the `hostPath` block in the `postgres-volume.yml` file with the absolute path to the persistent data directory. The path should look like this: `/home/<username>/betterstack-swarm-kubernetes/kubernetes/postgres/docker-pg-vol/data`

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%C2%A0-35" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="px-4 py-[6px] bg-white dark:bg-[#0B0C14] flex items-center rounded-t-md border-b border-neutral-50 dark:border-neutral-800"><div class="text-[15px] font-medium inline align-middle grow"><span class="text-app-small"> </span></div><div class="copy-button hidden sm:flex sm:items-center" data-clipboard-target="confirmation"><button class="text-sm p-1" data-action="click->clipboard#copy"><svg alt="copy code to clipboard" class="m-0 text-neutral-200" height="18" width="18"></svg></button></div></div><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded command" data-clipboard-target="content" data-controller="code"></div></div></div></div></div></div>```command
nano postgres-volume.yml

```

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-kubernetes%2Fpostgres-" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded command" data-clipboard-target="content" data-controller="code"></div></div><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="px-4 py-[6px] bg-white dark:bg-[#0B0C14] flex items-center rounded-t-md border-b border-neutral-50 dark:border-neutral-800"><div class="text-[15px] font-medium inline align-middle grow"><span class="text-app-small">kubernetes/postgres-volume.yml</span></div><div class="copy-button hidden sm:flex sm:items-center" data-clipboard-target="confirmation"><button class="text-sm p-1" data-action="click->clipboard#copy"><svg alt="copy code to clipboard" class="m-0 text-neutral-200" height="18" width="18"></svg></button></div></div><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded yaml" data-clipboard-target="content" data-controller="code"></div></div></div></div></div></div>```yaml
apiVersion: v1
kind: PersistentVolume
metadata:
  name: postgresql-claim0
  labels:
    type: local
spec:
  storageClassName: manual
  capacity:
    storage: 1Gi
  accessModes:
    - ReadWriteOnce
  hostPath:

```

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-path%3A-%22%2Fhome%2F%3Cuserna" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded yaml" data-clipboard-target="content" data-controller="code"><div class="code-highlight top bottom"><span class="token key atrule">path</span><span class="token punctuation">:</span> <span class="token string">"/home/&lt;username&gt;/betterstack-swarm-kubernetes/kubernetes/postgres/docker-pg-vol/data"</span></div></div></div></div></div></div></div>```yaml


```

Afterward, run the following command to create the Kubernetes Persistent Volume. If you do not specify the `--namespace` value, Kubernetes will automatically use the `default` namespace.

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%C2%A0-36" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="px-4 py-[6px] bg-white dark:bg-[#0B0C14] flex items-center rounded-t-md border-b border-neutral-50 dark:border-neutral-800"><div class="text-[15px] font-medium inline align-middle grow"><span class="text-app-small"> </span></div><div class="copy-button hidden sm:flex sm:items-center" data-clipboard-target="confirmation"><button class="text-sm p-1" data-action="click->clipboard#copy"><svg alt="copy code to clipboard" class="m-0 text-neutral-200" height="18" width="18"></svg></button></div></div><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded command" data-clipboard-target="content" data-controller="code"></div></div></div></div></div></div>```command
kubectl apply -f postgres-volume.yml

```

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%C2%A0output-10" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded command" data-clipboard-target="content" data-controller="code"></div></div><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="px-4 py-[6px] bg-white dark:bg-[#0B0C14] flex items-center rounded-t-md border-b border-neutral-50 dark:border-neutral-800"><div class="text-[15px] font-medium inline align-middle grow"><span class="text-app-small"><svg alt="" class="m-0 -mt-1 inline fill-neutral-200" height="20" width="20"></svg> Output</span></div></div><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded text" data-clipboard-target="content" data-controller="code"></div></div></div></div></div></div>```text
persistentvolume/postgresql-claim0 created

```

Then run the following command to create the Persistent Volume Claim.

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%C2%A0-37" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="px-4 py-[6px] bg-white dark:bg-[#0B0C14] flex items-center rounded-t-md border-b border-neutral-50 dark:border-neutral-800"><div class="text-[15px] font-medium inline align-middle grow"><span class="text-app-small"> </span></div><div class="copy-button hidden sm:flex sm:items-center" data-clipboard-target="confirmation"><button class="text-sm p-1" data-action="click->clipboard#copy"><svg alt="copy code to clipboard" class="m-0 text-neutral-200" height="18" width="18"></svg></button></div></div><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded command" data-clipboard-target="content" data-controller="code"></div></div></div></div></div></div>```command
kubectl apply -f postgres-pvc.yml

```

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%C2%A0output-11" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded command" data-clipboard-target="content" data-controller="code"></div></div><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="px-4 py-[6px] bg-white dark:bg-[#0B0C14] flex items-center rounded-t-md border-b border-neutral-50 dark:border-neutral-800"><div class="text-[15px] font-medium inline align-middle grow"><span class="text-app-small"><svg alt="" class="m-0 -mt-1 inline fill-neutral-200" height="20" width="20"></svg> Output</span></div></div><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded text" data-clipboard-target="content" data-controller="code"></div></div></div></div></div></div>```text
persistentvolumeclaim/postgresql-claim0 created

```

To create the configuration map for initializing the SQL query, run the following command:

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%C2%A0-38" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="px-4 py-[6px] bg-white dark:bg-[#0B0C14] flex items-center rounded-t-md border-b border-neutral-50 dark:border-neutral-800"><div class="text-[15px] font-medium inline align-middle grow"><span class="text-app-small"> </span></div><div class="copy-button hidden sm:flex sm:items-center" data-clipboard-target="confirmation"><button class="text-sm p-1" data-action="click->clipboard#copy"><svg alt="copy code to clipboard" class="m-0 text-neutral-200" height="18" width="18"></svg></button></div></div><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded command" data-clipboard-target="content" data-controller="code"></div></div></div></div></div></div>```command
kubectl apply -f postgres-initdb-config.yml

```

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%C2%A0output-12" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded command" data-clipboard-target="content" data-controller="code"></div></div><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="px-4 py-[6px] bg-white dark:bg-[#0B0C14] flex items-center rounded-t-md border-b border-neutral-50 dark:border-neutral-800"><div class="text-[15px] font-medium inline align-middle grow"><span class="text-app-small"><svg alt="" class="m-0 -mt-1 inline fill-neutral-200" height="20" width="20"></svg> Output</span></div></div><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded text" data-clipboard-target="content" data-controller="code"></div></div></div></div></div></div>```text
configmap/postgresql-initdb-config created

```

Next, run the following command to deploy the PostgreSQL database:

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%C2%A0-39" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="px-4 py-[6px] bg-white dark:bg-[#0B0C14] flex items-center rounded-t-md border-b border-neutral-50 dark:border-neutral-800"><div class="text-[15px] font-medium inline align-middle grow"><span class="text-app-small"> </span></div><div class="copy-button hidden sm:flex sm:items-center" data-clipboard-target="confirmation"><button class="text-sm p-1" data-action="click->clipboard#copy"><svg alt="copy code to clipboard" class="m-0 text-neutral-200" height="18" width="18"></svg></button></div></div><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded command" data-clipboard-target="content" data-controller="code"></div></div></div></div></div></div>```command
kubectl apply -f postgres-deployment.yml

```

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%C2%A0output-13" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded command" data-clipboard-target="content" data-controller="code"></div></div><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="px-4 py-[6px] bg-white dark:bg-[#0B0C14] flex items-center rounded-t-md border-b border-neutral-50 dark:border-neutral-800"><div class="text-[15px] font-medium inline align-middle grow"><span class="text-app-small"><svg alt="" class="m-0 -mt-1 inline fill-neutral-200" height="20" width="20"></svg> Output</span></div></div><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded text" data-clipboard-target="content" data-controller="code"></div></div></div></div></div></div>```text
deployment.apps/postgresql created

```

Finally, create the Kubernetes service for the PostgreSQL database:

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%C2%A0-40" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="px-4 py-[6px] bg-white dark:bg-[#0B0C14] flex items-center rounded-t-md border-b border-neutral-50 dark:border-neutral-800"><div class="text-[15px] font-medium inline align-middle grow"><span class="text-app-small"> </span></div><div class="copy-button hidden sm:flex sm:items-center" data-clipboard-target="confirmation"><button class="text-sm p-1" data-action="click->clipboard#copy"><svg alt="copy code to clipboard" class="m-0 text-neutral-200" height="18" width="18"></svg></button></div></div><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded command" data-clipboard-target="content" data-controller="code"></div></div></div></div></div></div>```command
kubectl apply -f postgres-service.yml

```

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%C2%A0output-14" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded command" data-clipboard-target="content" data-controller="code"></div></div><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="px-4 py-[6px] bg-white dark:bg-[#0B0C14] flex items-center rounded-t-md border-b border-neutral-50 dark:border-neutral-800"><div class="text-[15px] font-medium inline align-middle grow"><span class="text-app-small"><svg alt="" class="m-0 -mt-1 inline fill-neutral-200" height="20" width="20"></svg> Output</span></div></div><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded text" data-clipboard-target="content" data-controller="code"></div></div></div></div></div></div>```text
service/postgresql created

```

At this point, the PostgreSQL instance should be up and running. Go ahead and run the command below to confirm:

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%C2%A0-41" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="px-4 py-[6px] bg-white dark:bg-[#0B0C14] flex items-center rounded-t-md border-b border-neutral-50 dark:border-neutral-800"><div class="text-[15px] font-medium inline align-middle grow"><span class="text-app-small"> </span></div><div class="copy-button hidden sm:flex sm:items-center" data-clipboard-target="confirmation"><button class="text-sm p-1" data-action="click->clipboard#copy"><svg alt="copy code to clipboard" class="m-0 text-neutral-200" height="18" width="18"></svg></button></div></div><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded command" data-clipboard-target="content" data-controller="code"></div></div></div></div></div></div>```command
kubectl get pod

```

You should see the following result:

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%C2%A0output-15" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="px-4 py-[6px] bg-white dark:bg-[#0B0C14] flex items-center rounded-t-md border-b border-neutral-50 dark:border-neutral-800"><div class="text-[15px] font-medium inline align-middle grow"><span class="text-app-small"><svg alt="" class="m-0 -mt-1 inline fill-neutral-200" height="20" width="20"></svg> Output</span></div></div><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded text" data-clipboard-target="content" data-controller="code"></div></div></div></div></div></div>```text
NAME                               READY   STATUS    RESTARTS        AGE
postgresql-655746b9f8-n4dcf        1/1     Running   0               2m36s

```

Run the following command to check for the PostgreSQL service.

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%C2%A0-42" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="px-4 py-[6px] bg-white dark:bg-[#0B0C14] flex items-center rounded-t-md border-b border-neutral-50 dark:border-neutral-800"><div class="text-[15px] font-medium inline align-middle grow"><span class="text-app-small"> </span></div><div class="copy-button hidden sm:flex sm:items-center" data-clipboard-target="confirmation"><button class="text-sm p-1" data-action="click->clipboard#copy"><svg alt="copy code to clipboard" class="m-0 text-neutral-200" height="18" width="18"></svg></button></div></div><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded text" data-clipboard-target="content" data-controller="code"></div></div></div></div></div></div>```text
kubectl get service

```

You should see the following output:

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%C2%A0output-16" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="px-4 py-[6px] bg-white dark:bg-[#0B0C14] flex items-center rounded-t-md border-b border-neutral-50 dark:border-neutral-800"><div class="text-[15px] font-medium inline align-middle grow"><span class="text-app-small"><svg alt="" class="m-0 -mt-1 inline fill-neutral-200" height="20" width="20"></svg> Output</span></div></div><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded text" data-clipboard-target="content" data-controller="code"></div></div></div></div></div></div>```text
NAME         TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)    AGE
kubernetes   ClusterIP   10.96.0.1       <none>        443/TCP    14d
postgresql   ClusterIP   10.98.157.228   <none>        5432/TCP   2s

```

Now that you've successfully deployed the PostgreSQL database to the Kubernetes cluster, let's deploy the blog application next.

### 2. Deploying the application to the Kubernetes cluster

Before you can deploy your application using Kubernetes, you need to create a Docker secret so that Kubernetes can access your DockerHub account to pull the application image. Note that you need to replace the username, password, and email below with your DockerHub account information:

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%C2%A0-43" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="px-4 py-[6px] bg-white dark:bg-[#0B0C14] flex items-center rounded-t-md border-b border-neutral-50 dark:border-neutral-800"><div class="text-[15px] font-medium inline align-middle grow"><span class="text-app-small"> </span></div><div class="copy-button hidden sm:flex sm:items-center" data-clipboard-target="confirmation"><button class="text-sm p-1" data-action="click->clipboard#copy"><svg alt="copy code to clipboard" class="m-0 text-neutral-200" height="18" width="18"></svg></button></div></div><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded command" data-clipboard-target="content" data-controller="code"></div></div></div></div></div></div>```command
kubectl create secret docker-registry dockerhub-secret \
  --docker-server=docker.io \
  --docker-username=<username> \
  --docker-password=<password> \
  --docker-email=<email>

```

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%C2%A0output-17" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded command" data-clipboard-target="content" data-controller="code"></div></div><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="px-4 py-[6px] bg-white dark:bg-[#0B0C14] flex items-center rounded-t-md border-b border-neutral-50 dark:border-neutral-800"><div class="text-[15px] font-medium inline align-middle grow"><span class="text-app-small"><svg alt="" class="m-0 -mt-1 inline fill-neutral-200" height="20" width="20"></svg> Output</span></div></div><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded text" data-clipboard-target="content" data-controller="code"></div></div></div></div></div></div>```text
secret/dockerhub-secret created

```

Once the secret is created, open the `deployment.yml` file in your text editor and edit it as follows:

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%C2%A0-44" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="px-4 py-[6px] bg-white dark:bg-[#0B0C14] flex items-center rounded-t-md border-b border-neutral-50 dark:border-neutral-800"><div class="text-[15px] font-medium inline align-middle grow"><span class="text-app-small"> </span></div><div class="copy-button hidden sm:flex sm:items-center" data-clipboard-target="confirmation"><button class="text-sm p-1" data-action="click->clipboard#copy"><svg alt="copy code to clipboard" class="m-0 text-neutral-200" height="18" width="18"></svg></button></div></div><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded command" data-clipboard-target="content" data-controller="code"></div></div></div></div></div></div>```command
nano kubernetes/deployment.yml

```

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-kubernetes%2Fdeploymen" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded command" data-clipboard-target="content" data-controller="code"></div></div><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="px-4 py-[6px] bg-white dark:bg-[#0B0C14] flex items-center rounded-t-md border-b border-neutral-50 dark:border-neutral-800"><div class="text-[15px] font-medium inline align-middle grow"><span class="text-app-small">kubernetes/deployment.yml</span></div><div class="copy-button hidden sm:flex sm:items-center" data-clipboard-target="confirmation"><button class="text-sm p-1" data-action="click->clipboard#copy"><svg alt="copy code to clipboard" class="m-0 text-neutral-200" height="18" width="18"></svg></button></div></div><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded yaml" data-clipboard-target="content" data-controller="code"></div></div></div></div></div></div>```yaml
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: blogapp
spec:
  replicas: 2
  selector:
    matchLabels:
      name: blogapp
  template:
    metadata:
      labels:
        name: blogapp
    spec:
      containers:
        - name: application

```

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-image%3A-%3Cusername%3E%2Fbl-1" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded yaml" data-clipboard-target="content" data-controller="code"><div class="code-highlight top bottom"><span class="token key atrule">image</span><span class="token punctuation">:</span> &lt;username<span class="token punctuation">&gt;</span>/blog</div></div></div></div></div></div></div>```yaml

          imagePullPolicy: Always
          envFrom:
            - secretRef:
                name: dockerhub-secret
          env:
            - name: POSTGRES_DB
              value: blog_db
            - name: POSTGRES_USER
              value: blog_user
            - name: POSTGRES_PASSWORD
              value: blog_password
            - name: POSTGRES_HOST
              value: postgresql:5432
          ports:
            - containerPort: 8081

```

Save and close the file, then run the following command to deploy the blog app:

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%C2%A0-45" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="px-4 py-[6px] bg-white dark:bg-[#0B0C14] flex items-center rounded-t-md border-b border-neutral-50 dark:border-neutral-800"><div class="text-[15px] font-medium inline align-middle grow"><span class="text-app-small"> </span></div><div class="copy-button hidden sm:flex sm:items-center" data-clipboard-target="confirmation"><button class="text-sm p-1" data-action="click->clipboard#copy"><svg alt="copy code to clipboard" class="m-0 text-neutral-200" height="18" width="18"></svg></button></div></div><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded command" data-clipboard-target="content" data-controller="code"></div></div></div></div></div></div>```command
kubectl apply -f deployment.yml

```

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%C2%A0output-18" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded command" data-clipboard-target="content" data-controller="code"></div></div><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="px-4 py-[6px] bg-white dark:bg-[#0B0C14] flex items-center rounded-t-md border-b border-neutral-50 dark:border-neutral-800"><div class="text-[15px] font-medium inline align-middle grow"><span class="text-app-small"><svg alt="" class="m-0 -mt-1 inline fill-neutral-200" height="20" width="20"></svg> Output</span></div></div><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded text" data-clipboard-target="content" data-controller="code"></div></div></div></div></div></div>```text
deployment.apps/blogapp created

```

Then run the following command to create the Kubernetes service for the blog app, so that you can access the app from outside the Kubernetes cluster.

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%C2%A0-46" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="px-4 py-[6px] bg-white dark:bg-[#0B0C14] flex items-center rounded-t-md border-b border-neutral-50 dark:border-neutral-800"><div class="text-[15px] font-medium inline align-middle grow"><span class="text-app-small"> </span></div><div class="copy-button hidden sm:flex sm:items-center" data-clipboard-target="confirmation"><button class="text-sm p-1" data-action="click->clipboard#copy"><svg alt="copy code to clipboard" class="m-0 text-neutral-200" height="18" width="18"></svg></button></div></div><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded command" data-clipboard-target="content" data-controller="code"></div></div></div></div></div></div>```command
kubectl apply -f service.yml

```

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%C2%A0output-19" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded command" data-clipboard-target="content" data-controller="code"></div></div><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="px-4 py-[6px] bg-white dark:bg-[#0B0C14] flex items-center rounded-t-md border-b border-neutral-50 dark:border-neutral-800"><div class="text-[15px] font-medium inline align-middle grow"><span class="text-app-small"><svg alt="" class="m-0 -mt-1 inline fill-neutral-200" height="20" width="20"></svg> Output</span></div></div><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded text" data-clipboard-target="content" data-controller="code"></div></div></div></div></div></div>```text
service/blogapp-service created

```

Run the following command to get the running services inside the Kubernetes cluster.

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%C2%A0-47" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="px-4 py-[6px] bg-white dark:bg-[#0B0C14] flex items-center rounded-t-md border-b border-neutral-50 dark:border-neutral-800"><div class="text-[15px] font-medium inline align-middle grow"><span class="text-app-small"> </span></div><div class="copy-button hidden sm:flex sm:items-center" data-clipboard-target="confirmation"><button class="text-sm p-1" data-action="click->clipboard#copy"><svg alt="copy code to clipboard" class="m-0 text-neutral-200" height="18" width="18"></svg></button></div></div><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded command" data-clipboard-target="content" data-controller="code"></div></div></div></div></div></div>```command
kubectl get service

```

You should see the following result:

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%C2%A0-48" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="px-4 py-[6px] bg-white dark:bg-[#0B0C14] flex items-center rounded-t-md border-b border-neutral-50 dark:border-neutral-800"><div class="text-[15px] font-medium inline align-middle grow"><span class="text-app-small"> </span></div><div class="copy-button hidden sm:flex sm:items-center" data-clipboard-target="confirmation"><button class="text-sm p-1" data-action="click->clipboard#copy"><svg alt="copy code to clipboard" class="m-0 text-neutral-200" height="18" width="18"></svg></button></div></div><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded command" data-clipboard-target="content" data-controller="code"></div></div></div></div></div></div>```command
NAME              TYPE           CLUSTER-IP     EXTERNAL-IP   PORT(S)          AGE
blogapp-service   LoadBalancer   10.97.173.87   <pending>     8081:31983/TCP   5s
kubernetes        ClusterIP      10.96.0.1      <none>        443/TCP          14d
postgresql        ClusterIP      10.96.38.7     <none>        5432/TCP         8m1s

```

Notice that the `EXTERNAL-IP` column for the `blogapp-service` is pending. This is because you are using a custom Kubernetes cluster (minikube) that does not have an integrated load balancer. To workaround this issue, create a minikube tunnel in a new terminal through the command below:

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%C2%A0-49" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="px-4 py-[6px] bg-white dark:bg-[#0B0C14] flex items-center rounded-t-md border-b border-neutral-50 dark:border-neutral-800"><div class="text-[15px] font-medium inline align-middle grow"><span class="text-app-small"> </span></div><div class="copy-button hidden sm:flex sm:items-center" data-clipboard-target="confirmation"><button class="text-sm p-1" data-action="click->clipboard#copy"><svg alt="copy code to clipboard" class="m-0 text-neutral-200" height="18" width="18"></svg></button></div></div><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded command" data-clipboard-target="content" data-controller="code"></div></div></div></div></div></div>```command
minikube tunnel

```

Then run the `kubectl get service` command again. You should see the updated result with a proper `EXTERNAL-IP` value:

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%C2%A0output-20" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="px-4 py-[6px] bg-white dark:bg-[#0B0C14] flex items-center rounded-t-md border-b border-neutral-50 dark:border-neutral-800"><div class="text-[15px] font-medium inline align-middle grow"><span class="text-app-small"><svg alt="" class="m-0 -mt-1 inline fill-neutral-200" height="20" width="20"></svg> Output</span></div></div><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded text" data-clipboard-target="content" data-controller="code"></div></div></div></div></div></div>```text
NAME              TYPE           CLUSTER-IP     EXTERNAL-IP    PORT(S)          AGE
blogapp-service   LoadBalancer   10.97.173.87   10.97.173.87   8081:31983/TCP   4m40s
kubernetes        ClusterIP      10.96.0.1      <none>         443/TCP          14d
postgresql        ClusterIP      10.96.38.7     <none>         5432/TCP         12m

```

Now that you've deployed the blog application to the Kubernetes cluster, you can access it through its external IP which in the above example is `10.97.173.87`.

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%C2%A0-50" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="px-4 py-[6px] bg-white dark:bg-[#0B0C14] flex items-center rounded-t-md border-b border-neutral-50 dark:border-neutral-800"><div class="text-[15px] font-medium inline align-middle grow"><span class="text-app-small"> </span></div><div class="copy-button hidden sm:flex sm:items-center" data-clipboard-target="confirmation"><button class="text-sm p-1" data-action="click->clipboard#copy"><svg alt="copy code to clipboard" class="m-0 text-neutral-200" height="18" width="18"></svg></button></div></div><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded command" data-clipboard-target="content" data-controller="code"></div></div></div></div></div></div>```command
curl --location 'http://<external_ip>:8081/blog' \
    --header 'Content-Type: application/json' \
    --data '{
        "body":"this is a great blog"
    }'

```

Then run the following command to get the blog content with id `1`.

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%C2%A0-51" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="px-4 py-[6px] bg-white dark:bg-[#0B0C14] flex items-center rounded-t-md border-b border-neutral-50 dark:border-neutral-800"><div class="text-[15px] font-medium inline align-middle grow"><span class="text-app-small"> </span></div><div class="copy-button hidden sm:flex sm:items-center" data-clipboard-target="confirmation"><button class="text-sm p-1" data-action="click->clipboard#copy"><svg alt="copy code to clipboard" class="m-0 text-neutral-200" height="18" width="18"></svg></button></div></div><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded command" data-clipboard-target="content" data-controller="code"></div></div></div></div></div></div>```command
curl --location 'http://<external_ip>:8081/blog/1'

```

You should see the output as:

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%C2%A0output-21" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="px-4 py-[6px] bg-white dark:bg-[#0B0C14] flex items-center rounded-t-md border-b border-neutral-50 dark:border-neutral-800"><div class="text-[15px] font-medium inline align-middle grow"><span class="text-app-small"><svg alt="" class="m-0 -mt-1 inline fill-neutral-200" height="20" width="20"></svg> Output</span></div></div><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded json" data-clipboard-target="content" data-controller="code"></div></div></div></div></div></div>```json
{"id":1,"body":"this is a great blog","created_at":"2023-05-13T08:56:26.140815Z","updated_at":"2023-05-13T08:56:26.140815Z"}

```

And that's how you deploy the blog application to the Kubernetes cluster.

Comparing the deployment process between Docker Swarm and Kubernetes, we observe distinct trade-offs. Docker Swarm offers a simpler deployment experience, but it lacks built-in support for persistent data storage. In the event of a Docker Swarm cluster failure or recreation, there is a risk of losing the application data.

In contrast, Kubernetes introduces a more intricate deployment process but it offers the advantage of creating persistent data storage, ensuring data durability even during cluster disruptions or recreation. Additionally, Kubernetes provides flexibility in exposing the blog app service as per your requirements by leveraging the Kubernetes Service definition file.

## Use cases of Kubernetes vs. Docker Swarm

Docker Swarm and Kubernetes, despite being container orchestration platforms, possess distinct characteristics that cater to different use cases.

Docker Swarm is well-suited for:

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-beginners-in-contain" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content">- Beginners in containerization who seek to learn application deployment using containerization techniques.
- Small to medium-sized applications that require straightforward deployment and management.
- Users familiar with Docker and prefer a Docker-centric approach to application deployment. Docker Swarm seamlessly integrates with the Docker ecosystem.
- Applications with a relatively stable user base or predictable traffic patterns. Docker Swarm, although lacking advanced automatic scaling features compared to Kubernetes, can adequately handle such scenarios.

</div></div></div></div>Kubernetes should be considered when:

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-you-have-a-comprehen" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content">- You have a comprehensive understanding of Kubernetes components and have acquired proficiency in working with the platform. Kubernetes has a steeper learning curve but offers a comprehensive solution for deploying and managing containerized applications.
- Your application is complex and demands extensive customization during deployment. Kubernetes excels in managing large-scale, intricate applications, providing advanced management, scalability, and customization capabilities.
- Fine-grained control and customization options are crucial for your deployment.
- Automatic scaling is necessary due to your application's growing user base.

</div></div></div></div>In summary, Docker Swarm suits simpler deployments and those who prefer a Docker-centric approach, while Kubernetes caters to complex applications, fine-grained control, and automatic scaling needs. Carefully assess your requirements and familiarity with the platforms to determine the most suitable choice for your specific use case.

## Final thoughts

Throughout this article, you've gained insights into the distinctions between Docker Swarm and Kubernetes, and you've also had practical experience deploying a sample Go application using both platforms.

To further explore technical articles on cloud-native and containerization technologies, we invite you to visit our [BetterStack community guides](https://betterstack.com/community/guides/). There, you can find additional resources and in-depth information to enhance your understanding of these technologies.

Thanks for reading!

# How to Scale Docker Swarm Horizontally in Production

Link: [https://betterstack.com/community/guides/scaling-docker/horizontally-scaling-swarm/](https://betterstack.com/community/guides/scaling-docker/horizontally-scaling-swarm/)

<div class="dark bg-primary-hero" id="bkmrk-auto-scalingdockerhi" style="text-align: justify;"><div class="mx-auto pt-4 pb-8 px-7 max-w-[1130px]"><div class="pt-10 md:pt-16 lg:pt-20"><div class="mt-4 flex justify-center text-base flex-wrap">[Auto Scaling](https://betterstack.com/tag/auto-scaling?utm_content&utm_medium=guides&utm_source=community&utm_term=horizontally-scaling-swarm)[Docker](https://betterstack.com/tag/docker?utm_content&utm_medium=guides&utm_source=community&utm_term=horizontally-scaling-swarm)[High Availability](https://betterstack.com/tag/high-availability?utm_content&utm_medium=guides&utm_source=community&utm_term=horizontally-scaling-swarm)</div><div class="mt-10 md:mt-16 mt-20 text-center"><div class="text-white">Cristovao Cordeiro</div><div class="mt-1 uppercase whitespace-nowrap text-xs font-medium text-neutral-300 tracking-[1.56px]">Updated on January 9, 2024</div></div></div></div></div>###### Contents

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-prerequisites-gettin" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="sticky hidden xl:block mr-12 shrink-0 w-[190px]" data-toc-target="toc"><div class="text-base text-secondary sticky scroll-smooth overflow-y-auto pretty-scrollbars max-h-screen top-[100px] pb-40"><div class="table-of-contents flat">- [Prerequisites](https://betterstack.com/community/guides/scaling-docker/horizontally-scaling-swarm/#prerequisites)
- [Getting started](https://betterstack.com/community/guides/scaling-docker/horizontally-scaling-swarm/#getting-started)
- [Step 1 — Checking the current distribution of tasks](https://betterstack.com/community/guides/scaling-docker/horizontally-scaling-swarm/#step-1-checking-the-current-distribution-of-tasks)
- [Step 2 — Scaling out the service to 5 replicas](https://betterstack.com/community/guides/scaling-docker/horizontally-scaling-swarm/#step-2-scaling-out-the-service-to-5-replicas)
- [Step 3 — Undoing a scaling operation](https://betterstack.com/community/guides/scaling-docker/horizontally-scaling-swarm/#step-3-undoing-a-scaling-operation)
- [Step 4 — Scaling in the service to 3 replicas](https://betterstack.com/community/guides/scaling-docker/horizontally-scaling-swarm/#step-4-scaling-in-the-service-to-3-replicas)
- [Step 5 — Defining constraints while scaling a service](https://betterstack.com/community/guides/scaling-docker/horizontally-scaling-swarm/#step-5-defining-constraints-while-scaling-a-service)
- [Auto scaling Docker services (optional)](https://betterstack.com/community/guides/scaling-docker/horizontally-scaling-swarm/#auto-scaling-docker-services-optional)
- [Conclusion and next steps](https://betterstack.com/community/guides/scaling-docker/horizontally-scaling-swarm/#conclusion-and-next-steps)

</div></div></div><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content">  
</div></div></div></div>With any software service deployment, there might come a time when you need to think about scaling your service due to meet changing demands. Such an action may be triggered by multiple factors including the following:

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-your-service-is-unde" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content">- Your service is under heavy load which can ultimately impact its performance. Therefore, you'll want to add more instances of the service throughout the cluster, such that the incoming load can be re-distributed evenly.
- Your service does not have enough instances running throughout multiple availability zones of your cluster. This means it might be subject to a single point of failure which compromises its availability if one or more nodes in the cluster go down. Therefore, you'll want to add more instances to your service, distributed more equally throughout the cluster to increase its redundancy.
- Your service is experiencing a low demand from your users, which means you might be hosting and maintaining more instances of your service than what is needed to fulfill the demand. Therefore, you'll want to decrease the number of active service instances to reduce your maintenance efforts and compute costs.

</div></div></div></div>In this tutorial, you will learn how to horizontally scale in/out an existing Docker service, and you'll also experiment with scalability constraints and auto scaling solutions. For future reference, when we talk about *Scaling In* and *Scaling Out*, we mean the following:

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-scaling-in%3A-removing" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content">- **Scaling In**: removing instances from an existing service.
- **Scaling Out**: adding more instances in parallel to spread out the service load.

</div></div></div></div><div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-centralize-%26-visuali" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content">Centralize &amp; visualize your logs. Query everything with SQL. <div>[<button class="block px-3 py-2 bg-neutral-700 rounded font-medium text-white leading-none whitespace-nowrap">Explore more</button>](https://betterstack.com/telemetry?utm_content=upsell&utm_medium=guides&utm_source=community&utm_term=horizontally-scaling-swarm)</div></div></div></div></div>## Prerequisites

Before proceeding with this article, ensure that you've read and performed all the steps from the previous tutorial on [Setting up Docker Swarm High Availability in Production](https://betterstack.com/community/guides/scaling-docker/ha-docker-swarm/). This means you should have four replicas of an NGINX service running on a 5-node cluster with three managers and two workers where all managers have been drained:

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%C2%A0-2" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="px-4 py-[6px] bg-white dark:bg-[#0B0C14] flex items-center rounded-t-md border-b border-neutral-50 dark:border-neutral-800"><div class="text-[15px] font-medium inline align-middle grow"><span class="text-app-small"> </span></div><div class="copy-button hidden sm:flex sm:items-center" data-clipboard-target="confirmation"><button class="text-sm p-1" data-action="click->clipboard#copy"><svg alt="copy code to clipboard" class="m-0 text-neutral-200" height="18" width="18"></svg></button></div></div><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded command" data-clipboard-target="content" data-controller="code"></div></div></div></div></div></div>```command
docker node ls

```

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%C2%A0output" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded command" data-clipboard-target="content" data-controller="code"></div></div><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="px-4 py-[6px] bg-white dark:bg-[#0B0C14] flex items-center rounded-t-md border-b border-neutral-50 dark:border-neutral-800"><div class="text-[15px] font-medium inline align-middle grow"><span class="text-app-small"><svg alt="" class="m-0 -mt-1 inline fill-neutral-200" height="20" width="20"></svg> Output</span></div></div><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded text" data-clipboard-target="content" data-controller="code"></div></div></div></div></div></div>```text
ID                            HOSTNAME    STATUS    AVAILABILITY   MANAGER STATUS   ENGINE VERSION
9r83zto8qpqiazt6slxfkjypq     manager-1   Ready     Drain          Reachable        20.10.18
uspt9qwqnzqwl78gbxc7omja7 *   manager-2   Ready     Drain          Leader           20.10.18
txrdxwuwjpg5jjfer3bcmtc5r     manager-3   Ready     Drain          Reachable        20.10.18
kaq8r9gec4t58yc9oh3dc0r2d     worker-1    Ready     Active                          20.10.18
vk1224zd81xcihgm1iis2703z     worker-2    Ready     Active                          20.10.18

```

We are currently working on the `manager-2` node, which is the leader and is not schedulable (as it was drained in the previous tutorial). Go ahead and execute the following command to see the active services on the cluster:

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%C2%A0-3" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="px-4 py-[6px] bg-white dark:bg-[#0B0C14] flex items-center rounded-t-md border-b border-neutral-50 dark:border-neutral-800"><div class="text-[15px] font-medium inline align-middle grow"><span class="text-app-small"> </span></div><div class="copy-button hidden sm:flex sm:items-center" data-clipboard-target="confirmation"><button class="text-sm p-1" data-action="click->clipboard#copy"><svg alt="copy code to clipboard" class="m-0 text-neutral-200" height="18" width="18"></svg></button></div></div><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded command" data-clipboard-target="content" data-controller="code"></div></div></div></div></div></div>```command
docker service ls

```

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%C2%A0output-1" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded command" data-clipboard-target="content" data-controller="code"></div></div><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="px-4 py-[6px] bg-white dark:bg-[#0B0C14] flex items-center rounded-t-md border-b border-neutral-50 dark:border-neutral-800"><div class="text-[15px] font-medium inline align-middle grow"><span class="text-app-small"><svg alt="" class="m-0 -mt-1 inline fill-neutral-200" height="20" width="20"></svg> Output</span></div></div><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded text" data-clipboard-target="content" data-controller="code"></div></div></div></div></div></div>```text
ID             NAME          MODE         REPLICAS   IMAGE          PORTS
euqfhji2qpco   nginx_nginx   replicated   4/4        nginx:latest   *:8088->80/tcp

```

Currently, there is only one service with four replicas in the entire cluster. For now, ensure that you are connected to the Leader node (`manager-2` in this example). If you do not have access to a Docker cluster as required to follow this tutorial, we recommend you use the [online Docker playground<span class="whitespace-nowrap"><svg class="relative -top-[1px] ml-1  w-4 h-4 inline"></svg></span>](https://labs.play-with-docker.com/).Getting started

In this tutorial, we'll mainly use the `docker service` management command to perform all the service inspections and scalability actions. Knowledge of this command is crucial when scaling your services since it allows you to perform the following actions through various subcommands:

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-inspect%C2%A0all-the-info" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content">- `inspect` all the information about your service, including its previous and current states.
- `list` (or `ls`) all the services running in your cluster.
- list (`ps`) all the tasks within a service. Each task will correspond to a replica of your service, so this information is critical when scaling in/out.
- `update` a service's specification (i.e., its placement policies, number of replicas, etc.).
- `rollback` a service to its previous specification.
- `scale` one or more services concurrently, in, or out, which is pretty much the same as running a service `update` to change the number of service replicas.

</div></div></div></div>To see these subcommands in action, let's take on a 5-step scenario where we'll analyze our current cluster and services, and then scale in and out a service while also applying scalability constraints.

## Step 1 — Checking the current distribution of tasks

Docker services are composed of tasks which are scheduled into the cluster nodes based on the provided placement [preferences<span class="whitespace-nowrap"><svg class="relative -top-[1px] ml-1  w-4 h-4 inline"></svg></span>](https://docs.docker.com/engine/swarm/services/#placement-preferences) and [constraints<span class="whitespace-nowrap"><svg class="relative -top-[1px] ml-1  w-4 h-4 inline"></svg></span>](https://docs.docker.com/engine/swarm/services/#placement-constraints). In the previous tutorial, our NGINX service was deployed via a Docker Stack, which was declared with the `nginx.yaml` compose file. Let's confirm this through the command below:

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%C2%A0-4" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="px-4 py-[6px] bg-white dark:bg-[#0B0C14] flex items-center rounded-t-md border-b border-neutral-50 dark:border-neutral-800"><div class="text-[15px] font-medium inline align-middle grow"><span class="text-app-small"> </span></div><div class="copy-button hidden sm:flex sm:items-center" data-clipboard-target="confirmation"><button class="text-sm p-1" data-action="click->clipboard#copy"><svg alt="copy code to clipboard" class="m-0 text-neutral-200" height="18" width="18"></svg></button></div></div><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded command" data-clipboard-target="content" data-controller="code"></div></div></div></div></div></div>```command
docker stack ls

```

You should observe just one stack which was deployed from our `nginx.yaml` compose file:

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%C2%A0output-2" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="px-4 py-[6px] bg-white dark:bg-[#0B0C14] flex items-center rounded-t-md border-b border-neutral-50 dark:border-neutral-800"><div class="text-[15px] font-medium inline align-middle grow"><span class="text-app-small"><svg alt="" class="m-0 -mt-1 inline fill-neutral-200" height="20" width="20"></svg> Output</span></div></div><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded text" data-clipboard-target="content" data-controller="code"></div></div></div></div></div></div>```text
NAME      SERVICES   ORCHESTRATOR
nginx     1          Swarm

```

Next, list all the services in the `nginx` stack using the command below:

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%C2%A0-5" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="px-4 py-[6px] bg-white dark:bg-[#0B0C14] flex items-center rounded-t-md border-b border-neutral-50 dark:border-neutral-800"><div class="text-[15px] font-medium inline align-middle grow"><span class="text-app-small"> </span></div><div class="copy-button hidden sm:flex sm:items-center" data-clipboard-target="confirmation"><button class="text-sm p-1" data-action="click->clipboard#copy"><svg alt="copy code to clipboard" class="m-0 text-neutral-200" height="18" width="18"></svg></button></div></div><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded command" data-clipboard-target="content" data-controller="code"></div></div></div></div></div></div>```command
docker stack services nginx

```

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%C2%A0output-3" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded command" data-clipboard-target="content" data-controller="code"></div></div><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="px-4 py-[6px] bg-white dark:bg-[#0B0C14] flex items-center rounded-t-md border-b border-neutral-50 dark:border-neutral-800"><div class="text-[15px] font-medium inline align-middle grow"><span class="text-app-small"><svg alt="" class="m-0 -mt-1 inline fill-neutral-200" height="20" width="20"></svg> Output</span></div></div><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded text" data-clipboard-target="content" data-controller="code"></div></div></div></div></div></div>```text
ID             NAME          MODE         REPLICAS   IMAGE          PORTS
euqfhji2qpco   nginx_nginx   replicated   4/4        nginx:latest   *:8088->80/tcp

```

The above command produces all the services defined in the `nginx.yaml` file and deployed as part of the `nginx` stack above. In this case, it's the same as running `docker service ls` since there are no other stacks or services in the cluster.

It is easy to read through our `nginx.yaml` file to verify that we haven't defined any [placement policies<span class="whitespace-nowrap"><svg class="relative -top-[1px] ml-1  w-4 h-4 inline"></svg></span>](https://docs.docker.com/compose/compose-file/compose-file-v3/#placement) for this service. Take a look at the `deploy` section of the file:

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-nginx.yaml" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="px-4 py-[6px] bg-white dark:bg-[#0B0C14] flex items-center rounded-t-md border-b border-neutral-50 dark:border-neutral-800"><div class="text-[15px] font-medium inline align-middle grow"><span class="text-app-small">nginx.yaml</span></div><div class="copy-button hidden sm:flex sm:items-center" data-clipboard-target="confirmation"><button class="text-sm p-1" data-action="click->clipboard#copy"><svg alt="copy code to clipboard" class="m-0 text-neutral-200" height="18" width="18"></svg></button></div></div><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded yaml" data-clipboard-target="content" data-controller="code"></div></div></div></div></div></div>```yaml
version: '3.7'

networks:
  nginx:
    external: false

services:

  # --- NGINX ---
  nginx:
      image: nginx:latest
      ports:
        - '8088:80'

```

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-deploy%3A" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded yaml" data-clipboard-target="content" data-controller="code"><div class="code-highlight top"><span class="token key atrule">deploy</span><span class="token punctuation">:</span></div></div></div></div></div></div></div>```yaml


```

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-replicas%3A-4" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded yaml" data-clipboard-target="content" data-controller="code"><div class="code-highlight"><span class="token key atrule">replicas</span><span class="token punctuation">:</span> <span class="token number">4</span></div></div></div></div></div></div></div>```yaml


```

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-update_config%3A" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded yaml" data-clipboard-target="content" data-controller="code"><div class="code-highlight"><span class="token key atrule">update\_config</span><span class="token punctuation">:</span></div></div></div></div></div></div></div>```yaml


```

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-parallelism%3A-2" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded yaml" data-clipboard-target="content" data-controller="code"><div class="code-highlight"><span class="token key atrule">parallelism</span><span class="token punctuation">:</span> <span class="token number">2</span></div></div></div></div></div></div></div>```yaml


```

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-order%3A-start-first" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded yaml" data-clipboard-target="content" data-controller="code"><div class="code-highlight"><span class="token key atrule">order</span><span class="token punctuation">:</span> start<span class="token punctuation">-</span>first</div></div></div></div></div></div></div>```yaml


```

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-failure_action%3A-roll" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded yaml" data-clipboard-target="content" data-controller="code"><div class="code-highlight"><span class="token key atrule">failure\_action</span><span class="token punctuation">:</span> rollback</div></div></div></div></div></div></div>```yaml


```

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-delay%3A-10s" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded yaml" data-clipboard-target="content" data-controller="code"><div class="code-highlight"><span class="token key atrule">delay</span><span class="token punctuation">:</span> 10s</div></div></div></div></div></div></div>```yaml


```

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-rollback_config%3A" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded yaml" data-clipboard-target="content" data-controller="code"><div class="code-highlight"><span class="token key atrule">rollback\_config</span><span class="token punctuation">:</span></div></div></div></div></div></div></div>```yaml


```

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-parallelism%3A-0" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded yaml" data-clipboard-target="content" data-controller="code"><div class="code-highlight"><span class="token key atrule">parallelism</span><span class="token punctuation">:</span> <span class="token number">0</span></div></div></div></div></div></div></div>```yaml


```

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-order%3A-stop-first" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded yaml" data-clipboard-target="content" data-controller="code"><div class="code-highlight"><span class="token key atrule">order</span><span class="token punctuation">:</span> stop<span class="token punctuation">-</span>first</div></div></div></div></div></div></div>```yaml


```

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-restart_policy%3A" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded yaml" data-clipboard-target="content" data-controller="code"><div class="code-highlight"><span class="token key atrule">restart\_policy</span><span class="token punctuation">:</span></div></div></div></div></div></div></div>```yaml


```

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-condition%3A-any" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded yaml" data-clipboard-target="content" data-controller="code"><div class="code-highlight"><span class="token key atrule">condition</span><span class="token punctuation">:</span> any</div></div></div></div></div></div></div>```yaml


```

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-delay%3A-5s" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded yaml" data-clipboard-target="content" data-controller="code"><div class="code-highlight"><span class="token key atrule">delay</span><span class="token punctuation">:</span> 5s</div></div></div></div></div></div></div>```yaml


```

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-max_attempts%3A-3" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded yaml" data-clipboard-target="content" data-controller="code"><div class="code-highlight"><span class="token key atrule">max\_attempts</span><span class="token punctuation">:</span> <span class="token number">3</span></div></div></div></div></div></div></div>```yaml


```

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-window%3A-120s" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded yaml" data-clipboard-target="content" data-controller="code"><div class="code-highlight bottom"><span class="token key atrule">window</span><span class="token punctuation">:</span> 120s</div></div></div></div></div></div></div>```yaml

      healthcheck:
        test: ["CMD", "service", "nginx", "status"]
      networks:
        - nginx

```

We can also confirm this by using `docker service inspect` to get detailed information about the NGINX service. Because this inspection can return an exhaustive amount of information, we can format the output using a Go template. In our case, we know that the service's placement policies are detailed under the service's `Spec->TaskTemplate->Placement` field, so we can format our inspection output by running the following:

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%C2%A0-6" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="px-4 py-[6px] bg-white dark:bg-[#0B0C14] flex items-center rounded-t-md border-b border-neutral-50 dark:border-neutral-800"><div class="text-[15px] font-medium inline align-middle grow"><span class="text-app-small"> </span></div><div class="copy-button hidden sm:flex sm:items-center" data-clipboard-target="confirmation"><button class="text-sm p-1" data-action="click->clipboard#copy"><svg alt="copy code to clipboard" class="m-0 text-neutral-200" height="18" width="18"></svg></button></div></div><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded command" data-clipboard-target="content" data-controller="code"></div></div></div></div></div></div>```command
docker service inspect nginx_nginx --format '{{json .Spec.TaskTemplate.Placement}}'

```

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%C2%A0output-4" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded command" data-clipboard-target="content" data-controller="code"></div></div><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="px-4 py-[6px] bg-white dark:bg-[#0B0C14] flex items-center rounded-t-md border-b border-neutral-50 dark:border-neutral-800"><div class="text-[15px] font-medium inline align-middle grow"><span class="text-app-small"><svg alt="" class="m-0 -mt-1 inline fill-neutral-200" height="20" width="20"></svg> Output</span></div></div><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded text" data-clipboard-target="content" data-controller="code"></div></div></div></div></div></div>```text
{"Platforms":[{"Architecture":"amd64","OS":"linux"},{"OS":"linux"},{"OS":"linux"},{"Architecture":"arm64","OS":"linux"},{"Architecture":"386","OS":"linux"},{"Architecture":"mips64le","OS":"linux"},{"Architecture":"ppc64le","OS":"linux"},{"Architecture":"s390x","OS":"linux"}]}

```

As you can see, the service does not have any placement policies. We should expect that Docker is smart enough to distribute the four replicas of this service throughout all schedulable nodes of the cluster as evenly as possible. We have four schedulable nodes in our cluster, so in theory, we should have two NGINX replicas per worker node (since all three manager nodes are drained). Let's confirm this:

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%C2%A0-7" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="px-4 py-[6px] bg-white dark:bg-[#0B0C14] flex items-center rounded-t-md border-b border-neutral-50 dark:border-neutral-800"><div class="text-[15px] font-medium inline align-middle grow"><span class="text-app-small"> </span></div><div class="copy-button hidden sm:flex sm:items-center" data-clipboard-target="confirmation"><button class="text-sm p-1" data-action="click->clipboard#copy"><svg alt="copy code to clipboard" class="m-0 text-neutral-200" height="18" width="18"></svg></button></div></div><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded command" data-clipboard-target="content" data-controller="code"></div></div></div></div></div></div>```command
docker service ps nginx_nginx # list the tasks of the nginx_nginx service

```

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%C2%A0output-5" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded command" data-clipboard-target="content" data-controller="code"></div></div><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="px-4 py-[6px] bg-white dark:bg-[#0B0C14] flex items-center rounded-t-md border-b border-neutral-50 dark:border-neutral-800"><div class="text-[15px] font-medium inline align-middle grow"><span class="text-app-small"><svg alt="" class="m-0 -mt-1 inline fill-neutral-200" height="20" width="20"></svg> Output</span></div></div><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded text" data-clipboard-target="content" data-controller="code"></div></div></div></div></div></div>```text
ID             NAME                IMAGE          NODE        DESIRED STATE   CURRENT STATE           ERROR     PORTS
ikjo7su8ooo6   nginx_nginx.1       nginx:latest   worker-2    Running         Running 27 hours ago
inel921owq9b    \_ nginx_nginx.1   nginx:latest   manager-2   Shutdown        Shutdown 28 hours ago
y0y5mvj5n44r   nginx_nginx.2       nginx:latest   worker-1    Running         Running 27 hours ago
uk18jo6wwlq6    \_ nginx_nginx.2   nginx:latest   manager-3   Shutdown        Shutdown 28 hours ago
ijbalagf7isy   nginx_nginx.3       nginx:latest   worker-1    Running         Running 27 hours ago
drgu007baw8z   nginx_nginx.4       nginx:latest   worker-2    Running         Running 27 hours ago

```

As you can see, both worker nodes `worker-1` and `worker-2` are running two replicas of the NGINX service each. You can also see that the replicas that were running on `manager-2` and `manager-3` were shut down and reassigned to `worker-2` and `worker-1` respectively when both manager nodes were drained in step 8 of the [previous tutorial](https://betterstack.com/community/guides/scaling-docker/ha-docker-swarm/).

## Step 2 — Scaling out the service to 5 replicas

Let's begin this section by assuming our NGINX service is under a high load. We'll need to add another NGINX instance (aka replica) to cope with the increased demand. We can use the `docker service scale` command for this purpose. We only need to state the service name and the number of desired replicas.

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%C2%A0-8" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="px-4 py-[6px] bg-white dark:bg-[#0B0C14] flex items-center rounded-t-md border-b border-neutral-50 dark:border-neutral-800"><div class="text-[15px] font-medium inline align-middle grow"><span class="text-app-small"> </span></div><div class="copy-button hidden sm:flex sm:items-center" data-clipboard-target="confirmation"><button class="text-sm p-1" data-action="click->clipboard#copy"><svg alt="copy code to clipboard" class="m-0 text-neutral-200" height="18" width="18"></svg></button></div></div><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded command" data-clipboard-target="content" data-controller="code"></div></div></div></div></div></div>```command
docker service scale nginx_nginx=5

```

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%C2%A0output-6" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded command" data-clipboard-target="content" data-controller="code"></div></div><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="px-4 py-[6px] bg-white dark:bg-[#0B0C14] flex items-center rounded-t-md border-b border-neutral-50 dark:border-neutral-800"><div class="text-[15px] font-medium inline align-middle grow"><span class="text-app-small"><svg alt="" class="m-0 -mt-1 inline fill-neutral-200" height="20" width="20"></svg> Output</span></div></div><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded text" data-clipboard-target="content" data-controller="code"></div></div></div></div></div></div>```text
nginx_nginx scaled to 5
overall progress: 4 out of 5 tasks
1/5: running   [==================================================>]
2/5: starting  [============================================>      ]
3/5: running   [==================================================>]
4/5: running   [==================================================>]
5/5: running   [==================================================>]

```

Once the service is stable, we'll find a new replica in our service:

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%C2%A0-9" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="px-4 py-[6px] bg-white dark:bg-[#0B0C14] flex items-center rounded-t-md border-b border-neutral-50 dark:border-neutral-800"><div class="text-[15px] font-medium inline align-middle grow"><span class="text-app-small"> </span></div><div class="copy-button hidden sm:flex sm:items-center" data-clipboard-target="confirmation"><button class="text-sm p-1" data-action="click->clipboard#copy"><svg alt="copy code to clipboard" class="m-0 text-neutral-200" height="18" width="18"></svg></button></div></div><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded command" data-clipboard-target="content" data-controller="code"></div></div></div></div></div></div>```command
docker service ps nginx_nginx

```

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%C2%A0output-7" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded command" data-clipboard-target="content" data-controller="code"></div></div><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="px-4 py-[6px] bg-white dark:bg-[#0B0C14] flex items-center rounded-t-md border-b border-neutral-50 dark:border-neutral-800"><div class="text-[15px] font-medium inline align-middle grow"><span class="text-app-small"><svg alt="" class="m-0 -mt-1 inline fill-neutral-200" height="20" width="20"></svg> Output</span></div></div><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded text" data-clipboard-target="content" data-controller="code"></div></div></div></div></div></div>```text
ID             NAME                IMAGE          NODE        DESIRED STATE   CURRENT STATE            ERROR     PORTS
ikjo7su8ooo6   nginx_nginx.1       nginx:latest   worker-2    Running         Running 28 hours ago
inel921owq9b    \_ nginx_nginx.1   nginx:latest   manager-2   Shutdown        Shutdown 29 hours ago
y0y5mvj5n44r   nginx_nginx.2       nginx:latest   worker-1    Running         Running 28 hours ago
uk18jo6wwlq6    \_ nginx_nginx.2   nginx:latest   manager-3   Shutdown        Shutdown 29 hours ago
ijbalagf7isy   nginx_nginx.3       nginx:latest   worker-1    Running         Running 28 hours ago
drgu007baw8z   nginx_nginx.4       nginx:latest   worker-2    Running         Running 28 hours ago

```

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-2cd89o4cybmn-nginx_n" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded text" data-clipboard-target="content" data-controller="code"><div class="code-highlight top bottom">2cd89o4cybmn nginx_nginx.5 nginx:latest worker-2 Running Running 11 seconds ago</div></div></div></div></div></div></div>```text


```

This new `nginx_nginx.5` task is now running alongside `nginx_nginx.1` and `nginx_nginx.4` in `worker-2`.

We could've also added a new NGINX replica by running:

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%C2%A0-10" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="px-4 py-[6px] bg-white dark:bg-[#0B0C14] flex items-center rounded-t-md border-b border-neutral-50 dark:border-neutral-800"><div class="text-[15px] font-medium inline align-middle grow"><span class="text-app-small"> </span></div><div class="copy-button hidden sm:flex sm:items-center" data-clipboard-target="confirmation"><button class="text-sm p-1" data-action="click->clipboard#copy"><svg alt="copy code to clipboard" class="m-0 text-neutral-200" height="18" width="18"></svg></button></div></div><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded command" data-clipboard-target="content" data-controller="code"></div></div></div></div></div></div>```command
docker service update nginx_nginx --replicas 5

```

The outcome would've been the same as:

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%C2%A0-11" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="px-4 py-[6px] bg-white dark:bg-[#0B0C14] flex items-center rounded-t-md border-b border-neutral-50 dark:border-neutral-800"><div class="text-[15px] font-medium inline align-middle grow"><span class="text-app-small"> </span></div><div class="copy-button hidden sm:flex sm:items-center" data-clipboard-target="confirmation"><button class="text-sm p-1" data-action="click->clipboard#copy"><svg alt="copy code to clipboard" class="m-0 text-neutral-200" height="18" width="18"></svg></button></div></div><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded command" data-clipboard-target="content" data-controller="code"></div></div></div></div></div></div>```command
docker service scale nginx_nginx=5

```

Nonetheless, we recommend always using the `docker service scale` command as it can scale multiple services simultaneously. For example:

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%C2%A0-12" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="px-4 py-[6px] bg-white dark:bg-[#0B0C14] flex items-center rounded-t-md border-b border-neutral-50 dark:border-neutral-800"><div class="text-[15px] font-medium inline align-middle grow"><span class="text-app-small"> </span></div><div class="copy-button hidden sm:flex sm:items-center" data-clipboard-target="confirmation"><button class="text-sm p-1" data-action="click->clipboard#copy"><svg alt="copy code to clipboard" class="m-0 text-neutral-200" height="18" width="18"></svg></button></div></div><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded command" data-clipboard-target="content" data-controller="code"></div></div></div></div></div></div>```command
docker service scale my_service=3 my_other_service=4 ...

```

On the other hand, `docker service update` can only update one service at a time.

## Step 3 — Undoing a scaling operation

In this step, we will assume that we scaled our service by accident in the previous section and we'd like to revert our changes. As mentioned earlier, the `docker service scale` command is pretty much the same as a `docker service update` that only targets the number of service replicas. What happens under the hood is that the service is taking in a new specification where the number of replicas differs from the current one.

So how can we return our service to its previous state? Do we need to remember its entire previous specification by heart? Gladly we don't! Docker is smart enough to keep the service's previous specification within its definition. By running `docker service inspect`, we can examine a service's current and previous states:

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%C2%A0-13" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="px-4 py-[6px] bg-white dark:bg-[#0B0C14] flex items-center rounded-t-md border-b border-neutral-50 dark:border-neutral-800"><div class="text-[15px] font-medium inline align-middle grow"><span class="text-app-small"> </span></div><div class="copy-button hidden sm:flex sm:items-center" data-clipboard-target="confirmation"><button class="text-sm p-1" data-action="click->clipboard#copy"><svg alt="copy code to clipboard" class="m-0 text-neutral-200" height="18" width="18"></svg></button></div></div><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded command" data-clipboard-target="content" data-controller="code"></div></div></div></div></div></div>```command
docker service inspect nginx_nginx

```

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%C2%A0output-8" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded command" data-clipboard-target="content" data-controller="code"></div></div><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="px-4 py-[6px] bg-white dark:bg-[#0B0C14] flex items-center rounded-t-md border-b border-neutral-50 dark:border-neutral-800"><div class="text-[15px] font-medium inline align-middle grow"><span class="text-app-small"><svg alt="" class="m-0 -mt-1 inline fill-neutral-200" height="20" width="20"></svg> Output</span></div></div><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded text" data-clipboard-target="content" data-controller="code"></div></div></div></div></div></div>```text
[
    {
        "ID": "euqfhji2qpco",
        . . .

```

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%22spec%22%3A-%7B" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded text" data-clipboard-target="content" data-controller="code"><div class="code-highlight top">"Spec": {</div></div></div></div></div></div></div>```text


```

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%22name%22%3A-%22nginx_nginx" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded text" data-clipboard-target="content" data-controller="code"><div class="code-highlight">"Name": "nginx_nginx",</div></div></div></div></div></div></div>```text


```

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-.-.-." style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded text" data-clipboard-target="content" data-controller="code"><div class="code-highlight">. . .</div></div></div></div></div></div></div>```text


```

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%22tasktemplate%22%3A-%7B" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded text" data-clipboard-target="content" data-controller="code"><div class="code-highlight">"TaskTemplate": {</div></div></div></div></div></div></div>```text


```

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%22containerspec%22%3A-%7B" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded text" data-clipboard-target="content" data-controller="code"><div class="code-highlight">"ContainerSpec": {</div></div></div></div></div></div></div>```text


```

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%22image%22%3A-%22nginx%3Alate" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded text" data-clipboard-target="content" data-controller="code"><div class="code-highlight">"Image": "nginx:latest@sha256:2834dc507516af02784808c5f48b7cbe38b8ed5d0f4837f16e78d00deb7e7767",</div></div></div></div></div></div></div>```text


```

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%22labels%22%3A-%7B" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded text" data-clipboard-target="content" data-controller="code"><div class="code-highlight">"Labels": {</div></div></div></div></div></div></div>```text


```

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%22com.docker.stack.na" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded text" data-clipboard-target="content" data-controller="code"><div class="code-highlight">"com.docker.stack.namespace": "nginx"</div></div></div></div></div></div></div>```text


```

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%7D%2C" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded text" data-clipboard-target="content" data-controller="code"><div class="code-highlight">},</div></div></div></div></div></div></div>```text


```

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-.-.-.-1" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded text" data-clipboard-target="content" data-controller="code"><div class="code-highlight">. . .</div></div></div></div></div></div></div>```text


```

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%7D%2C-1" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded text" data-clipboard-target="content" data-controller="code"><div class="code-highlight">},</div></div></div></div></div></div></div>```text


```

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-.-.-.-2" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded text" data-clipboard-target="content" data-controller="code"><div class="code-highlight">. . .</div></div></div></div></div></div></div>```text


```

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%7D%2C-2" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded text" data-clipboard-target="content" data-controller="code"><div class="code-highlight">},</div></div></div></div></div></div></div>```text


```

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%22mode%22%3A-%7B" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded text" data-clipboard-target="content" data-controller="code"><div class="code-highlight">"Mode": {</div></div></div></div></div></div></div>```text


```

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%22replicated%22%3A-%7B" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded text" data-clipboard-target="content" data-controller="code"><div class="code-highlight">"Replicated": {</div></div></div></div></div></div></div>```text


```

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%22replicas%22%3A-5" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded text" data-clipboard-target="content" data-controller="code"><div class="code-highlight">"Replicas": 5</div></div></div></div></div></div></div>```text


```

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%7D" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded text" data-clipboard-target="content" data-controller="code"><div class="code-highlight">}</div></div></div></div></div></div></div>```text


```

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%7D%2C-3" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded text" data-clipboard-target="content" data-controller="code"><div class="code-highlight">},</div></div></div></div></div></div></div>```text


```

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-.-.-.-3" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded text" data-clipboard-target="content" data-controller="code"><div class="code-highlight">. . .</div></div></div></div></div></div></div>```text


```

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%22rollbackconfig%22%3A-%7B" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded text" data-clipboard-target="content" data-controller="code"><div class="code-highlight">"RollbackConfig": {</div></div></div></div></div></div></div>```text


```

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%22parallelism%22%3A-0%2C" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded text" data-clipboard-target="content" data-controller="code"><div class="code-highlight">"Parallelism": 0,</div></div></div></div></div></div></div>```text


```

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%22failureaction%22%3A-%22pa" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded text" data-clipboard-target="content" data-controller="code"><div class="code-highlight">"FailureAction": "pause",</div></div></div></div></div></div></div>```text


```

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%22monitor%22%3A-500000000" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded text" data-clipboard-target="content" data-controller="code"><div class="code-highlight">"Monitor": 5000000000,</div></div></div></div></div></div></div>```text


```

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%22maxfailureratio%22%3A-0" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded text" data-clipboard-target="content" data-controller="code"><div class="code-highlight">"MaxFailureRatio": 0,</div></div></div></div></div></div></div>```text


```

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%22order%22%3A-%22stop-first" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded text" data-clipboard-target="content" data-controller="code"><div class="code-highlight">"Order": "stop-first"</div></div></div></div></div></div></div>```text


```

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%7D%2C-4" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded text" data-clipboard-target="content" data-controller="code"><div class="code-highlight">},</div></div></div></div></div></div></div>```text


```

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-.-.-.-4" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded text" data-clipboard-target="content" data-controller="code"><div class="code-highlight">. . .</div></div></div></div></div></div></div>```text


```

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%7D%2C-5" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded text" data-clipboard-target="content" data-controller="code"><div class="code-highlight">},</div></div></div></div></div></div></div>```text


```

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%22previousspec%22%3A-%7B" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded text" data-clipboard-target="content" data-controller="code"><div class="code-highlight">"PreviousSpec": {</div></div></div></div></div></div></div>```text


```

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%22name%22%3A-%22nginx_nginx-1" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded text" data-clipboard-target="content" data-controller="code"><div class="code-highlight">"Name": "nginx_nginx",</div></div></div></div></div></div></div>```text


```

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-.-.-.-5" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded text" data-clipboard-target="content" data-controller="code"><div class="code-highlight">. . .</div></div></div></div></div></div></div>```text


```

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%22tasktemplate%22%3A-%7B-1" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded text" data-clipboard-target="content" data-controller="code"><div class="code-highlight">"TaskTemplate": {</div></div></div></div></div></div></div>```text


```

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%22containerspec%22%3A-%7B-1" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded text" data-clipboard-target="content" data-controller="code"><div class="code-highlight">"ContainerSpec": {</div></div></div></div></div></div></div>```text


```

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%22image%22%3A-%22nginx%3Alate-1" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded text" data-clipboard-target="content" data-controller="code"><div class="code-highlight">"Image": "nginx:latest@sha256:2834dc507516af02784808c5f48b7cbe38b8ed5d0f4837f16e78d00deb7e7767",</div></div></div></div></div></div></div>```text


```

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%22labels%22%3A-%7B-1" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded text" data-clipboard-target="content" data-controller="code"><div class="code-highlight">"Labels": {</div></div></div></div></div></div></div>```text


```

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%22com.docker.stack.na-1" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded text" data-clipboard-target="content" data-controller="code"><div class="code-highlight">"com.docker.stack.namespace": "nginx"</div></div></div></div></div></div></div>```text


```

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%7D%2C-6" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded text" data-clipboard-target="content" data-controller="code"><div class="code-highlight">},</div></div></div></div></div></div></div>```text


```

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-.-.-.-6" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded text" data-clipboard-target="content" data-controller="code"><div class="code-highlight">. . .</div></div></div></div></div></div></div>```text


```

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%7D%2C-7" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded text" data-clipboard-target="content" data-controller="code"><div class="code-highlight">},</div></div></div></div></div></div></div>```text


```

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-.-.-.-7" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded text" data-clipboard-target="content" data-controller="code"><div class="code-highlight">. . .</div></div></div></div></div></div></div>```text


```

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%7D%2C-8" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded text" data-clipboard-target="content" data-controller="code"><div class="code-highlight">},</div></div></div></div></div></div></div>```text


```

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%22mode%22%3A-%7B-1" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded text" data-clipboard-target="content" data-controller="code"><div class="code-highlight">"Mode": {</div></div></div></div></div></div></div>```text


```

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%22replicated%22%3A-%7B-1" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded text" data-clipboard-target="content" data-controller="code"><div class="code-highlight">"Replicated": {</div></div></div></div></div></div></div>```text


```

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%22replicas%22%3A-4" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded text" data-clipboard-target="content" data-controller="code"><div class="code-highlight">"Replicas": 4</div></div></div></div></div></div></div>```text


```

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%7D-1" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded text" data-clipboard-target="content" data-controller="code"><div class="code-highlight">}</div></div></div></div></div></div></div>```text


```

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%7D%2C-9" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded text" data-clipboard-target="content" data-controller="code"><div class="code-highlight">},</div></div></div></div></div></div></div>```text


```

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-.-.-.-8" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded text" data-clipboard-target="content" data-controller="code"><div class="code-highlight">. . .</div></div></div></div></div></div></div>```text


```

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%22rollbackconfig%22%3A-%7B-1" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded text" data-clipboard-target="content" data-controller="code"><div class="code-highlight">"RollbackConfig": {</div></div></div></div></div></div></div>```text


```

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%22parallelism%22%3A-0%2C-1" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded text" data-clipboard-target="content" data-controller="code"><div class="code-highlight">"Parallelism": 0,</div></div></div></div></div></div></div>```text


```

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%22failureaction%22%3A-%22pa-1" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded text" data-clipboard-target="content" data-controller="code"><div class="code-highlight">"FailureAction": "pause",</div></div></div></div></div></div></div>```text


```

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%22maxfailureratio%22%3A-0-1" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded text" data-clipboard-target="content" data-controller="code"><div class="code-highlight">"MaxFailureRatio": 0,</div></div></div></div></div></div></div>```text


```

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%22order%22%3A-%22stop-first-1" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded text" data-clipboard-target="content" data-controller="code"><div class="code-highlight">"Order": "stop-first"</div></div></div></div></div></div></div>```text


```

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%7D%2C-10" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded text" data-clipboard-target="content" data-controller="code"><div class="code-highlight">},</div></div></div></div></div></div></div>```text


```

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-.-.-.-9" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded text" data-clipboard-target="content" data-controller="code"><div class="code-highlight">. . .</div></div></div></div></div></div></div>```text


```

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%7D%2C-11" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded text" data-clipboard-target="content" data-controller="code"><div class="code-highlight bottom">},</div></div></div></div></div></div></div>```text

        . . .
    }
]

```

The above command results in a large output (thus truncated), but we can clearly see two top-level keys, `Spec` and `PreviousSpec`, which look identical at first, but if you look closely, `PreviousSpec` defines a `Replicated` service with `4` replicas, while `Spec` sets this number to `5` (as expected, given the scale out we've performed in the previous step).

Since we have this `PreviousSpec` information, we can determine what our service will look like once we revert to the previous state. But the question now is: how do we undo the last scaling operation?

Once again, Docker comes to the rescue! The `docker service` management command has a `rollback` subcommand for these situations. There's not much to know about it, you simply run `docker service rollback` on the desired service, and Docker will automatically update it to its `PreviousSpec` configuration. Go ahead and try it out as shown below:

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%C2%A0-14" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="px-4 py-[6px] bg-white dark:bg-[#0B0C14] flex items-center rounded-t-md border-b border-neutral-50 dark:border-neutral-800"><div class="text-[15px] font-medium inline align-middle grow"><span class="text-app-small"> </span></div><div class="copy-button hidden sm:flex sm:items-center" data-clipboard-target="confirmation"><button class="text-sm p-1" data-action="click->clipboard#copy"><svg alt="copy code to clipboard" class="m-0 text-neutral-200" height="18" width="18"></svg></button></div></div><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded command" data-clipboard-target="content" data-controller="code"></div></div></div></div></div></div>```command
docker service rollback nginx_nginx

```

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%C2%A0output-9" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded command" data-clipboard-target="content" data-controller="code"></div></div><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="px-4 py-[6px] bg-white dark:bg-[#0B0C14] flex items-center rounded-t-md border-b border-neutral-50 dark:border-neutral-800"><div class="text-[15px] font-medium inline align-middle grow"><span class="text-app-small"><svg alt="" class="m-0 -mt-1 inline fill-neutral-200" height="20" width="20"></svg> Output</span></div></div><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded text" data-clipboard-target="content" data-controller="code"></div></div></div></div></div></div>```text
nginx_nginx
rollback: manually requested rollback
overall progress: rolling back update: 4 out of 4 tasks
1/4: running   [>                                                  ]
2/4: running   [>                                                  ]
3/4: running   [>                                                  ]
4/4: running   [>                                                  ]
verify: Service converged
rollback: rollback completed

```

If the rollback is successful, we should now see our initial four replicas instead of the five we scaled out to in the previous step:

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%C2%A0-15" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="px-4 py-[6px] bg-white dark:bg-[#0B0C14] flex items-center rounded-t-md border-b border-neutral-50 dark:border-neutral-800"><div class="text-[15px] font-medium inline align-middle grow"><span class="text-app-small"> </span></div><div class="copy-button hidden sm:flex sm:items-center" data-clipboard-target="confirmation"><button class="text-sm p-1" data-action="click->clipboard#copy"><svg alt="copy code to clipboard" class="m-0 text-neutral-200" height="18" width="18"></svg></button></div></div><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded command" data-clipboard-target="content" data-controller="code"></div></div></div></div></div></div>```command
docker service ps nginx_nginx

```

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%C2%A0output-10" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded command" data-clipboard-target="content" data-controller="code"></div></div><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="px-4 py-[6px] bg-white dark:bg-[#0B0C14] flex items-center rounded-t-md border-b border-neutral-50 dark:border-neutral-800"><div class="text-[15px] font-medium inline align-middle grow"><span class="text-app-small"><svg alt="" class="m-0 -mt-1 inline fill-neutral-200" height="20" width="20"></svg> Output</span></div></div><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded text" data-clipboard-target="content" data-controller="code"></div></div></div></div></div></div>```text
ID             NAME                IMAGE          NODE        DESIRED STATE   CURRENT STATE           ERROR     PORTS
ikjo7su8ooo6   nginx_nginx.1       nginx:latest   worker-2    Running         Running 29 hours ago
inel921owq9b    \_ nginx_nginx.1   nginx:latest   manager-2   Shutdown        Shutdown 30 hours ago
y0y5mvj5n44r   nginx_nginx.2       nginx:latest   worker-1    Running         Running 29 hours ago
uk18jo6wwlq6    \_ nginx_nginx.2   nginx:latest   manager-3   Shutdown        Shutdown 30 hours ago
ijbalagf7isy   nginx_nginx.3       nginx:latest   worker-1    Running         Running 29 hours ago
drgu007baw8z   nginx_nginx.4       nginx:latest   worker-2    Running         Running 29 hours ago

```

And there we go, our service is back to where it was in Step 1, running with four replicas.

## Step 4 — Scaling in the service to 3 replicas

Let's now assume we've been able to absorb the high service loads with our previous scale out and are now experiencing low demand for our service. To free up some space and potentially reduce our compute costs, let's shrink our service from four to three replicas:

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%C2%A0-16" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="px-4 py-[6px] bg-white dark:bg-[#0B0C14] flex items-center rounded-t-md border-b border-neutral-50 dark:border-neutral-800"><div class="text-[15px] font-medium inline align-middle grow"><span class="text-app-small"> </span></div><div class="copy-button hidden sm:flex sm:items-center" data-clipboard-target="confirmation"><button class="text-sm p-1" data-action="click->clipboard#copy"><svg alt="copy code to clipboard" class="m-0 text-neutral-200" height="18" width="18"></svg></button></div></div><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded command" data-clipboard-target="content" data-controller="code"></div></div></div></div></div></div>```command
docker service scale nginx_nginx=3

```

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%C2%A0output-11" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded command" data-clipboard-target="content" data-controller="code"></div></div><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="px-4 py-[6px] bg-white dark:bg-[#0B0C14] flex items-center rounded-t-md border-b border-neutral-50 dark:border-neutral-800"><div class="text-[15px] font-medium inline align-middle grow"><span class="text-app-small"><svg alt="" class="m-0 -mt-1 inline fill-neutral-200" height="20" width="20"></svg> Output</span></div></div><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded text" data-clipboard-target="content" data-controller="code"></div></div></div></div></div></div>```text
nginx_nginx scaled to 3
overall progress: 3 out of 3 tasks
1/3: running   [==================================================>]
2/3: running   [==================================================>]
3/3: running   [==================================================>]
verify: Service converged

```

The command is pretty much the same as in step 2, except for the desired number of replicas. Docker will take care of shutting down one of the replicas, leaving us with the desired number, evenly distributed throughout the cluster once again:

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%C2%A0-17" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="px-4 py-[6px] bg-white dark:bg-[#0B0C14] flex items-center rounded-t-md border-b border-neutral-50 dark:border-neutral-800"><div class="text-[15px] font-medium inline align-middle grow"><span class="text-app-small"> </span></div><div class="copy-button hidden sm:flex sm:items-center" data-clipboard-target="confirmation"><button class="text-sm p-1" data-action="click->clipboard#copy"><svg alt="copy code to clipboard" class="m-0 text-neutral-200" height="18" width="18"></svg></button></div></div><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded command" data-clipboard-target="content" data-controller="code"></div></div></div></div></div></div>```command
docker service ps nginx_nginx

```

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%C2%A0output-12" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded command" data-clipboard-target="content" data-controller="code"></div></div><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="px-4 py-[6px] bg-white dark:bg-[#0B0C14] flex items-center rounded-t-md border-b border-neutral-50 dark:border-neutral-800"><div class="text-[15px] font-medium inline align-middle grow"><span class="text-app-small"><svg alt="" class="m-0 -mt-1 inline fill-neutral-200" height="20" width="20"></svg> Output</span></div></div><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded text" data-clipboard-target="content" data-controller="code"></div></div></div></div></div></div>```text
ID             NAME                IMAGE          NODE        DESIRED STATE   CURRENT STATE           ERROR     PORTS
ikjo7su8ooo6   nginx_nginx.1       nginx:latest   worker-2    Running         Running 29 hours ago
inel921owq9b    \_ nginx_nginx.1   nginx:latest   manager-2   Shutdown        Shutdown 30 hours ago
y0y5mvj5n44r   nginx_nginx.2       nginx:latest   worker-1    Running         Running 29 hours ago
uk18jo6wwlq6    \_ nginx_nginx.2   nginx:latest   manager-3   Shutdown        Shutdown 30 hours ago
ijbalagf7isy   nginx_nginx.3       nginx:latest   worker-1    Running         Running 29 hours ago

```

Notice that other replicas weren't disturbed by this action — they are still running, uninterruptedly, for 29 hours.

## Step 5 — Defining constraints while scaling a service

Finally, sometimes you might want to ensure that a certain condition is met, even after your service is already running. For example, let's assume we now need to scale out to five NGINX replicas again, but we discovered that our worker nodes are not capable of hosting more than two NGINX replicas concurrently without a performance degradation.

In such scenario, we can no longer use `docker service scale` because it does not allow us to specify other configurations besides the number of replicas. This is where the `docker service update` command comes in, as it offers a wide range of options for configuring the new state of our service.

We need a new number of replicas, plus one condition (no more than two replicas per node), so we can use the following options:

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%C2%A0-18" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="px-4 py-[6px] bg-white dark:bg-[#0B0C14] flex items-center rounded-t-md border-b border-neutral-50 dark:border-neutral-800"><div class="text-[15px] font-medium inline align-middle grow"><span class="text-app-small"> </span></div><div class="copy-button hidden sm:flex sm:items-center" data-clipboard-target="confirmation"><button class="text-sm p-1" data-action="click->clipboard#copy"><svg alt="copy code to clipboard" class="m-0 text-neutral-200" height="18" width="18"></svg></button></div></div><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded command" data-clipboard-target="content" data-controller="code"></div></div></div></div></div></div>```command
docker service update --help

```

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%C2%A0output-13" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded command" data-clipboard-target="content" data-controller="code"></div></div><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="px-4 py-[6px] bg-white dark:bg-[#0B0C14] flex items-center rounded-t-md border-b border-neutral-50 dark:border-neutral-800"><div class="text-[15px] font-medium inline align-middle grow"><span class="text-app-small"><svg alt="" class="m-0 -mt-1 inline fill-neutral-200" height="20" width="20"></svg> Output</span></div></div><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded text" data-clipboard-target="content" data-controller="code"></div></div></div></div></div></div>```text
. . .
--constraint-add list                Add or update a placement constraint
. . .
--replicas uint                      Number of tasks
--replicas-max-per-node uint         Maximum number of tasks per node (default 0 = unlimited)
. . .

```

Go ahead and run the following service update command to scale out to five replicas once more:

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%C2%A0-19" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="px-4 py-[6px] bg-white dark:bg-[#0B0C14] flex items-center rounded-t-md border-b border-neutral-50 dark:border-neutral-800"><div class="text-[15px] font-medium inline align-middle grow"><span class="text-app-small"> </span></div><div class="copy-button hidden sm:flex sm:items-center" data-clipboard-target="confirmation"><button class="text-sm p-1" data-action="click->clipboard#copy"><svg alt="copy code to clipboard" class="m-0 text-neutral-200" height="18" width="18"></svg></button></div></div><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded command" data-clipboard-target="content" data-controller="code"></div></div></div></div></div></div>```command
docker service update nginx_nginx --replicas 5 --replicas-max-per-node 2

```

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%C2%A0output-14" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded command" data-clipboard-target="content" data-controller="code"></div></div><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="px-4 py-[6px] bg-white dark:bg-[#0B0C14] flex items-center rounded-t-md border-b border-neutral-50 dark:border-neutral-800"><div class="text-[15px] font-medium inline align-middle grow"><span class="text-app-small"><svg alt="" class="m-0 -mt-1 inline fill-neutral-200" height="20" width="20"></svg> Output</span></div></div><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded text" data-clipboard-target="content" data-controller="code"></div></div></div></div></div></div>```text
nginx_nginx
overall progress: 2 out of 5 tasks
1/5: starting  [============================================>      ]
2/5: running   [==================================================>]
3/5: starting  [============================================>      ]
4/5: running   [==================================================>]

```

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-5%2F5%3A-no-suitable-nod" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded text" data-clipboard-target="content" data-controller="code"><div class="code-highlight top bottom">5/5: no suitable node (max replicas per node limit exceed; scheduling constrain…</div></div></div></div></div></div></div>```text


```

You'll observe that Docker will rightfully complain about your decision, because you've restricted each worker to only two replicas which means the fifth one will have no where to go. Since the above command was executed in the foreground, Docker will keep indefinitely, trying to fix this situation. You'll see something like this:

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%C2%A0output-15" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="px-4 py-[6px] bg-white dark:bg-[#0B0C14] flex items-center rounded-t-md border-b border-neutral-50 dark:border-neutral-800"><div class="text-[15px] font-medium inline align-middle grow"><span class="text-app-small"><svg alt="" class="m-0 -mt-1 inline fill-neutral-200" height="20" width="20"></svg> Output</span></div></div><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded text" data-clipboard-target="content" data-controller="code"></div></div></div></div></div></div>```text
nginx_nginx
overall progress: 4 out of 5 tasks
1/5: running   [==================================================>]
2/5: running   [==================================================>]
3/5: running   [==================================================>]
4/5: running   [==================================================>]
5/5: no suitable node (max replicas per node limit exceed; scheduling constrain…

```

We can `Ctrl+c` to interrupt the process (the service update will continue in the background), and then verify that this new task is pending, waiting for a suitable node to show up:

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%C2%A0-20" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="px-4 py-[6px] bg-white dark:bg-[#0B0C14] flex items-center rounded-t-md border-b border-neutral-50 dark:border-neutral-800"><div class="text-[15px] font-medium inline align-middle grow"><span class="text-app-small"> </span></div><div class="copy-button hidden sm:flex sm:items-center" data-clipboard-target="confirmation"><button class="text-sm p-1" data-action="click->clipboard#copy"><svg alt="copy code to clipboard" class="m-0 text-neutral-200" height="18" width="18"></svg></button></div></div><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded command" data-clipboard-target="content" data-controller="code"></div></div></div></div></div></div>```command
docker service ps nginx_nginx --no-trunc # use --no-trunc to see the whole output

```

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%C2%A0output-16" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded command" data-clipboard-target="content" data-controller="code"></div></div><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="px-4 py-[6px] bg-white dark:bg-[#0B0C14] flex items-center rounded-t-md border-b border-neutral-50 dark:border-neutral-800"><div class="text-[15px] font-medium inline align-middle grow"><span class="text-app-small"><svg alt="" class="m-0 -mt-1 inline fill-neutral-200" height="20" width="20"></svg> Output</span></div></div><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded text" data-clipboard-target="content" data-controller="code"></div></div></div></div></div></div>```text
ID                          NAME                IMAGE                                                                                  NODE        DESIRED STATE   CURRENT STATE           ERROR                                                                                          PORTS
ikjo7su8ooo6b7wmh4r9uj1lq   nginx_nginx.1       nginx:latest@sha256:0b970013351304af46f322da1263516b188318682b2ab1091862497591189ff1   worker-2    Running         Running 3 days ago
inel921owq9bjq4zotkz590dz    \_ nginx_nginx.1   nginx:latest@sha256:0b970013351304af46f322da1263516b188318682b2ab1091862497591189ff1   manager-2   Shutdown        Shutdown 3 days ago
y0y5mvj5n44r23b5y548hrvsm   nginx_nginx.2       nginx:latest@sha256:0b970013351304af46f322da1263516b188318682b2ab1091862497591189ff1   worker-1    Running         Running 3 days ago
uk18jo6wwlq6qfrv2lr6zk1xz    \_ nginx_nginx.2   nginx:latest@sha256:0b970013351304af46f322da1263516b188318682b2ab1091862497591189ff1   manager-3   Shutdown        Shutdown 3 days ago
ijbalagf7isyu1drhm0hu8z95   nginx_nginx.3       nginx:latest@sha256:0b970013351304af46f322da1263516b188318682b2ab1091862497591189ff1   worker-1    Running         Running 3 days ago
lqa493b94iu8lpmc8yqtu4jd1   nginx_nginx.4       nginx:latest@sha256:0b970013351304af46f322da1263516b188318682b2ab1091862497591189ff1   worker-2    Running         Running 4 minutes ago

```

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-txc8rjd3xpojvl7ckz8z" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded text" data-clipboard-target="content" data-controller="code"><div class="code-highlight top bottom">txc8rjd3xpojvl7ckz8zgohx9 nginx_nginx.5 nginx:latest@sha256:0b970013351304af46f322da1263516b188318682b2ab1091862497591189ff1 Running Pending 5 minutes ago "no suitable node (3 nodes not available for new tasks; max replicas per node limit exceed)"</div></div></div></div></div></div></div>```text


```

To move the highlighted `Pending` task above to `Running`, you can take either of the following actions:

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-redefine-the-schedul" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content">1. Redefine the scheduling constraints by allowing the cluster to run more than two replicas per node (as defined in the `docker service update` command above).
2. Horizontally scaling the cluster by provisioning additional worker nodes (this will be covered in the next tutorial).

</div></div></div></div>## Auto scaling Docker services (optional)

When talking about scaling container services, "auto scaling" often comes up. Now, the reason why this is a bonus (and optional) step, is because **Docker doesn't really offer any auto scaling mechanisms** (unlike [Kubernetes<span class="whitespace-nowrap"><svg class="relative -top-[1px] ml-1  w-4 h-4 inline"></svg></span>](https://kubernetes.io/)).

Nonetheless, you might be wondering how to introduce some level of automation to help scale in and out Docker services. Let's face it, there is no right answer for this, nor there is any "one size fits all" solution that can help you. Because we cannot auto scale directly with Docker, we must resort to workarounds that might involve third-party tools, custom scripts, etc.

There are some tools out there (such as [Orbiter<span class="whitespace-nowrap"><svg class="relative -top-[1px] ml-1  w-4 h-4 inline"></svg></span>](https://github.com/gianarb/orbiter)) that are designed specifically to fill this gap in Docker. But depending on the use case and auto scaling rules, you could build a custom Docker auto scaler with just a few lines of Bash and a [cronjob](https://betterstack.com/community/guides/linux/cron-jobs-getting-started/)!

Our NGINX service from above currently has five replicas. Regardless of their state and placement policies, let's say we simply want to **add** and **delete** service replicas every time a worker joins or leaves the Docker Swarm cluster, such that we always have two replicas per worker.

Start by building a script to monitor the cluster size and scale the service when necessary. As a superuser, create a new file called "/opt/autoscaler.sh" and open it with your favorite text editor:

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%C2%A0-21" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="px-4 py-[6px] bg-white dark:bg-[#0B0C14] flex items-center rounded-t-md border-b border-neutral-50 dark:border-neutral-800"><div class="text-[15px] font-medium inline align-middle grow"><span class="text-app-small"> </span></div><div class="copy-button hidden sm:flex sm:items-center" data-clipboard-target="confirmation"><button class="text-sm p-1" data-action="click->clipboard#copy"><svg alt="copy code to clipboard" class="m-0 text-neutral-200" height="18" width="18"></svg></button></div></div><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded command" data-clipboard-target="content" data-controller="code"></div></div></div></div></div></div>```command
sudo nano /opt/autoscaler.sh

```

Paste the following text into the file:

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%2Fopt%2Fautoscaler.sh" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="px-4 py-[6px] bg-white dark:bg-[#0B0C14] flex items-center rounded-t-md border-b border-neutral-50 dark:border-neutral-800"><div class="text-[15px] font-medium inline align-middle grow"><span class="text-app-small">/opt/autoscaler.sh</span></div><div class="copy-button hidden sm:flex sm:items-center" data-clipboard-target="confirmation"><button class="text-sm p-1" data-action="click->clipboard#copy"><svg alt="copy code to clipboard" class="m-0 text-neutral-200" height="18" width="18"></svg></button></div></div><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded text" data-clipboard-target="content" data-controller="code"></div></div></div></div></div></div>```text
#!/bin/sh

service_name=nginx_nginx

# 1
## let's see how many workers we have, by listing and counting all
## node IDs corresponding to the workers in the cluster
num_workers=$(docker node ls --filter role=worker -q | wc -l)

# 2
## then, let's infer the current number of replicas our service has
num_replicas=$(docker service inspect $service_name --format '{{json .Spec.Mode.Replicated.Replicas}}')

# 3
## let's then assess how many replicas we should have (2 per node)
let "target_replicas = 2*$num_workers"

# 4
## and finally, let's compare the target replicas
## with the ones we currently have, and if they are different
## we scale the service to the number of target_replicas
if [[ $num_replicas -ne $target_replicas ]]
then
  echo "Autoscaling Docker service ${service_name} to ${target_replicas} replicas"
  docker service scale $service_name=$target_replicas -d
fi

## else, there's nothing to do since we already have
## the desired amount of replicas

```

The above file defines a simplistic auto scaling rule, but applicable nonetheless. Next, you need to run this script periodically via a cronjob (say once every hour). To do that, execute the following command to open the crontab config file in your text editor:

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%C2%A0-22" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="px-4 py-[6px] bg-white dark:bg-[#0B0C14] flex items-center rounded-t-md border-b border-neutral-50 dark:border-neutral-800"><div class="text-[15px] font-medium inline align-middle grow"><span class="text-app-small"> </span></div><div class="copy-button hidden sm:flex sm:items-center" data-clipboard-target="confirmation"><button class="text-sm p-1" data-action="click->clipboard#copy"><svg alt="copy code to clipboard" class="m-0 text-neutral-200" height="18" width="18"></svg></button></div></div><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded command" data-clipboard-target="content" data-controller="code"></div></div></div></div></div></div>```command
crontab -e

```

Add the following line at the end of the file, then save and close it.

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%C2%A0-23" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="px-4 py-[6px] bg-white dark:bg-[#0B0C14] flex items-center rounded-t-md border-b border-neutral-50 dark:border-neutral-800"><div class="text-[15px] font-medium inline align-middle grow"><span class="text-app-small"> </span></div><div class="copy-button hidden sm:flex sm:items-center" data-clipboard-target="confirmation"><button class="text-sm p-1" data-action="click->clipboard#copy"><svg alt="copy code to clipboard" class="m-0 text-neutral-200" height="18" width="18"></svg></button></div></div><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded text" data-clipboard-target="content" data-controller="code"></div></div></div></div></div></div>```text
0 * * * * sh /opt/autoscaler.sh

```

With this setup in place, the `/opt/autoscaler.sh` script will be executed once per hour by the system's `cron` daemon. While this autoscaling infrastructure isn't production quality, it is enough to bootstrap your understanding of how to work around the autoscaling limitations in Docker.

## Conclusion and next steps

In this tutorial, you learned about scaling a Docker Swarm service in and out, and how to undo a scaling operation. You also learned how to inspect a service so that you can make educated decisions about your scaling constraints. Finally, we touched base on auto scaling, giving you some tips on how to automate the scaling operations for your service.

In a future tutorial, we'll learn about horizontally scaling the cluster itself, such that a suitable node shows up to serve the pending task from step five.

*This article was contributed by guest author [Cristovao Cordeiro<span class="whitespace-nowrap"><svg class="relative -top-[1px] ml-1  w-4 h-4 inline"></svg></span>](https://twitter.com/@cristovaojdc), a Docker certified Engineering Manager at Canonical. He's an expert in Containers and ex-CERN engineer with 9+ years of experience in Cloud and Edge computing.*

# Setting up Docker Swarm High Availability in Production

Link: [https://betterstack.com/community/guides/scaling-docker/ha-docker-swarm/](https://betterstack.com/community/guides/scaling-docker/ha-docker-swarm/)

<div class="dark bg-primary-hero" id="bkmrk-dockerhigh-availabil" style="text-align: justify;"><div class="mx-auto pt-4 pb-8 px-7 max-w-[1130px]"><div class="pt-10 md:pt-16 lg:pt-20"><div class="mt-4 flex justify-center text-base flex-wrap">[Docker](https://betterstack.com/tag/docker?utm_content&utm_medium=guides&utm_source=community&utm_term=ha-docker-swarm)[High Availability](https://betterstack.com/tag/high-availability?utm_content&utm_medium=guides&utm_source=community&utm_term=ha-docker-swarm)</div><div class="mt-10 md:mt-16 mt-20 text-center"><div class="text-white">Ayooluwa Isaiah</div><div class="mt-1 uppercase whitespace-nowrap text-xs font-medium text-neutral-300 tracking-[1.56px]">Updated on January 14, 2026</div></div></div></div></div>###### Contents

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-prerequisites-explai" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="sticky hidden xl:block mr-12 shrink-0 w-[190px]" data-toc-target="toc"><div class="text-base text-secondary sticky scroll-smooth overflow-y-auto pretty-scrollbars max-h-screen top-[100px] pb-40"><div class="table-of-contents flat">- [Prerequisites](https://betterstack.com/community/guides/scaling-docker/ha-docker-swarm/#prerequisites)
- [Explaining Docker Swarm terminology](https://betterstack.com/community/guides/scaling-docker/ha-docker-swarm/#explaining-docker-swarm-terminology)
- [Docker Swarm requirements for high availability](https://betterstack.com/community/guides/scaling-docker/ha-docker-swarm/#docker-swarm-requirements-for-high-availability)
- [Step 1 — Installing Docker](https://betterstack.com/community/guides/scaling-docker/ha-docker-swarm/#step-1-installing-docker)
- [Step 2 — Executing the Docker command without sudo](https://betterstack.com/community/guides/scaling-docker/ha-docker-swarm/#step-2-executing-the-docker-command-without-sudo)
- [Step 3 — Initializing the Swarm Cluster](https://betterstack.com/community/guides/scaling-docker/ha-docker-swarm/#step-3-initializing-the-swarm-cluster)
- [Step 4 — Adding worker nodes to the cluster](https://betterstack.com/community/guides/scaling-docker/ha-docker-swarm/#step-4-adding-worker-nodes-to-the-cluster)
- [Step 5 — Adding manager nodes to the cluster](https://betterstack.com/community/guides/scaling-docker/ha-docker-swarm/#step-5-adding-manager-nodes-to-the-cluster)
- [Step 6 — Draining a node on the swarm](https://betterstack.com/community/guides/scaling-docker/ha-docker-swarm/#step-6-draining-a-node-on-the-swarm)
- [Step 7 — Deploying a Highly Available NGINX service](https://betterstack.com/community/guides/scaling-docker/ha-docker-swarm/#step-7-deploying-a-highly-available-nginx-service)
- [Step 8 — Draining the other manager nodes](https://betterstack.com/community/guides/scaling-docker/ha-docker-swarm/#step-8-draining-the-other-manager-nodes)
- [Step 9 — Testing the failover mechanism](https://betterstack.com/community/guides/scaling-docker/ha-docker-swarm/#step-9-testing-the-failover-mechanism)
- [Monitoring your Docker Swarm cluster](https://betterstack.com/community/guides/scaling-docker/ha-docker-swarm/#monitoring-your-docker-swarm-cluster)
- [Final thoughts](https://betterstack.com/community/guides/scaling-docker/ha-docker-swarm/#final-thoughts)

</div></div></div></div></div></div>[Docker Swarm<span class="whitespace-nowrap"><svg class="relative -top-[1px] ml-1  w-4 h-4 inline"></svg></span>](https://docs.docker.com/engine/swarm/) is a container orchestration tool that makes it easy to manage and scale your existing Docker infrastructure. It consists of a pool of Docker hosts that run in Swarm mode with some nodes acting as managers, workers, or both. Using Docker Swarm mode to manage your Docker containers brings the following [benefits<span class="whitespace-nowrap"><svg class="relative -top-[1px] ml-1  w-4 h-4 inline"></svg></span>](https://docs.docker.com/engine/swarm/#feature-highlights):

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-it-allows-you-to-inc" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content">- It allows you to incrementally apply updates with zero downtime.
- It increases application resilience to outages by reconciling any differences between the actual state and your expressed desired state.
- It eases the process of scaling your applications since you only need to define the desired number of replicas in the cluster.
- It is built into the `docker` CLI, so you don't need additional software to get up and running.
- It enables multi-host networking such that containers deployed on different nodes can communicate with each other easily.

</div></div></div></div>In this tutorial, you will learn key concepts in Docker Swarm and set up a highly available Swarm cluster that is resilient to failures. You will also learn some best practices and recommendations to ensure that your Swarm setup is fault tolerant.

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><iframe allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen="allowfullscreen" frameborder="0" height="315" src="https://www.youtube.com/embed/wQKjCDD7nfk" title="YouTube video player" width="100%"></iframe>

</div></div></div></div>## Prerequisites

Before proceeding with this tutorial, ensure that you have access to five Ubuntu 22.04 servers. This is necessary to demonstrate a highly available set up, although it is also possible to run Docker Swarm on a single machine. You also need to configure each server with a user that has administrative privileges.

The following ports must also be available on each server for communication purposes between the nodes. On Ubuntu 22.04, they are open by default:

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-tcp-port-2377-for-cl" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content">- TCP port 2377 for cluster management communications,
- TCP and UDP port 7946 for communication among nodes,
- TCP and UDP port 4789 for overlay network traffic.

</div></div></div></div><div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-centralize-%26-visuali" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content">Centralize &amp; visualize your logs. Query everything with SQL. <div>[<button class="block px-3 py-2 bg-neutral-700 rounded font-medium text-white leading-none whitespace-nowrap">Explore more</button>](https://betterstack.com/telemetry?utm_content=upsell&utm_medium=guides&utm_source=community&utm_term=ha-docker-swarm)</div></div></div></div></div>## Explaining Docker Swarm terminology

Before proceeding with this tutorial, let's examine some terms and definitions in Docker Swarm so that you have enough understanding of what each one means when they are used in this article and in other Docker Swarm resources.

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-node%3A-refers-to-an-i" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content">- **Node**: refers to an instance of the Docker engine in the Swarm cluster.
- **Manager nodes**: they are tasked with handling orchestration and cluster management functions, and dispatching incoming tasks to worker nodes. They can also act as worker nodes unless placed in Drain mode (recommended).
- **Leader**: this is a specific manager node that is elected to perform orchestration tasks and management/maintenance operations by all the manager nodes in the cluster using the [Raft Consensus Algorithm<span class="whitespace-nowrap"><svg class="relative -top-[1px] ml-1  w-4 h-4 inline"></svg></span>](https://raft.github.io/).
- **Worker nodes**: are Docker instances whose sole purpose is to receive and execute Swarm tasks from manager nodes.
- **Swarm task**: refers to a Docker container and the commands that run inside the container. Once a task is assigned to a node, it can run or fail but it cannot be transferred to a different node.
- **Swarm service**: this is the mechanism for defining tasks that should be executed on a node. It involves specifying the container image and commands that should run inside the container.
- **Drain**: means that new tasks are no longer assigned to a node, and existing tasks are reassigned to other available nodes.

</div></div></div></div>## Docker Swarm requirements for high availability

A highly available Docker Swarm setup ensures that if a node fails, services on the failed node are re-provisioned and assigned to other available nodes in the cluster. A Docker Swarm setup that consists of one or two manager nodes is not considered highly available because any incident will cause operations on the cluster to be interrupted. Therefore the minimum number of manager nodes in a highly available Swarm cluster should be three.

The table below shows the number of failures a Swarm cluster can tolerate depending on the number of manager nodes in the cluster:

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-manager-nodes-failur" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="table-container"><table><thead><tr><th>Manager Nodes</th><th>Failures tolerated</th></tr></thead><tbody><tr><td>1</td><td>0</td></tr><tr><td>2</td><td>0</td></tr><tr><td>3</td><td>1</td></tr><tr><td>4</td><td>1</td></tr><tr><td>5</td><td>2</td></tr><tr><td>6</td><td>2</td></tr><tr><td>7</td><td>3</td></tr></tbody></table>

</div></div></div></div></div>As you can see, having an even number of manager nodes does not help with failure tolerance, so you should always maintain an odd number of manager nodes. Fault tolerance improves as you add more manager nodes, but Docker recommends no more than seven managers so that performance is not negatively impacted since each node must acknowledge proposals to update the state of the cluster.

You should also distribute your manager nodes in separate locations so they are not affected by the same outage. If they run on the same server, a hardware problem could cause them all to go down. The high availability Swarm cluster that you will be set up in this tutorial will therefore exhibit the following characteristics:

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-5-total-nodes-%282-wor" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content">- 5 total nodes (2 workers and 3 managers) with each one running on a separate server.
- 2 worker nodes (`worker-1` and `worker-2`).
- 3 manager nodes (`manager-1`, `manager-2`, and `manager-3`).

</div></div></div></div>## Step 1 — Installing Docker

In this step, you will install Docker on all five Ubuntu servers. Therefore, execute all the commands below (and in step 2) on all five servers. If your host offers a snapshot feature, you may be able to run the commands on a single server and use that server as a base for the other four instances.

Let's start by installing the latest version of the Docker Engine (20.10.18 at the time of writing). Go ahead and update the package information list from all configured sources on your system:

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%C2%A0-2" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="px-4 py-[6px] bg-white dark:bg-[#0B0C14] flex items-center rounded-t-md border-b border-neutral-50 dark:border-neutral-800"><div class="text-[15px] font-medium inline align-middle grow"><span class="text-app-small"> </span></div><div class="copy-button hidden sm:flex sm:items-center" data-clipboard-target="confirmation"><button class="text-sm p-1" data-action="click->clipboard#copy"><svg alt="copy code to clipboard" class="m-0 text-neutral-200" height="18" width="18"></svg></button></div></div><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded command" data-clipboard-target="content" data-controller="code"></div></div></div></div></div></div>```command
sudo apt update

```

Afterward, install the following packages to allow `apt` use packages over HTTPS:

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%C2%A0-3" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="px-4 py-[6px] bg-white dark:bg-[#0B0C14] flex items-center rounded-t-md border-b border-neutral-50 dark:border-neutral-800"><div class="text-[15px] font-medium inline align-middle grow"><span class="text-app-small"> </span></div><div class="copy-button hidden sm:flex sm:items-center" data-clipboard-target="confirmation"><button class="text-sm p-1" data-action="click->clipboard#copy"><svg alt="copy code to clipboard" class="m-0 text-neutral-200" height="18" width="18"></svg></button></div></div><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded command" data-clipboard-target="content" data-controller="code"></div></div></div></div></div></div>```command
sudo apt install apt-transport-https ca-certificates curl software-properties-common

```

Next, add the GPG key for the official Docker repository to the server:

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%C2%A0-4" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="px-4 py-[6px] bg-white dark:bg-[#0B0C14] flex items-center rounded-t-md border-b border-neutral-50 dark:border-neutral-800"><div class="text-[15px] font-medium inline align-middle grow"><span class="text-app-small"> </span></div><div class="copy-button hidden sm:flex sm:items-center" data-clipboard-target="confirmation"><button class="text-sm p-1" data-action="click->clipboard#copy"><svg alt="copy code to clipboard" class="m-0 text-neutral-200" height="18" width="18"></svg></button></div></div><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded command" data-clipboard-target="content" data-controller="code"></div></div></div></div></div></div>```command
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg

```

Once the GPG key is added, include the official Docker repository in the server's apt sources list.

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%C2%A0-5" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="px-4 py-[6px] bg-white dark:bg-[#0B0C14] flex items-center rounded-t-md border-b border-neutral-50 dark:border-neutral-800"><div class="text-[15px] font-medium inline align-middle grow"><span class="text-app-small"> </span></div><div class="copy-button hidden sm:flex sm:items-center" data-clipboard-target="confirmation"><button class="text-sm p-1" data-action="click->clipboard#copy"><svg alt="copy code to clipboard" class="m-0 text-neutral-200" height="18" width="18"></svg></button></div></div><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded command" data-clipboard-target="content" data-controller="code"></div></div></div></div></div></div>```command
echo "deb [arch=amd64 signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

```

Finally, update apt once again and install the Docker Engine:

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%C2%A0-6" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="px-4 py-[6px] bg-white dark:bg-[#0B0C14] flex items-center rounded-t-md border-b border-neutral-50 dark:border-neutral-800"><div class="text-[15px] font-medium inline align-middle grow"><span class="text-app-small"> </span></div><div class="copy-button hidden sm:flex sm:items-center" data-clipboard-target="confirmation"><button class="text-sm p-1" data-action="click->clipboard#copy"><svg alt="copy code to clipboard" class="m-0 text-neutral-200" height="18" width="18"></svg></button></div></div><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded command" data-clipboard-target="content" data-controller="code"></div></div></div></div></div></div>```command
sudo apt update

```

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%C2%A0-7" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded command" data-clipboard-target="content" data-controller="code"></div></div><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="px-4 py-[6px] bg-white dark:bg-[#0B0C14] flex items-center rounded-t-md border-b border-neutral-50 dark:border-neutral-800"><div class="text-[15px] font-medium inline align-middle grow"><span class="text-app-small"> </span></div><div class="copy-button hidden sm:flex sm:items-center" data-clipboard-target="confirmation"><button class="text-sm p-1" data-action="click->clipboard#copy"><svg alt="copy code to clipboard" class="m-0 text-neutral-200" height="18" width="18"></svg></button></div></div><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded command" data-clipboard-target="content" data-controller="code"></div></div></div></div></div></div>```command
sudo apt install docker-ce

```

Once the relevant packages are installed, you check the status of the `docker` service using the command below:

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%C2%A0-8" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="px-4 py-[6px] bg-white dark:bg-[#0B0C14] flex items-center rounded-t-md border-b border-neutral-50 dark:border-neutral-800"><div class="text-[15px] font-medium inline align-middle grow"><span class="text-app-small"> </span></div><div class="copy-button hidden sm:flex sm:items-center" data-clipboard-target="confirmation"><button class="text-sm p-1" data-action="click->clipboard#copy"><svg alt="copy code to clipboard" class="m-0 text-neutral-200" height="18" width="18"></svg></button></div></div><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded command" data-clipboard-target="content" data-controller="code"></div></div></div></div></div></div>```command
sudo systemctl status docker

```

If everything goes well, you should observe that the container engine is active and running on your server:

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%C2%A0output" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="px-4 py-[6px] bg-white dark:bg-[#0B0C14] flex items-center rounded-t-md border-b border-neutral-50 dark:border-neutral-800"><div class="text-[15px] font-medium inline align-middle grow"><span class="text-app-small"><svg alt="" class="m-0 -mt-1 inline fill-neutral-200" height="20" width="20"></svg> Output</span></div></div><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded text" data-clipboard-target="content" data-controller="code"></div></div></div></div></div></div>```text
● docker.service - Docker Application Container Engine
     Loaded: loaded (/lib/systemd/system/docker.service; enabled; vendor preset: enabled)
     Active: active (running) since Wed 2022-09-21 10:18:15 UTC; 58s ago
TriggeredBy: ● docker.socket
       Docs: https://docs.docker.com
   Main PID: 25355 (dockerd)
      Tasks: 7
     Memory: 22.2M
        CPU: 346ms
     CGroup: /system.slice/docker.service
             └─25355 /usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock

```

In the next step, we will add the current user to the `docker` group so that you can use the `docker` command without escalating to administrative privileges (using `sudo`) which can lead to security issues.

## Step 2 — Executing the Docker command without sudo

By default, the `docker` command can only be executed by the root user or any user in the `docker` group (auto created on installation). If you execute a `docker` command without prefixing it with `sudo` or running it through a user that belongs to the `docker` group, you will get a permission error that looks like this:

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%C2%A0output-1" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="px-4 py-[6px] bg-white dark:bg-[#0B0C14] flex items-center rounded-t-md border-b border-neutral-50 dark:border-neutral-800"><div class="text-[15px] font-medium inline align-middle grow"><span class="text-app-small"><svg alt="" class="m-0 -mt-1 inline fill-neutral-200" height="20" width="20"></svg> Output</span></div></div><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded text" data-clipboard-target="content" data-controller="code"></div></div></div></div></div></div>```text
Got permission denied while trying to connect to the Docker daemon socket at unix:///var/run/docker.sock: Get "http://%2Fvar%2Frun%2Fdocker.sock/v1.24/containers/json": dial unix /var/run/docker.sock: connect: permission denied

```

As mentioned earlier, using `sudo` with `docker` is a security risk, so the solution to the above error is to add the relevant user to the `docker` group which can be achieved through the command below:

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%C2%A0-9" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="px-4 py-[6px] bg-white dark:bg-[#0B0C14] flex items-center rounded-t-md border-b border-neutral-50 dark:border-neutral-800"><div class="text-[15px] font-medium inline align-middle grow"><span class="text-app-small"> </span></div><div class="copy-button hidden sm:flex sm:items-center" data-clipboard-target="confirmation"><button class="text-sm p-1" data-action="click->clipboard#copy"><svg alt="copy code to clipboard" class="m-0 text-neutral-200" height="18" width="18"></svg></button></div></div><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded command" data-clipboard-target="content" data-controller="code"></div></div></div></div></div></div>```command
sudo usermod -aG docker ${USER}

```

Next, run the following command and enter the user's password when prompted for the changes to take effect:

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%C2%A0-10" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="px-4 py-[6px] bg-white dark:bg-[#0B0C14] flex items-center rounded-t-md border-b border-neutral-50 dark:border-neutral-800"><div class="text-[15px] font-medium inline align-middle grow"><span class="text-app-small"> </span></div><div class="copy-button hidden sm:flex sm:items-center" data-clipboard-target="confirmation"><button class="text-sm p-1" data-action="click->clipboard#copy"><svg alt="copy code to clipboard" class="m-0 text-neutral-200" height="18" width="18"></svg></button></div></div><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded command" data-clipboard-target="content" data-controller="code"></div></div></div></div></div></div>```command
su - ${USER}

```

You should now be able to run `docker` commands without prefixing them with `sudo`. For example, when you run the command below:

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%C2%A0-11" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="px-4 py-[6px] bg-white dark:bg-[#0B0C14] flex items-center rounded-t-md border-b border-neutral-50 dark:border-neutral-800"><div class="text-[15px] font-medium inline align-middle grow"><span class="text-app-small"> </span></div><div class="copy-button hidden sm:flex sm:items-center" data-clipboard-target="confirmation"><button class="text-sm p-1" data-action="click->clipboard#copy"><svg alt="copy code to clipboard" class="m-0 text-neutral-200" height="18" width="18"></svg></button></div></div><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded command" data-clipboard-target="content" data-controller="code"></div></div></div></div></div></div>```command
docker ps

```

You should observe the following output:

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%C2%A0-12" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="px-4 py-[6px] bg-white dark:bg-[#0B0C14] flex items-center rounded-t-md border-b border-neutral-50 dark:border-neutral-800"><div class="text-[15px] font-medium inline align-middle grow"><span class="text-app-small"> </span></div><div class="copy-button hidden sm:flex sm:items-center" data-clipboard-target="confirmation"><button class="text-sm p-1" data-action="click->clipboard#copy"><svg alt="copy code to clipboard" class="m-0 text-neutral-200" height="18" width="18"></svg></button></div></div><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded command" data-clipboard-target="content" data-controller="code"></div></div></div></div></div></div>```command
CONTAINER ID   IMAGE     COMMAND   CREATED   STATUS    PORTS     NAMES


```

Before proceeding to the next step, ensure that all the commands in step 1 and step 2 have been executed on all five servers.

## Step 3 — Initializing the Swarm Cluster

At this point, each of your five Docker instances are acting as separate hosts and not as part of a Swarm cluster. Therefore, in this step, we will initialize the Swarm cluster on the `manager-1` server and add the hosts to the cluster accordingly.

Start by logging into one of the Ubuntu servers (`manager-1`), and retrieve the private IP address of the machine using the following command:

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%C2%A0-13" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="px-4 py-[6px] bg-white dark:bg-[#0B0C14] flex items-center rounded-t-md border-b border-neutral-50 dark:border-neutral-800"><div class="text-[15px] font-medium inline align-middle grow"><span class="text-app-small"> </span></div><div class="copy-button hidden sm:flex sm:items-center" data-clipboard-target="confirmation"><button class="text-sm p-1" data-action="click->clipboard#copy"><svg alt="copy code to clipboard" class="m-0 text-neutral-200" height="18" width="18"></svg></button></div></div><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded command" data-clipboard-target="content" data-controller="code"></div></div></div></div></div></div>```command
hostname -I | awk '{print $1}'

```

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%C2%A0output-2" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded command" data-clipboard-target="content" data-controller="code"></div></div><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="px-4 py-[6px] bg-white dark:bg-[#0B0C14] flex items-center rounded-t-md border-b border-neutral-50 dark:border-neutral-800"><div class="text-[15px] font-medium inline align-middle grow"><span class="text-app-small"><svg alt="" class="m-0 -mt-1 inline fill-neutral-200" height="20" width="20"></svg> Output</span></div></div><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded text" data-clipboard-target="content" data-controller="code"></div></div></div></div></div></div>```text
<manager_1_server_ip>

```

Copy the IP address to your clipboard and replace the `<manager_1_server_ip>` placeholder in the command below to initialize Swarm mode:

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%C2%A0-14" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="px-4 py-[6px] bg-white dark:bg-[#0B0C14] flex items-center rounded-t-md border-b border-neutral-50 dark:border-neutral-800"><div class="text-[15px] font-medium inline align-middle grow"><span class="text-app-small"> </span></div><div class="copy-button hidden sm:flex sm:items-center" data-clipboard-target="confirmation"><button class="text-sm p-1" data-action="click->clipboard#copy"><svg alt="copy code to clipboard" class="m-0 text-neutral-200" height="18" width="18"></svg></button></div></div><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded command" data-clipboard-target="content" data-controller="code"></div></div></div></div></div></div>```command
docker swarm init --advertise-addr <manager_1_server_ip>

```

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%C2%A0output-3" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded command" data-clipboard-target="content" data-controller="code"></div></div><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="px-4 py-[6px] bg-white dark:bg-[#0B0C14] flex items-center rounded-t-md border-b border-neutral-50 dark:border-neutral-800"><div class="text-[15px] font-medium inline align-middle grow"><span class="text-app-small"><svg alt="" class="m-0 -mt-1 inline fill-neutral-200" height="20" width="20"></svg> Output</span></div></div><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded text" data-clipboard-target="content" data-controller="code"></div></div></div></div></div></div>```text
Swarm initialized: current node (9r83zto8qpqiazt6slxfkjypq) is now a manager.

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


```

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-docker-swarm-join---" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded text" data-clipboard-target="content" data-controller="code"><div class="code-highlight top bottom">docker swarm join --token &lt;token&gt; &lt;manager_1_server_ip&gt;:&lt;port&gt;</div></div></div></div></div></div></div>```text


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

```

The command above enables Swarm mode on the node and configures it as the first manager of the cluster. Ensure to copy the entire command to your clipboard (and replace the placeholders) as it will be utilized in the next section.

You can view the current state of the Swarm using the command below:

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%C2%A0-15" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="px-4 py-[6px] bg-white dark:bg-[#0B0C14] flex items-center rounded-t-md border-b border-neutral-50 dark:border-neutral-800"><div class="text-[15px] font-medium inline align-middle grow"><span class="text-app-small"> </span></div><div class="copy-button hidden sm:flex sm:items-center" data-clipboard-target="confirmation"><button class="text-sm p-1" data-action="click->clipboard#copy"><svg alt="copy code to clipboard" class="m-0 text-neutral-200" height="18" width="18"></svg></button></div></div><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded command" data-clipboard-target="content" data-controller="code"></div></div></div></div></div></div>```command
docker info

```

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%C2%A0output-4" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded command" data-clipboard-target="content" data-controller="code"></div></div><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="px-4 py-[6px] bg-white dark:bg-[#0B0C14] flex items-center rounded-t-md border-b border-neutral-50 dark:border-neutral-800"><div class="text-[15px] font-medium inline align-middle grow"><span class="text-app-small"><svg alt="" class="m-0 -mt-1 inline fill-neutral-200" height="20" width="20"></svg> Output</span></div></div><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded text" data-clipboard-target="content" data-controller="code"></div></div></div></div></div></div>```text
. . .
 Swarm: active
  NodeID: 9r83zto8qpqiazt6slxfkjypq
  Is Manager: true
  ClusterID: q6laywz9u8xlis9wlkbzap8i0
  Managers: 1
  Nodes: 1
. . .

```

You can also use the command below to view information regarding the nodes on the cluster:

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%C2%A0-16" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="px-4 py-[6px] bg-white dark:bg-[#0B0C14] flex items-center rounded-t-md border-b border-neutral-50 dark:border-neutral-800"><div class="text-[15px] font-medium inline align-middle grow"><span class="text-app-small"> </span></div><div class="copy-button hidden sm:flex sm:items-center" data-clipboard-target="confirmation"><button class="text-sm p-1" data-action="click->clipboard#copy"><svg alt="copy code to clipboard" class="m-0 text-neutral-200" height="18" width="18"></svg></button></div></div><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded command" data-clipboard-target="content" data-controller="code"></div></div></div></div></div></div>```command
docker node ls

```

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%C2%A0output-5" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded command" data-clipboard-target="content" data-controller="code"></div></div><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="px-4 py-[6px] bg-white dark:bg-[#0B0C14] flex items-center rounded-t-md border-b border-neutral-50 dark:border-neutral-800"><div class="text-[15px] font-medium inline align-middle grow"><span class="text-app-small"><svg alt="" class="m-0 -mt-1 inline fill-neutral-200" height="20" width="20"></svg> Output</span></div></div><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded text" data-clipboard-target="content" data-controller="code"></div></div></div></div></div></div>```text
ID                            HOSTNAME    STATUS    AVAILABILITY   MANAGER STATUS   ENGINE VERSION
9r83zto8qpqiazt6slxfkjypq *   manager-1   Ready     Active         Leader           20.10.18

```

The `*` next to the node ID indicates that you're currently connected to this node. Here's the meaning of the other values:

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-ready%3A-the-node-is-r" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content">- **Ready**: the node is recognized by the manager and can participate in the cluster.
- **Active**: the node is used as a worker also to run Docker containers.
- **Leader**: the node is a manager node and is also the cluster's leader.

</div></div></div></div>In the next section of this tutorial, we will add two workers to our cluster bringing the total nodes to three.

## Step 4 — Adding worker nodes to the cluster

Adding worker modes to a cluster can be done by running the command copied from step 3 above (the `docker swarm init` output) on the `worker-1` and `worker-2` servers:

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%C2%A0-17" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="px-4 py-[6px] bg-white dark:bg-[#0B0C14] flex items-center rounded-t-md border-b border-neutral-50 dark:border-neutral-800"><div class="text-[15px] font-medium inline align-middle grow"><span class="text-app-small"> </span></div><div class="copy-button hidden sm:flex sm:items-center" data-clipboard-target="confirmation"><button class="text-sm p-1" data-action="click->clipboard#copy"><svg alt="copy code to clipboard" class="m-0 text-neutral-200" height="18" width="18"></svg></button></div></div><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded command" data-clipboard-target="content" data-controller="code"></div></div></div></div></div></div>```command
docker swarm join --token <token> <manager_1_server_ip>:<port>

```

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%C2%A0output-6" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded command" data-clipboard-target="content" data-controller="code"></div></div><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="px-4 py-[6px] bg-white dark:bg-[#0B0C14] flex items-center rounded-t-md border-b border-neutral-50 dark:border-neutral-800"><div class="text-[15px] font-medium inline align-middle grow"><span class="text-app-small"><svg alt="" class="m-0 -mt-1 inline fill-neutral-200" height="20" width="20"></svg> Output</span></div></div><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded text" data-clipboard-target="content" data-controller="code"></div></div></div></div></div></div>```text
This node joined a swarm as a worker.

```

If you forgot to copy the `join` command for workers, use the command below on the `manager-1` server to retrieve it:

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%C2%A0-18" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="px-4 py-[6px] bg-white dark:bg-[#0B0C14] flex items-center rounded-t-md border-b border-neutral-50 dark:border-neutral-800"><div class="text-[15px] font-medium inline align-middle grow"><span class="text-app-small"> </span></div><div class="copy-button hidden sm:flex sm:items-center" data-clipboard-target="confirmation"><button class="text-sm p-1" data-action="click->clipboard#copy"><svg alt="copy code to clipboard" class="m-0 text-neutral-200" height="18" width="18"></svg></button></div></div><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded command" data-clipboard-target="content" data-controller="code"></div></div></div></div></div></div>```command
docker swarm join-token worker

```

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%C2%A0output-7" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded command" data-clipboard-target="content" data-controller="code"></div></div><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="px-4 py-[6px] bg-white dark:bg-[#0B0C14] flex items-center rounded-t-md border-b border-neutral-50 dark:border-neutral-800"><div class="text-[15px] font-medium inline align-middle grow"><span class="text-app-small"><svg alt="" class="m-0 -mt-1 inline fill-neutral-200" height="20" width="20"></svg> Output</span></div></div><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded text" data-clipboard-target="content" data-controller="code"></div></div></div></div></div></div>```text
To add a worker to this swarm, run the following command:


```

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-docker-swarm-join----2" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded text" data-clipboard-target="content" data-controller="code"><div class="code-highlight top bottom">docker swarm join --token &lt;token&gt; &lt;manager_1_server_ip&gt;:&lt;port&gt;</div></div></div></div></div></div></div>```text


```

After executing the `join` command on each worker node, you should be able to see the updated list of Swarm nodes when you run the command below on your `manager-1` server:

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%C2%A0-19" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="px-4 py-[6px] bg-white dark:bg-[#0B0C14] flex items-center rounded-t-md border-b border-neutral-50 dark:border-neutral-800"><div class="text-[15px] font-medium inline align-middle grow"><span class="text-app-small"> </span></div><div class="copy-button hidden sm:flex sm:items-center" data-clipboard-target="confirmation"><button class="text-sm p-1" data-action="click->clipboard#copy"><svg alt="copy code to clipboard" class="m-0 text-neutral-200" height="18" width="18"></svg></button></div></div><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded command" data-clipboard-target="content" data-controller="code"></div></div></div></div></div></div>```command
 docker node ls

```

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%C2%A0output-8" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded command" data-clipboard-target="content" data-controller="code"></div></div><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="px-4 py-[6px] bg-white dark:bg-[#0B0C14] flex items-center rounded-t-md border-b border-neutral-50 dark:border-neutral-800"><div class="text-[15px] font-medium inline align-middle grow"><span class="text-app-small"><svg alt="" class="m-0 -mt-1 inline fill-neutral-200" height="20" width="20"></svg> Output</span></div></div><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded text" data-clipboard-target="content" data-controller="code"></div></div></div></div></div></div>```text
ID                            HOSTNAME    STATUS    AVAILABILITY   MANAGER STATUS   ENGINE VERSION
9r83zto8qpqiazt6slxfkjypq *   manager-1   Ready     Active         Leader           20.10.18
kaq8r9gec4t58yc9oh3dc0r2d     worker-1    Ready     Active                          20.10.18
vk1224zd81xcihgm1iis2703z     worker-2    Ready     Active                          20.10.18

```

The empty `MANAGER` column for the `worker-1` and `worker-2` nodes identifies them as worker nodes. Note that you can promote a worker node to a manager mode by using the command below:

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%C2%A0-20" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="px-4 py-[6px] bg-white dark:bg-[#0B0C14] flex items-center rounded-t-md border-b border-neutral-50 dark:border-neutral-800"><div class="text-[15px] font-medium inline align-middle grow"><span class="text-app-small"> </span></div><div class="copy-button hidden sm:flex sm:items-center" data-clipboard-target="confirmation"><button class="text-sm p-1" data-action="click->clipboard#copy"><svg alt="copy code to clipboard" class="m-0 text-neutral-200" height="18" width="18"></svg></button></div></div><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded command" data-clipboard-target="content" data-controller="code"></div></div></div></div></div></div>```command
docker node promote <worker_node_id>

```

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%C2%A0output-9" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded command" data-clipboard-target="content" data-controller="code"></div></div><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="px-4 py-[6px] bg-white dark:bg-[#0B0C14] flex items-center rounded-t-md border-b border-neutral-50 dark:border-neutral-800"><div class="text-[15px] font-medium inline align-middle grow"><span class="text-app-small"><svg alt="" class="m-0 -mt-1 inline fill-neutral-200" height="20" width="20"></svg> Output</span></div></div><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded text" data-clipboard-target="content" data-controller="code"></div></div></div></div></div></div>```text
Node <worker_node_id> promoted to a manager in the swarm.

```

## Step 5 — Adding manager nodes to the cluster

In this section, you will add the remaining two nodes to the cluster as managers. This time, you need to retrieve the `join` command for manager nodes by running the command below on the `manager-1` server:

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%C2%A0-21" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="px-4 py-[6px] bg-white dark:bg-[#0B0C14] flex items-center rounded-t-md border-b border-neutral-50 dark:border-neutral-800"><div class="text-[15px] font-medium inline align-middle grow"><span class="text-app-small"> </span></div><div class="copy-button hidden sm:flex sm:items-center" data-clipboard-target="confirmation"><button class="text-sm p-1" data-action="click->clipboard#copy"><svg alt="copy code to clipboard" class="m-0 text-neutral-200" height="18" width="18"></svg></button></div></div><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded command" data-clipboard-target="content" data-controller="code"></div></div></div></div></div></div>```command
docker swarm join-token manager

```

Output:

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%C2%A0output-10" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="px-4 py-[6px] bg-white dark:bg-[#0B0C14] flex items-center rounded-t-md border-b border-neutral-50 dark:border-neutral-800"><div class="text-[15px] font-medium inline align-middle grow"><span class="text-app-small"><svg alt="" class="m-0 -mt-1 inline fill-neutral-200" height="20" width="20"></svg> Output</span></div></div><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded text" data-clipboard-target="content" data-controller="code"></div></div></div></div></div></div>```text
To add a manager to this swarm, run the following command:

    docker swarm join --token <token> <manager_1_server_ip>:<port>

```

Copy the generated command above and execute it on each additional manager nodes (`manager-2` and `manager-3`) as shown below:

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%C2%A0-22" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="px-4 py-[6px] bg-white dark:bg-[#0B0C14] flex items-center rounded-t-md border-b border-neutral-50 dark:border-neutral-800"><div class="text-[15px] font-medium inline align-middle grow"><span class="text-app-small"> </span></div><div class="copy-button hidden sm:flex sm:items-center" data-clipboard-target="confirmation"><button class="text-sm p-1" data-action="click->clipboard#copy"><svg alt="copy code to clipboard" class="m-0 text-neutral-200" height="18" width="18"></svg></button></div></div><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded command" data-clipboard-target="content" data-controller="code"></div></div></div></div></div></div>```command
docker swarm join --token <token> <manager_1_server_ip>:<port>

```

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%C2%A0output-11" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded command" data-clipboard-target="content" data-controller="code"></div></div><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="px-4 py-[6px] bg-white dark:bg-[#0B0C14] flex items-center rounded-t-md border-b border-neutral-50 dark:border-neutral-800"><div class="text-[15px] font-medium inline align-middle grow"><span class="text-app-small"><svg alt="" class="m-0 -mt-1 inline fill-neutral-200" height="20" width="20"></svg> Output</span></div></div><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded text" data-clipboard-target="content" data-controller="code"></div></div></div></div></div></div>```text
This node joined a swarm as a manager.

```

Finally, verify the status of the cluster nodes using the following command:

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%C2%A0-23" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="px-4 py-[6px] bg-white dark:bg-[#0B0C14] flex items-center rounded-t-md border-b border-neutral-50 dark:border-neutral-800"><div class="text-[15px] font-medium inline align-middle grow"><span class="text-app-small"> </span></div><div class="copy-button hidden sm:flex sm:items-center" data-clipboard-target="confirmation"><button class="text-sm p-1" data-action="click->clipboard#copy"><svg alt="copy code to clipboard" class="m-0 text-neutral-200" height="18" width="18"></svg></button></div></div><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded command" data-clipboard-target="content" data-controller="code"></div></div></div></div></div></div>```command
docker node ls

```

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%C2%A0output-12" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded command" data-clipboard-target="content" data-controller="code"></div></div><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="px-4 py-[6px] bg-white dark:bg-[#0B0C14] flex items-center rounded-t-md border-b border-neutral-50 dark:border-neutral-800"><div class="text-[15px] font-medium inline align-middle grow"><span class="text-app-small"><svg alt="" class="m-0 -mt-1 inline fill-neutral-200" height="20" width="20"></svg> Output</span></div></div><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded text" data-clipboard-target="content" data-controller="code"></div></div></div></div></div></div>```text
ID                            HOSTNAME    STATUS    AVAILABILITY   MANAGER STATUS   ENGINE VERSION
9r83zto8qpqiazt6slxfkjypq *   manager-1   Ready     Active         Leader           20.10.18
uspt9qwqnzqwl78gbxc7omja7     manager-2   Ready     Active         Reachable        20.10.18
txrdxwuwjpg5jjfer3bcmtc5r     manager-3   Ready     Active         Reachable        20.10.18
kaq8r9gec4t58yc9oh3dc0r2d     worker-1    Ready     Active                          20.10.18
vk1224zd81xcihgm1iis2703z     worker-2    Ready     Active                          20.10.18

```

Note that you can also demote a manager node to a worker as follows:

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%C2%A0-24" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="px-4 py-[6px] bg-white dark:bg-[#0B0C14] flex items-center rounded-t-md border-b border-neutral-50 dark:border-neutral-800"><div class="text-[15px] font-medium inline align-middle grow"><span class="text-app-small"> </span></div><div class="copy-button hidden sm:flex sm:items-center" data-clipboard-target="confirmation"><button class="text-sm p-1" data-action="click->clipboard#copy"><svg alt="copy code to clipboard" class="m-0 text-neutral-200" height="18" width="18"></svg></button></div></div><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded command" data-clipboard-target="content" data-controller="code"></div></div></div></div></div></div>```command
docker node demote <manager_node_id>

```

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%C2%A0output-13" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded command" data-clipboard-target="content" data-controller="code"></div></div><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="px-4 py-[6px] bg-white dark:bg-[#0B0C14] flex items-center rounded-t-md border-b border-neutral-50 dark:border-neutral-800"><div class="text-[15px] font-medium inline align-middle grow"><span class="text-app-small"><svg alt="" class="m-0 -mt-1 inline fill-neutral-200" height="20" width="20"></svg> Output</span></div></div><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded text" data-clipboard-target="content" data-controller="code"></div></div></div></div></div></div>```text
Manager <manager_node_id> demoted in the swarm.

```

## Step 6 — Draining a node on the swarm

At the moment, all five nodes in the swarm cluster are running with `Active` availability. This means they are all available to accept new tasks from the swarm manager (including the leader). If you want to avoid scheduling tasks on a node, you need to `drain` it such that no new tasks are assigned to it, and existing tasks are stopped and relaunched on a replica node with `Active` availability.

In this section, you will drain the manager node so that it is no longer able to receive new tasks, which should help to improve its performance since no resources will be allocated towards running Docker containers.

Before you can drain a node, you need to figure out ID of the node to be drained using the following command on the `manager-1` server:

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%C2%A0-25" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="px-4 py-[6px] bg-white dark:bg-[#0B0C14] flex items-center rounded-t-md border-b border-neutral-50 dark:border-neutral-800"><div class="text-[15px] font-medium inline align-middle grow"><span class="text-app-small"> </span></div><div class="copy-button hidden sm:flex sm:items-center" data-clipboard-target="confirmation"><button class="text-sm p-1" data-action="click->clipboard#copy"><svg alt="copy code to clipboard" class="m-0 text-neutral-200" height="18" width="18"></svg></button></div></div><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded command" data-clipboard-target="content" data-controller="code"></div></div></div></div></div></div>```command
docker node ls

```

Copy the ID of the `Leader` node:

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%C2%A0output-14" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="px-4 py-[6px] bg-white dark:bg-[#0B0C14] flex items-center rounded-t-md border-b border-neutral-50 dark:border-neutral-800"><div class="text-[15px] font-medium inline align-middle grow"><span class="text-app-small"><svg alt="" class="m-0 -mt-1 inline fill-neutral-200" height="20" width="20"></svg> Output</span></div></div><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded text" data-clipboard-target="content" data-controller="code"></div></div></div></div></div></div>```text
ID                            HOSTNAME    STATUS    AVAILABILITY   MANAGER STATUS   ENGINE VERSION
9r83zto8qpqiazt6slxfkjypq *   manager-1   Ready     Active         Leader           20.10.18
. . .

```

Next, update the node availability using the below command:

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%C2%A0-26" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="px-4 py-[6px] bg-white dark:bg-[#0B0C14] flex items-center rounded-t-md border-b border-neutral-50 dark:border-neutral-800"><div class="text-[15px] font-medium inline align-middle grow"><span class="text-app-small"> </span></div><div class="copy-button hidden sm:flex sm:items-center" data-clipboard-target="confirmation"><button class="text-sm p-1" data-action="click->clipboard#copy"><svg alt="copy code to clipboard" class="m-0 text-neutral-200" height="18" width="18"></svg></button></div></div><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded command" data-clipboard-target="content" data-controller="code"></div></div></div></div></div></div>```command
docker node update  --availability drain <leader_node_id>

```

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%C2%A0output-15" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded command" data-clipboard-target="content" data-controller="code"></div></div><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="px-4 py-[6px] bg-white dark:bg-[#0B0C14] flex items-center rounded-t-md border-b border-neutral-50 dark:border-neutral-800"><div class="text-[15px] font-medium inline align-middle grow"><span class="text-app-small"><svg alt="" class="m-0 -mt-1 inline fill-neutral-200" height="20" width="20"></svg> Output</span></div></div><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded text" data-clipboard-target="content" data-controller="code"></div></div></div></div></div></div>```text
<leader_node_id>

```

When you run `docker node ls` once more, you should observe that the `AVAILABILITY` of the `Leader` node has been changed to `Drain`:

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%C2%A0-27" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="px-4 py-[6px] bg-white dark:bg-[#0B0C14] flex items-center rounded-t-md border-b border-neutral-50 dark:border-neutral-800"><div class="text-[15px] font-medium inline align-middle grow"><span class="text-app-small"> </span></div><div class="copy-button hidden sm:flex sm:items-center" data-clipboard-target="confirmation"><button class="text-sm p-1" data-action="click->clipboard#copy"><svg alt="copy code to clipboard" class="m-0 text-neutral-200" height="18" width="18"></svg></button></div></div><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded command" data-clipboard-target="content" data-controller="code"></div></div></div></div></div></div>```command
docker node ls

```

Output:

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%C2%A0output-16" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="px-4 py-[6px] bg-white dark:bg-[#0B0C14] flex items-center rounded-t-md border-b border-neutral-50 dark:border-neutral-800"><div class="text-[15px] font-medium inline align-middle grow"><span class="text-app-small"><svg alt="" class="m-0 -mt-1 inline fill-neutral-200" height="20" width="20"></svg> Output</span></div></div><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded text" data-clipboard-target="content" data-controller="code"></div></div></div></div></div></div>```text
ID                            HOSTNAME    STATUS    AVAILABILITY   MANAGER STATUS   ENGINE VERSION
9r83zto8qpqiazt6slxfkjypq *   manager-1   Ready     Drain          Leader           20.10.18
uspt9qwqnzqwl78gbxc7omja7     manager-2   Ready     Active         Reachable        20.10.18
txrdxwuwjpg5jjfer3bcmtc5r     manager-3   Ready     Active         Reachable        20.10.18
kaq8r9gec4t58yc9oh3dc0r2d     worker-1    Ready     Active                          20.10.18
vk1224zd81xcihgm1iis2703z     worker-2    Ready     Active                          20.10.18

```

You can also use the `docker node inspect` command to check the availability of a node:

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%C2%A0-28" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="px-4 py-[6px] bg-white dark:bg-[#0B0C14] flex items-center rounded-t-md border-b border-neutral-50 dark:border-neutral-800"><div class="text-[15px] font-medium inline align-middle grow"><span class="text-app-small"> </span></div><div class="copy-button hidden sm:flex sm:items-center" data-clipboard-target="confirmation"><button class="text-sm p-1" data-action="click->clipboard#copy"><svg alt="copy code to clipboard" class="m-0 text-neutral-200" height="18" width="18"></svg></button></div></div><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded command" data-clipboard-target="content" data-controller="code"></div></div></div></div></div></div>```command
docker node inspect --pretty <node_id>

```

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%C2%A0output-17" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded command" data-clipboard-target="content" data-controller="code"></div></div><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="px-4 py-[6px] bg-white dark:bg-[#0B0C14] flex items-center rounded-t-md border-b border-neutral-50 dark:border-neutral-800"><div class="text-[15px] font-medium inline align-middle grow"><span class="text-app-small"><svg alt="" class="m-0 -mt-1 inline fill-neutral-200" height="20" width="20"></svg> Output</span></div></div><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded text" data-clipboard-target="content" data-controller="code"></div></div></div></div></div></div>```text
ID:                     <node_id>
Hostname:               manager-1
Joined at:              2022-09-21 11:07:08.730840341 +0000 utc
Status:
 State:                 Ready

```

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-availability%3A-drain" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded text" data-clipboard-target="content" data-controller="code"><div class="code-highlight top bottom">Availability: Drain</div></div></div></div></div></div></div>```text

 Address:               116.203.21.130
Manager Status:
 Address:               <ip_address>
 Raft Status:           Reachable
 Leader:                Yes

. . .

```

If you change your mind about draining a node, you can return it to an active state by executing the following command:

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%C2%A0output-18" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="px-4 py-[6px] bg-white dark:bg-[#0B0C14] flex items-center rounded-t-md border-b border-neutral-50 dark:border-neutral-800"><div class="text-[15px] font-medium inline align-middle grow"><span class="text-app-small"><svg alt="" class="m-0 -mt-1 inline fill-neutral-200" height="20" width="20"></svg> Output</span></div></div><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded text" data-clipboard-target="content" data-controller="code"></div></div></div></div></div></div>```text
docker node update  --availability active <node_id>

```

## Step 7 — Deploying a Highly Available NGINX service

In this section, you will deploy a service to the running cluster using a High Availability Swarm configuration. We'll be utilizing the [official NGINX docker image<span class="whitespace-nowrap"><svg class="relative -top-[1px] ml-1  w-4 h-4 inline"></svg></span>](https://hub.docker.com/_/nginx) for demonstration purposes, but you can use any Docker image you want.

Start by creating the compose file for the `nginx` service on the `manager-1` server with all the necessary configurations for High Availability mode.

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%C2%A0-29" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="px-4 py-[6px] bg-white dark:bg-[#0B0C14] flex items-center rounded-t-md border-b border-neutral-50 dark:border-neutral-800"><div class="text-[15px] font-medium inline align-middle grow"><span class="text-app-small"> </span></div><div class="copy-button hidden sm:flex sm:items-center" data-clipboard-target="confirmation"><button class="text-sm p-1" data-action="click->clipboard#copy"><svg alt="copy code to clipboard" class="m-0 text-neutral-200" height="18" width="18"></svg></button></div></div><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded command" data-clipboard-target="content" data-controller="code"></div></div></div></div></div></div>```command
nano nginx.yaml

```

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-nginx.yaml" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded command" data-clipboard-target="content" data-controller="code"></div></div><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="px-4 py-[6px] bg-white dark:bg-[#0B0C14] flex items-center rounded-t-md border-b border-neutral-50 dark:border-neutral-800"><div class="text-[15px] font-medium inline align-middle grow"><span class="text-app-small">nginx.yaml</span></div><div class="copy-button hidden sm:flex sm:items-center" data-clipboard-target="confirmation"><button class="text-sm p-1" data-action="click->clipboard#copy"><svg alt="copy code to clipboard" class="m-0 text-neutral-200" height="18" width="18"></svg></button></div></div><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded yaml" data-clipboard-target="content" data-controller="code"></div></div></div></div></div></div>```yaml
version: '3.7'

networks:
  nginx:
    external: false

services:

  # --- NGINX ---
  nginx:
      image: nginx:latest
      ports:
        - '8088:80'
      deploy:
        replicas: 4
        update_config:
          parallelism: 2
          order: start-first
          failure_action: rollback
          delay: 10s
        rollback_config:
          parallelism: 0
          order: stop-first
        restart_policy:
          condition: any
          delay: 5s
          max_attempts: 3
          window: 120s
      healthcheck:
        test: ["CMD", "service", "nginx", "status"]
      networks:
        - nginx

```

The above file configures an `nginx` service with four replicas. Updates to the containers will be carried out in batches (two at a time) with a wait time of 10 seconds before updating the next batch. If an update failure is detected, it will roll back to the previous configuration. Please see the [Compose file reference<span class="whitespace-nowrap"><svg class="relative -top-[1px] ml-1  w-4 h-4 inline"></svg></span>](https://docs.docker.com/compose/compose-file/) for more information.

Go ahead and deploy the NGINX stack on the `manager-1` node using the command below:

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%C2%A0-30" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="px-4 py-[6px] bg-white dark:bg-[#0B0C14] flex items-center rounded-t-md border-b border-neutral-50 dark:border-neutral-800"><div class="text-[15px] font-medium inline align-middle grow"><span class="text-app-small"> </span></div><div class="copy-button hidden sm:flex sm:items-center" data-clipboard-target="confirmation"><button class="text-sm p-1" data-action="click->clipboard#copy"><svg alt="copy code to clipboard" class="m-0 text-neutral-200" height="18" width="18"></svg></button></div></div><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded command" data-clipboard-target="content" data-controller="code"></div></div></div></div></div></div>```command
docker stack deploy -c nginx.yaml nginx

```

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%C2%A0output-19" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded command" data-clipboard-target="content" data-controller="code"></div></div><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="px-4 py-[6px] bg-white dark:bg-[#0B0C14] flex items-center rounded-t-md border-b border-neutral-50 dark:border-neutral-800"><div class="text-[15px] font-medium inline align-middle grow"><span class="text-app-small"><svg alt="" class="m-0 -mt-1 inline fill-neutral-200" height="20" width="20"></svg> Output</span></div></div><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded text" data-clipboard-target="content" data-controller="code"></div></div></div></div></div></div>```text
Creating network nginx_nginx
Creating service nginx_nginx

```

Once you deploy the stack, you will be able to see a list of running services on the cluster using the command below:

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%C2%A0-31" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="px-4 py-[6px] bg-white dark:bg-[#0B0C14] flex items-center rounded-t-md border-b border-neutral-50 dark:border-neutral-800"><div class="text-[15px] font-medium inline align-middle grow"><span class="text-app-small"> </span></div><div class="copy-button hidden sm:flex sm:items-center" data-clipboard-target="confirmation"><button class="text-sm p-1" data-action="click->clipboard#copy"><svg alt="copy code to clipboard" class="m-0 text-neutral-200" height="18" width="18"></svg></button></div></div><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded command" data-clipboard-target="content" data-controller="code"></div></div></div></div></div></div>```command
docker service ls

```

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%C2%A0output-20" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded command" data-clipboard-target="content" data-controller="code"></div></div><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="px-4 py-[6px] bg-white dark:bg-[#0B0C14] flex items-center rounded-t-md border-b border-neutral-50 dark:border-neutral-800"><div class="text-[15px] font-medium inline align-middle grow"><span class="text-app-small"><svg alt="" class="m-0 -mt-1 inline fill-neutral-200" height="20" width="20"></svg> Output</span></div></div><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded text" data-clipboard-target="content" data-controller="code"></div></div></div></div></div></div>```text
ID             NAME          MODE         REPLICAS   IMAGE          PORTS
xh24wj31z4ml   nginx_nginx   replicated   4/4        nginx:latest   *:8088->80/tcp

```

You can also see which nodes are running the service:

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%C2%A0-32" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="px-4 py-[6px] bg-white dark:bg-[#0B0C14] flex items-center rounded-t-md border-b border-neutral-50 dark:border-neutral-800"><div class="text-[15px] font-medium inline align-middle grow"><span class="text-app-small"> </span></div><div class="copy-button hidden sm:flex sm:items-center" data-clipboard-target="confirmation"><button class="text-sm p-1" data-action="click->clipboard#copy"><svg alt="copy code to clipboard" class="m-0 text-neutral-200" height="18" width="18"></svg></button></div></div><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded command" data-clipboard-target="content" data-controller="code"></div></div></div></div></div></div>```command
docker service ps <service_id>

```

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%C2%A0output-21" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded command" data-clipboard-target="content" data-controller="code"></div></div><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="px-4 py-[6px] bg-white dark:bg-[#0B0C14] flex items-center rounded-t-md border-b border-neutral-50 dark:border-neutral-800"><div class="text-[15px] font-medium inline align-middle grow"><span class="text-app-small"><svg alt="" class="m-0 -mt-1 inline fill-neutral-200" height="20" width="20"></svg> Output</span></div></div><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded text" data-clipboard-target="content" data-controller="code"></div></div></div></div></div></div>```text
ID             NAME            IMAGE          NODE        DESIRED STATE   CURRENT STATE           ERROR     PORTS
inel921owq9b   nginx_nginx.1   nginx:latest   manager-2   Running         Running 2 minutes ago
uk18jo6wwlq6   nginx_nginx.2   nginx:latest   manager-3   Running         Running 2 minutes ago
ijbalagf7isy   nginx_nginx.3   nginx:latest   worker-1    Running         Running 2 minutes ago
drgu007baw8z   nginx_nginx.4   nginx:latest   worker-2    Running         Running 2 minutes ago

```

Each replica runs on the four `Active` nodes in this case. The `DESIRED STATE` and `CURRENT STATE` columns lets you determine the tasks are running according to the service definition.

If you want to see details about the container for a task, run `docker ps` on the relevant node. For example, on `manager-3`:

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%C2%A0-33" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="px-4 py-[6px] bg-white dark:bg-[#0B0C14] flex items-center rounded-t-md border-b border-neutral-50 dark:border-neutral-800"><div class="text-[15px] font-medium inline align-middle grow"><span class="text-app-small"> </span></div><div class="copy-button hidden sm:flex sm:items-center" data-clipboard-target="confirmation"><button class="text-sm p-1" data-action="click->clipboard#copy"><svg alt="copy code to clipboard" class="m-0 text-neutral-200" height="18" width="18"></svg></button></div></div><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded command" data-clipboard-target="content" data-controller="code"></div></div></div></div></div></div>```command
docker ps

```

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%C2%A0output-22" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded command" data-clipboard-target="content" data-controller="code"></div></div><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="px-4 py-[6px] bg-white dark:bg-[#0B0C14] flex items-center rounded-t-md border-b border-neutral-50 dark:border-neutral-800"><div class="text-[15px] font-medium inline align-middle grow"><span class="text-app-small"><svg alt="" class="m-0 -mt-1 inline fill-neutral-200" height="20" width="20"></svg> Output</span></div></div><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded text" data-clipboard-target="content" data-controller="code"></div></div></div></div></div></div>```text
CONTAINER ID   IMAGE          COMMAND                  CREATED         STATUS                   PORTS     NAMES
62e396145307   nginx:latest   "/docker-entrypoint.…"   7 minutes ago   Up 7 minutes (healthy)   80/tcp    nginx_nginx.2.uk18jo6wwlq6qfrv2lr6zk1xz

```

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-monitor-your-docker-" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded text" data-clipboard-target="content" data-controller="code"></div></div><article class="callout flex py-[13px] pl-4 pr-5 my-8 rounded-lg border text-brand-primary-200 dark:text-brand-primary-100 marker:text-brand-primary-200 border-[#BECCFB]/80 dark:border-brand-primary-100/30 bg-brand-primary-100/10"><div class="shrink-0 not-prose mr-3 -mt-1"><svg class="text-brand-primary-200 dark:text-brand-primary-100 w-4 h-4 inline"></svg></div>### Monitor your Docker Swarm cluster with Better Stack

While Docker Swarm handles container orchestration, [Better Stack](https://betterstack.com/?utm_content=callout&utm_medium=guides&utm_source=community&utm_term=ha-docker-swarm) provides comprehensive monitoring for your distributed services. Track container health, collect logs from all nodes, and get alerted when services fail with infrastructure monitoring that checks your cluster every 30 seconds.

**Predictable pricing and up to 30x cheaper than Datadog.** Start free in minutes.

</article></div></div></div></div><div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk--2" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"></div></div></div></div>## Step 8 — Draining the other manager nodes

As mentioned earlier, manager nodes should ideally be only responsible for management-related tasks. Currently, two of the three manager nodes are running replicas of the NGINX service which could hamper management operations under certain conditions. To prevent such interference, it is best to mark them as unavailable for running tasks by draining them as follows:

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%C2%A0-36" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="px-4 py-[6px] bg-white dark:bg-[#0B0C14] flex items-center rounded-t-md border-b border-neutral-50 dark:border-neutral-800"><div class="text-[15px] font-medium inline align-middle grow"><span class="text-app-small"> </span></div><div class="copy-button hidden sm:flex sm:items-center" data-clipboard-target="confirmation"><button class="text-sm p-1" data-action="click->clipboard#copy"><svg alt="copy code to clipboard" class="m-0 text-neutral-200" height="18" width="18"></svg></button></div></div><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded command" data-clipboard-target="content" data-controller="code"></div></div></div></div></div></div>```command
docker node update --availability drain <manager_node_id>

```

Once you've done so for both the `manager-2` and `manager-3` nodes, you'll observe that their `AVAILABILITY` has been updated to drain:

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%C2%A0-37" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="px-4 py-[6px] bg-white dark:bg-[#0B0C14] flex items-center rounded-t-md border-b border-neutral-50 dark:border-neutral-800"><div class="text-[15px] font-medium inline align-middle grow"><span class="text-app-small"> </span></div><div class="copy-button hidden sm:flex sm:items-center" data-clipboard-target="confirmation"><button class="text-sm p-1" data-action="click->clipboard#copy"><svg alt="copy code to clipboard" class="m-0 text-neutral-200" height="18" width="18"></svg></button></div></div><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded command" data-clipboard-target="content" data-controller="code"></div></div></div></div></div></div>```command
docker node ls

```

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%C2%A0output-23" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded command" data-clipboard-target="content" data-controller="code"></div></div><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="px-4 py-[6px] bg-white dark:bg-[#0B0C14] flex items-center rounded-t-md border-b border-neutral-50 dark:border-neutral-800"><div class="text-[15px] font-medium inline align-middle grow"><span class="text-app-small"><svg alt="" class="m-0 -mt-1 inline fill-neutral-200" height="20" width="20"></svg> Output</span></div></div><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded text" data-clipboard-target="content" data-controller="code"></div></div></div></div></div></div>```text
ID                            HOSTNAME    STATUS    AVAILABILITY   MANAGER STATUS   ENGINE VERSION
9r83zto8qpqiazt6slxfkjypq *   manager-1   Ready     Drain          Leader           20.10.18
uspt9qwqnzqwl78gbxc7omja7     manager-2   Ready     Drain          Reachable        20.10.18
txrdxwuwjpg5jjfer3bcmtc5r     manager-3   Ready     Drain          Reachable        20.10.18
kaq8r9gec4t58yc9oh3dc0r2d     worker-1    Ready     Active                          20.10.18
vk1224zd81xcihgm1iis2703z     worker-2    Ready     Active                          20.10.18

```

The NGINX replicas that were running on both manager nodes are subsequently stopped and reassigned to each worker node. You can confirm that four replicas are still running using the command below:

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%C2%A0-38" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="px-4 py-[6px] bg-white dark:bg-[#0B0C14] flex items-center rounded-t-md border-b border-neutral-50 dark:border-neutral-800"><div class="text-[15px] font-medium inline align-middle grow"><span class="text-app-small"> </span></div><div class="copy-button hidden sm:flex sm:items-center" data-clipboard-target="confirmation"><button class="text-sm p-1" data-action="click->clipboard#copy"><svg alt="copy code to clipboard" class="m-0 text-neutral-200" height="18" width="18"></svg></button></div></div><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded command" data-clipboard-target="content" data-controller="code"></div></div></div></div></div></div>```command
docker service ls

```

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%C2%A0output-24" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded command" data-clipboard-target="content" data-controller="code"></div></div><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="px-4 py-[6px] bg-white dark:bg-[#0B0C14] flex items-center rounded-t-md border-b border-neutral-50 dark:border-neutral-800"><div class="text-[15px] font-medium inline align-middle grow"><span class="text-app-small"><svg alt="" class="m-0 -mt-1 inline fill-neutral-200" height="20" width="20"></svg> Output</span></div></div><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded text" data-clipboard-target="content" data-controller="code"></div></div></div></div></div></div>```text
ID             NAME          MODE         REPLICAS   IMAGE          PORTS
xh24wj31z4ml   nginx_nginx   replicated   4/4        nginx:latest   *:8088->80/tcp

```

Now, confirm which nodes are running each replica through the command below:

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%C2%A0-39" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="px-4 py-[6px] bg-white dark:bg-[#0B0C14] flex items-center rounded-t-md border-b border-neutral-50 dark:border-neutral-800"><div class="text-[15px] font-medium inline align-middle grow"><span class="text-app-small"> </span></div><div class="copy-button hidden sm:flex sm:items-center" data-clipboard-target="confirmation"><button class="text-sm p-1" data-action="click->clipboard#copy"><svg alt="copy code to clipboard" class="m-0 text-neutral-200" height="18" width="18"></svg></button></div></div><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded command" data-clipboard-target="content" data-controller="code"></div></div></div></div></div></div>```command
docker service ps <service_id>

```

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%C2%A0output-25" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded command" data-clipboard-target="content" data-controller="code"></div></div><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="px-4 py-[6px] bg-white dark:bg-[#0B0C14] flex items-center rounded-t-md border-b border-neutral-50 dark:border-neutral-800"><div class="text-[15px] font-medium inline align-middle grow"><span class="text-app-small"><svg alt="" class="m-0 -mt-1 inline fill-neutral-200" height="20" width="20"></svg> Output</span></div></div><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded text" data-clipboard-target="content" data-controller="code"></div></div></div></div></div></div>```text
ID             NAME                IMAGE          NODE        DESIRED STATE   CURRENT STATE               ERROR     PORTS
ikjo7su8ooo6   nginx_nginx.1       nginx:latest   worker-2    Running         Running 19 minutes ago
inel921owq9b    \_ nginx_nginx.1   nginx:latest   manager-2   Shutdown        Shutdown 19 minutes ago
y0y5mvj5n44r   nginx_nginx.2       nginx:latest   worker-1    Running         Running 19 minutes ago
uk18jo6wwlq6    \_ nginx_nginx.2   nginx:latest   manager-3   Shutdown        Shutdown 19 minutes ago
ijbalagf7isy   nginx_nginx.3       nginx:latest   worker-1    Running         Running about an hour ago
drgu007baw8z   nginx_nginx.4       nginx:latest   worker-2    Running         Running about an hour ago

```

As you can see, the `manager-2` and `manager-3` tasks were shut down 19 minutes ago and subsequently reassigned to `worker-2` and `worker-1` respectively. Your manager nodes are now only responsible for cluster management activities and maintaining high availability of the cluster.

## Step 9 — Testing the failover mechanism

Before concluding this tutorial, let's test the availability of our cluster by causing the current leader (`manager-1`) to fail. Once this happens, the other managers should detect the failure and elect a new leader.

You can cause the `manager-1` node to become unavailable by stopping the `docker` service on the server:

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%C2%A0-40" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="px-4 py-[6px] bg-white dark:bg-[#0B0C14] flex items-center rounded-t-md border-b border-neutral-50 dark:border-neutral-800"><div class="text-[15px] font-medium inline align-middle grow"><span class="text-app-small"> </span></div><div class="copy-button hidden sm:flex sm:items-center" data-clipboard-target="confirmation"><button class="text-sm p-1" data-action="click->clipboard#copy"><svg alt="copy code to clipboard" class="m-0 text-neutral-200" height="18" width="18"></svg></button></div></div><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded command" data-clipboard-target="content" data-controller="code"></div></div></div></div></div></div>```command
sudo systemctl stop docker

```

Afterward, run the `docker node ls` command on any of the other manager nodes:

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%C2%A0-41" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="px-4 py-[6px] bg-white dark:bg-[#0B0C14] flex items-center rounded-t-md border-b border-neutral-50 dark:border-neutral-800"><div class="text-[15px] font-medium inline align-middle grow"><span class="text-app-small"> </span></div><div class="copy-button hidden sm:flex sm:items-center" data-clipboard-target="confirmation"><button class="text-sm p-1" data-action="click->clipboard#copy"><svg alt="copy code to clipboard" class="m-0 text-neutral-200" height="18" width="18"></svg></button></div></div><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded command" data-clipboard-target="content" data-controller="code"></div></div></div></div></div></div>```command
docker node ls

```

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%C2%A0output-26" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded command" data-clipboard-target="content" data-controller="code"></div></div><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="px-4 py-[6px] bg-white dark:bg-[#0B0C14] flex items-center rounded-t-md border-b border-neutral-50 dark:border-neutral-800"><div class="text-[15px] font-medium inline align-middle grow"><span class="text-app-small"><svg alt="" class="m-0 -mt-1 inline fill-neutral-200" height="20" width="20"></svg> Output</span></div></div><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded text" data-clipboard-target="content" data-controller="code"></div></div></div></div></div></div>```text
ID                            HOSTNAME    STATUS    AVAILABILITY   MANAGER STATUS   ENGINE VERSION
9r83zto8qpqiazt6slxfkjypq     manager-1   Ready     Drain          Unreachable      20.10.18
uspt9qwqnzqwl78gbxc7omja7     manager-2   Ready     Drain          Leader           20.10.18
txrdxwuwjpg5jjfer3bcmtc5r *   manager-3   Ready     Drain          Reachable        20.10.18
kaq8r9gec4t58yc9oh3dc0r2d     worker-1    Ready     Active                          20.10.18
vk1224zd81xcihgm1iis2703z     worker-2    Ready     Active                          20.10.18

```

Notice that `manager-1` is deemed unreachable and `manager-2` has been elected the new leader. If you check the NGINX service status, you'll observe that the replicas running on the worker nodes were all restarted afterward:

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%C2%A0-42" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="px-4 py-[6px] bg-white dark:bg-[#0B0C14] flex items-center rounded-t-md border-b border-neutral-50 dark:border-neutral-800"><div class="text-[15px] font-medium inline align-middle grow"><span class="text-app-small"> </span></div><div class="copy-button hidden sm:flex sm:items-center" data-clipboard-target="confirmation"><button class="text-sm p-1" data-action="click->clipboard#copy"><svg alt="copy code to clipboard" class="m-0 text-neutral-200" height="18" width="18"></svg></button></div></div><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded command" data-clipboard-target="content" data-controller="code"></div></div></div></div></div></div>```command
docker service ps <service_id>

```

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%C2%A0output-27" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded command" data-clipboard-target="content" data-controller="code"></div></div><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="px-4 py-[6px] bg-white dark:bg-[#0B0C14] flex items-center rounded-t-md border-b border-neutral-50 dark:border-neutral-800"><div class="text-[15px] font-medium inline align-middle grow"><span class="text-app-small"><svg alt="" class="m-0 -mt-1 inline fill-neutral-200" height="20" width="20"></svg> Output</span></div></div><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded text" data-clipboard-target="content" data-controller="code"></div></div></div></div></div></div>```text
ID             NAME                IMAGE          NODE        DESIRED STATE   CURRENT STATE             ERROR     PORTS
ikjo7su8ooo6   nginx_nginx.1       nginx:latest   worker-2    Running         Running 3 minutes ago
inel921owq9b    \_ nginx_nginx.1   nginx:latest   manager-2   Shutdown        Shutdown 34 minutes ago
y0y5mvj5n44r   nginx_nginx.2       nginx:latest   worker-1    Running         Running 3 minutes ago
uk18jo6wwlq6    \_ nginx_nginx.2   nginx:latest   manager-3   Shutdown        Shutdown 34 minutes ago
ijbalagf7isy   nginx_nginx.3       nginx:latest   worker-1    Running         Running 3 minutes ago
drgu007baw8z   nginx_nginx.4       nginx:latest   worker-2    Running         Running 3 minutes ago

```

When you start the `docker` service on `manager-1` once again, it will be marked as `Reachable`, but `manager-2` will remain the `Leader` of the cluster.

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%C2%A0-43" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="px-4 py-[6px] bg-white dark:bg-[#0B0C14] flex items-center rounded-t-md border-b border-neutral-50 dark:border-neutral-800"><div class="text-[15px] font-medium inline align-middle grow"><span class="text-app-small"> </span></div><div class="copy-button hidden sm:flex sm:items-center" data-clipboard-target="confirmation"><button class="text-sm p-1" data-action="click->clipboard#copy"><svg alt="copy code to clipboard" class="m-0 text-neutral-200" height="18" width="18"></svg></button></div></div><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded command" data-clipboard-target="content" data-controller="code"></div></div></div></div></div></div>```command
sudo systemctl start docker

```

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%C2%A0-44" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded command" data-clipboard-target="content" data-controller="code"></div></div><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="px-4 py-[6px] bg-white dark:bg-[#0B0C14] flex items-center rounded-t-md border-b border-neutral-50 dark:border-neutral-800"><div class="text-[15px] font-medium inline align-middle grow"><span class="text-app-small"> </span></div><div class="copy-button hidden sm:flex sm:items-center" data-clipboard-target="confirmation"><button class="text-sm p-1" data-action="click->clipboard#copy"><svg alt="copy code to clipboard" class="m-0 text-neutral-200" height="18" width="18"></svg></button></div></div><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded command" data-clipboard-target="content" data-controller="code"></div></div></div></div></div></div>```command
docker node ls

```

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-%C2%A0output-28" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded command" data-clipboard-target="content" data-controller="code"></div></div><div class="relative mb-5 bg-neutral-30 dark:bg-[#171824] border border-neutral-50 dark:border-neutral-800 rounded-md text-[15px] shadow-2xs" data-controller="clipboard"><div class="px-4 py-[6px] bg-white dark:bg-[#0B0C14] flex items-center rounded-t-md border-b border-neutral-50 dark:border-neutral-800"><div class="text-[15px] font-medium inline align-middle grow"><span class="text-app-small"><svg alt="" class="m-0 -mt-1 inline fill-neutral-200" height="20" width="20"></svg> Output</span></div></div><div class="code-wrapper overflow-x-auto pretty-scrollbars p-2 rounded text" data-clipboard-target="content" data-controller="code"></div></div></div></div></div></div>```text
ID                            HOSTNAME    STATUS    AVAILABILITY   MANAGER STATUS   ENGINE VERSION
9r83zto8qpqiazt6slxfkjypq *   manager-1   Ready     Drain          Reachable        20.10.18
uspt9qwqnzqwl78gbxc7omja7     manager-2   Ready     Drain          Leader           20.10.18
txrdxwuwjpg5jjfer3bcmtc5r     manager-3   Ready     Drain          Reachable        20.10.18
kaq8r9gec4t58yc9oh3dc0r2d     worker-1    Ready     Active                          20.10.18
vk1224zd81xcihgm1iis2703z     worker-2    Ready     Active                          20.10.18

```

## Monitoring your Docker Swarm cluster

You've set up a highly available Docker Swarm cluster that can withstand node failures and automatically redistribute workloads. However, high availability means nothing without proper monitoring to detect issues before they impact your services.

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk--3" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content"></div></div></div></div>[Better Stack](https://betterstack.com/) provides unified monitoring for your entire Swarm cluster:

<div class="container mx-auto py-8 lg:py-16 max-w-[1130px]" id="bkmrk-infrastructure-monit" style="text-align: justify;"><div class="lg:flex" data-controller="toc"><div class="grow xl:flex"><div class="grow shrink-0 prose max-w-[616px]" data-controller="body" data-toc-target="content">- Infrastructure monitoring checks all your nodes every 30 seconds from global locations
- Collect logs from all containers across manager and worker nodes in one place
- Track container health, resource usage, and service availability
- Get instant alerts via email, SMS, or phone when nodes become unreachable
- Monitor NGINX and other services with automatic health checks
- Create status pages to communicate cluster status to users
- Incident management tools coordinate your team during outages

</div></div></div></div>Instead of manually checking `docker service ps` and `docker node ls`, Better Stack gives you real-time visibility into your entire cluster. When a manager node fails like in Step 9, you'll get alerted immediately rather than discovering it later.

The platform combines infrastructure monitoring, log management, and incident response in one place, eliminating the need to piece together multiple monitoring tools for your Swarm cluster.

If you want comprehensive monitoring for your Docker Swarm setup, check out [Better Stack](https://betterstack.com/).

## Final thoughts

A highly available setup is one of the essential requirements for any production system, but building such systems used to be a tedious and complex task. As demonstrated in this tutorial, using Docker and Docker Swarm makes this task much easier and also takes fewer resources when compared to other technologies (such as Kubernetes) used to accomplish the same type of high availability setup.

There's a lot more pertaining to Docker Swarm (security, scaling, secrets management, etc) that cannot be covered in one tutorial, so ensure to check out the [official Swarm guide<span class="whitespace-nowrap"><svg class="relative -top-[1px] ml-1  w-4 h-4 inline"></svg></span>](https://docs.docker.com/engine/swarm/) and the rest of our [scaling docker tutorial series](https://betterstack.com/community/guides/scaling-docker/). If you would like to read more on Docker, feel free to also explore our [Docker logging guide](https://betterstack.com/community/guides/logging/how-to-start-logging-with-docker/).

Thanks for reading!

# Swarmpit Docker

Link: [https://github.com/swarmpit/swarmpit#installation](https://github.com/swarmpit/swarmpit#installation) [https://swarmpit.io/](https://swarmpit.io/)

[![swarmpit](https://raw.githubusercontent.com/swarmpit/swarmpit/master/resources/public/img/logo.svg?sanitize=true)](https://swarmpit.io/)

Lightweight mobile-friendly Docker Swarm management UI

⚠️ **Status:** This UI is in maintenance mode. Click [here](https://github.com/swarmpit/swarmpit/issues/719) for details.

[![version](https://camo.githubusercontent.com/7e5a117d263a9f5db2a63121233c8a0c99026e2cec5925c9d60083844d7b66e3/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f72656c656173652d7072652f737761726d7069742f737761726d7069742e737667)](https://github.com/swarmpit/swarmpit/releases) [![gitter](https://camo.githubusercontent.com/22b3aca7b3e53fd12b311486d8622d4d5f9f274e04ab7200fe90b18648bdf486/68747470733a2f2f6261646765732e6769747465722e696d2f7472657a6f722f636f6d6d756e6974792e737667)](https://gitter.im/swarmpit_io/swarmpit) [![Test, Build & Deploy](https://github.com/swarmpit/swarmpit/actions/workflows/build.yml/badge.svg)](https://github.com/swarmpit/swarmpit/actions/workflows/build.yml) [![PRs Welcome](https://camo.githubusercontent.com/dd0b24c1e6776719edb2c273548a510d6490d8d25269a043dfabbd38419905da/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f5052732d77656c636f6d652d627269676874677265656e2e737667)](https://github.com/swarmpit/swarmpit/pulls) [![Financial Contributors on Open Collective](https://camo.githubusercontent.com/417e04f12e9a5e2605c97e7a07ac3c0ba0c1dfab3ca34f9690b4df2501653a73/68747470733a2f2f6f70656e636f6c6c6563746976652e636f6d2f737761726d7069742f616c6c2f62616467652e7376673f6c6162656c3d66696e616e6369616c2b636f6e7472696275746f7273)](https://opencollective.com/swarmpit)

[![Twitter URL](https://camo.githubusercontent.com/19db955659aa569d718db98d46e9c4dc63e2407574c8cded851a681d1f9272d0/68747470733a2f2f696d672e736869656c64732e696f2f747769747465722f75726c2f68747470732f747769747465722e636f6d2f666f6c645f6c6566742e7376673f7374796c653d736f6369616c266c6162656c3d466f6c6c6f77253230253430737761726d7069745f696f)](https://twitter.com/swarmpit_io)

[![](https://raw.githubusercontent.com/swarmpit/swarmpit/master/resources/public/imac.png)](https://raw.githubusercontent.com/swarmpit/swarmpit/master/resources/public/imac.png)

Swarmpit provides simple and easy to use interface for your Docker Swarm cluster. You can manage your stacks, services, secrets, volumes, networks etc. After linking your Docker Hub account or custom registry, private repositories can be easily deployed on Swarm. Best of all, you can share this management console securely with your whole team.

Swarmpit doesn't compromise your privacy as it is completely self-hosted and will never gather any metrics or other data from you.

More details about future and past releases can be found in [ROADMAP.md](https://github.com/swarmpit/swarmpit/blob/master/ROADMAP.md)

[![opencollective](https://camo.githubusercontent.com/bdd1bd58c61a05f30a5b3216cdfde5d81573104a49ad7c4f9b4b9ce7c2cc07a9/68747470733a2f2f6f70656e636f6c6c6563746976652e636f6d2f737761726d7069742f74696572732f6261636b6572732e7376673f6176617461724865696768743d3530)](https://opencollective.com/swarmpit)

## Installation

<div class="markdown-heading" dir="auto" id="bkmrk--4" style="text-align: justify;">[<svg aria-hidden="true" class="octicon octicon-link" height="16" version="1.1" viewbox="0 0 16 16" width="16"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg>](https://github.com/swarmpit/swarmpit#installation)</div>The only dependency for Swarmpit deployment is Docker with Swarm initialized, we are supporting Docker 1.13 and newer. Linux hosts on x86 and ARM architectures are supported as well.

### Package installer

<div class="markdown-heading" dir="auto" id="bkmrk--6" style="text-align: justify;">[<svg aria-hidden="true" class="octicon octicon-link" height="16" version="1.1" viewbox="0 0 16 16" width="16"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg>](https://github.com/swarmpit/swarmpit#package-installer)</div>Installer is your guide to setup Swarmpit platform. For more details see the [installer](https://github.com/swarmpit/installer)

#### Stable version

<div class="markdown-heading" dir="auto" id="bkmrk--8" style="text-align: justify;">[<svg aria-hidden="true" class="octicon octicon-link" height="16" version="1.1" viewbox="0 0 16 16" width="16"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg>](https://github.com/swarmpit/swarmpit#stable-version)</div>Deploy our current milestone version

```
docker run -it --rm \
  --name swarmpit-installer \
  --volume /var/run/docker.sock:/var/run/docker.sock \
  swarmpit/install:1.9

```

<div class="snippet-clipboard-content notranslate position-relative overflow-auto" id="bkmrk--10" style="text-align: justify;"><div class="zeroclipboard-container"><svg aria-hidden="true" class="octicon octicon-copy js-clipboard-copy-icon" data-view-component="true" height="16" version="1.1" viewbox="0 0 16 16" width="16"></svg></div></div>#### Edge version

<div class="markdown-heading" dir="auto" id="bkmrk--11" style="text-align: justify;">[<svg aria-hidden="true" class="octicon octicon-link" height="16" version="1.1" viewbox="0 0 16 16" width="16"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg>](https://github.com/swarmpit/swarmpit#edge-version)</div>Deploy latest version for the brave and true

```
docker run -it --rm \
  --name swarmpit-installer \
  --volume /var/run/docker.sock:/var/run/docker.sock \
  swarmpit/install:edge

```

<div class="snippet-clipboard-content notranslate position-relative overflow-auto" id="bkmrk--13" style="text-align: justify;"><div class="zeroclipboard-container"><svg aria-hidden="true" class="octicon octicon-copy js-clipboard-copy-icon" data-view-component="true" height="16" version="1.1" viewbox="0 0 16 16" width="16"></svg></div></div>### Manual installation

<div class="markdown-heading" dir="auto" id="bkmrk--14" style="text-align: justify;">[<svg aria-hidden="true" class="octicon octicon-link" height="16" version="1.1" viewbox="0 0 16 16" width="16"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg>](https://github.com/swarmpit/swarmpit#manual-installation)</div>Deploy Swarmpit by using a compose file from our git repo with branch of corresponding version.

```
git clone https://github.com/swarmpit/swarmpit -b master
docker stack deploy -c swarmpit/docker-compose.yml swarmpit

```

<div class="snippet-clipboard-content notranslate position-relative overflow-auto" id="bkmrk--16" style="text-align: justify;"><div class="zeroclipboard-container"><svg aria-hidden="true" class="octicon octicon-copy js-clipboard-copy-icon" data-view-component="true" height="16" version="1.1" viewbox="0 0 16 16" width="16"></svg></div></div>For ARM based cluster use custom compose file.

```
git clone https://github.com/swarmpit/swarmpit -b master
docker stack deploy -c swarmpit/docker-compose.arm.yml swarmpit

```

<div class="snippet-clipboard-content notranslate position-relative overflow-auto" id="bkmrk--17" style="text-align: justify;"><div class="zeroclipboard-container"><svg aria-hidden="true" class="octicon octicon-copy js-clipboard-copy-icon" data-view-component="true" height="16" version="1.1" viewbox="0 0 16 16" width="16"></svg></div></div>[This stack](https://github.com/swarmpit/swarmpit/blob/master/docker-compose.yml) is a composition of 4 services:

- app - Swarmpit
- [agent](https://github.com/swarmpit/agent) - Swarmpit agent
- db - CouchDB (Application data)
- influxdb - InfluxDB (Cluster statistics)

Feel free to edit the stackfile to change an application port and we strongly recommend to specify following volumes:

- db-data
- influxdb-data

to shared-volume driver type of your choice. Alternatively, you can link db service to the specific node by using [constraint](https://docs.docker.com/compose/compose-file/#placement).

Swarmpit is published on port `888` by default.

## Environment Variables

<div class="markdown-heading" dir="auto" id="bkmrk--18" style="text-align: justify;">[<svg aria-hidden="true" class="octicon octicon-link" height="16" version="1.1" viewbox="0 0 16 16" width="16"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg>](https://github.com/swarmpit/swarmpit#environment-variables)</div>Refer to following [document](https://github.com/swarmpit/swarmpit/blob/master/doc/configuration.md)

## User Configuration

<div class="markdown-heading" dir="auto" id="bkmrk--20" style="text-align: justify;">[<svg aria-hidden="true" class="octicon octicon-link" height="16" version="1.1" viewbox="0 0 16 16" width="16"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg>](https://github.com/swarmpit/swarmpit#user-configuration)</div>By default Swarmpit offers you to configure first user using web interface. If you want to automate this process, you can use docker config to provide users.yaml file.

Refer to following [document](https://github.com/swarmpit/swarmpit/blob/master/doc/USER_CONFIG.md) for details.

## User Types

<div class="markdown-heading" dir="auto" id="bkmrk--22" style="text-align: justify;">[<svg aria-hidden="true" class="octicon octicon-link" height="16" version="1.1" viewbox="0 0 16 16" width="16"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg>](https://github.com/swarmpit/swarmpit#user-types)</div>Refer to following [document](https://github.com/swarmpit/swarmpit/blob/master/doc/user_types.md)

## Development

<div class="markdown-heading" dir="auto" id="bkmrk--24" style="text-align: justify;">[<svg aria-hidden="true" class="octicon octicon-link" height="16" version="1.1" viewbox="0 0 16 16" width="16"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg>](https://github.com/swarmpit/swarmpit#development)</div>Swarmpit is written purely in Clojure and utilizes React on front-end. CouchDB is used to persist application data &amp; InfluxDB for cluster statistics.

Everything about building, issue reporting and setting up development environment can be found in [CONTRIBUTING.md](https://github.com/swarmpit/swarmpit/blob/master/CONTRIBUTING.md)

## Demo

<div class="markdown-heading" dir="auto" id="bkmrk--26" style="text-align: justify;">[<svg aria-hidden="true" class="octicon octicon-link" height="16" version="1.1" viewbox="0 0 16 16" width="16"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg>](https://github.com/swarmpit/swarmpit#demo)</div>[![Try in PWD](https://camo.githubusercontent.com/3a70c843ed69647058702b32b5ade194b5b500e6943e4aa33a055bebfe964cfb/68747470733a2f2f63646e2e7261776769742e636f6d2f706c61792d776974682d646f636b65722f737461636b732f63666632323433382f6173736574732f696d616765732f627574746f6e2e706e67)](http://play-with-docker.com/?stack=https://raw.githubusercontent.com/swarmpit/swarmpit/master/docker-compose.yml)

Deploys Swarmpit to play-with-docker sandbox. Please wait few moments till application is up and running before accessing port 888. Initialization might take a few seconds.