Zero-Downtime Deployments with Docker Swarm and Portainer - Part 1/2
Nico Saia 5 Minuten Lesezeit

Zero-Downtime Deployments with Docker Swarm and Portainer - Part 1/2

It doesn’t always have to be Kubernetes: highly available apps with Docker Swarm and Portainer.
docker-swarm apps

What are Zero-downtime deployments?

Before we dive into the details, let’s clarify what Zero-downtime deployments are. Zero-downtime deployments are deployments that have no downtime. This means that the application being deployed is not offline during the deployment. This is especially important for applications that need to run 24/7. The high availability of applications is becoming increasingly important. Let’s be honest, who wants to wait when Netflix and others update their applications?

Rolling Updates vs Zero-downtime deployments

Both approaches have the same goal, but there are significant differences. Therefore, let’s take a look at both approaches using a table.

Rolling Updates

Operation New versions are gradually introduced into production by updating individual instances step by step.
Time Intervals The update requires some time as it is performed step by step on individual instances.
Downtime Short downtimes are possible as each step involves stopping an instance and replacing it with the new version.
Versioning During the update, different versions of the application may run in parallel for a short time.

Zero-downtime deployments

Operation Zero Downtime Deployments allow a new version of the application to be introduced into production without any downtime for users.
Time Intervals Zero Downtime Deployments aim for a seamless update without time delays or operational interruptions.
Downtime The main difference from Rolling Updates is that Zero Downtime Deployments have no downtime. The application remains continuously available even during the update.
Versioning In Zero Downtime Deployments, new versions of the application are gradually brought into production, and only when the new version is deemed fully functional and stable is the old version shut down.

How does a Zero-downtime deployment work with Docker Swarm and Portainer?

Enough theory. How do I now implement a Zero-downtime deployment with Docker Swarm and Portainer?

The following prerequisites are required:

  • Docker Swarm is set up
  • a repository with the stack file (docker-stack.yaml)
  • Portainer is set up

Since I have already shown in the article Why Portainer how to deploy a basic YAML file via Portainer, I will not go into further detail here.

The focus is much more on the commands that Docker offers me to achieve a Zero-downtime deployment. In Part 2, the focus will be more on the connection between Portainer and the repository.

Let’s start with the YAML file. It looks like this:

version: '3.8'
services:
  db:
    image: mariadb:10.6.4-focal
    command: '--default-authentication-plugin=mysql_native_password'
    volumes:
      - db_data:/var/lib/mysql
    restart: always
    environment:
      - MYSQL_ROOT_PASSWORD=somewordpress
      - MYSQL_DATABASE=wordpress
      - MYSQL_USER=wordpress
      - MYSQL_PASSWORD=wordpress
    expose:
      - 3306
      - 33060
  wordpress:
    image: wordpress:latest
    volumes:
      - wp_data:/var/www/html
    ports:
      - 7002:80
    restart: always
    environment:
      - WORDPRESS_DB_HOST=db
      - WORDPRESS_DB_USER=wordpress
      - WORDPRESS_DB_PASSWORD=wordpress
      - WORDPRESS_DB_NAME=wordpress
volumes:
  db_data:
  wp_data:

So far, nothing special. We have a WordPress instance with a database. If a new version of WordPress is released, the application must go offline to roll out the new version. This is, of course, not optimal.

Healthcheck

The next step is therefore to integrate a Docker Healthcheck that checks whether an application is running correctly. It would theoretically also work without a Healthcheck, but there are containers that are still displayed as running even when they are no longer running internally.

healthcheck:
  test: ["CMD", "curl", "-f", "http://localhost"] # Simply tests if the application is accessible via port 80
  interval: 30s
  timeout: 10s
  retries: 5

After this, we can check in Portainer whether our application is healthy.

That already looks very good.

I will not go into further detail about the Healthcheck here. If you want to know more, feel free to read the Docker Manuals.

Zero-downtime deployment

Now that we have the Healthcheck, we can turn to the actual Zero-downtime deployment. For this, we need to extend our YAML file by a few lines.

deploy:
  replicas: 2 # Number of instances that should run simultaneously
  update_config: # The configuration for the update
    order: start-first  # The order in which the instances should be updated    
    failure_action: rollback # What should happen if an update fails

  rollback_config: # The configuration for the rollback
    parallelism: 1 # How many instances should be rolled back simultaneously
    order: start-first # The order in which the instances should be rolled back

  restart_policy: # The configuration for the restart
    condition: on-failure # Under what conditions a restart should be performed

Now we have everything we need to perform a Zero-downtime deployment. You can find the complete stack here

Why do we run two instances simultaneously?

Simply put, if we only run one instance and that instance fails, we no longer have an instance providing the application. That’s why we run two instances simultaneously. If one instance fails, we still have a second instance providing the application. In a Swarm cluster, Docker can also distribute the Container across multiple nodes.

This way, we can achieve high availability of the application.

If we now want to update our WordPress instance, we can easily do so via Portainer. However, I will show you this in Part 2 of this post, as it would exceed the scope here.

Sources:

Ähnliche Artikel