BoxBoat Blog

Service updates, customer stories, and tips and tricks for effective DevOps

Deploy your Stateful Web Applications in Docker Swarm using Traefik Sticky Sessions

by David Widen | Thursday, Aug 3, 2017 | Docker

Deploy your Stateful Web Applications in Docker Swarm using Traefik Sticky Sessions

The shift away from monolithic legacy applications to microservices has been long coming. The benefits of deploying your application as a microservice far outweigh any additional complexity or costs. High availability, redundancy, robustness, cost, and ease of development are only a few of the advantages.

Docker has significantly sped up this process. With Docker, you can package your applications in lightweight containers and run them on any system with a Docker Engine. When Docker Swarm was released, they brought native orchestration to our production clusters. Stateless applications fit perfectly into this deployment model; however, what about stateful services?

Configuring your stateful application to work with load balancers in high availability mode used to require a significant amount of effort. You needed to point your load balancers at a set of reverse proxies. These proxies needed to cache cookies or other metadata to determine how to route traffic from the web connections to containers providing your services. All of this was fairly complicated and costly, until Traefik and Docker Swarm came along.

Traefik is a modern reverse proxy / load balancer that is designed for use with microservices. It supports a large number of technologies. In this post, we’ll go over how to use Traefik with Docker Swarm to serve a WordPress blog in high availability mode with sticky sessions. Sticky sessions basically means the reverse proxy will remember which connections are associated with each server / container, and continue to route those HTTP messages.This is extremely useful for applications that require you to sign in.

WordPress is one of the most popular content management systems in use today. By default, it contains stateful components such as session management. Let’s explore how to setup WordPress in High Availability mode on Docker Swarm using sticky session in Traefik so that these stateful components work out of the box.

Deploying WordPress with Docker Swarm

The first thing we’ll do is deploy WordPress using Docker Swarm in high availability mode. To start, go to play-with-docker. This is a fantastic website to play around with Docker. After you verify that you’re a human, you will have access to a server instance with Docker installed. Once the GUI loads, click the wrench icon to the right of “Instances” on the left side of the screen.

boxboat play with docker

Then click 3 Managers and 2 Workers.

boxboat play with docker

Play-with-docker is provisioning a Docker Swarm with 5 machines. 3 of the machines are managers, and 2 are workers. We will deploy WordPress using this Docker Swarm.

Go to one of your managers (blue person icon)

boxboat play with docker

Now, execute the following: docker network create -d overlay net. Next, using your text editor of choice, create a file called wordpress.yml and paste in the following content. Remember, if you are using vim, execute :set paste and then make sure to enter interactive mode, otherwise “versi” will be cut off in the pasted file.

version: '3'

services:
  db:
    image: mysql:5.7
    deploy:
      replicas: 1
      restart_policy:
        condition: on-failure
        max_attempts: 3
    volumes:
      - db_data:/var/lib/mysql
    networks:
      - net
    environment:
      MYSQL_ROOT_PASSWORD: wordpress
      MYSQL_DATABASE: wordpress
      MYSQL_USER: wordpress
      MYSQL_PASSWORD: wordpress
  wordpress:
    depends_on:
      - db
    image: wordpress:latest
    deploy:
      replicas: 3
      restart_policy:
        condition: on-failure
        max_attempts: 3
    volumes:
      - wordpress_data:/var/www/html
    networks:
      - net
    ports:
      - "8001:80"
    environment:
      WORDPRESS_DB_HOST: db:3306
      WORDPRESS_DB_PASSWORD: wordpress

volumes:
 db_data:
 wordpress_data:

networks:
  net:
    external: true

What you just pasted is a Docker Compose file. This file specifies the configuration for a set of containers that you will deploy as a microservice. The main thing to look at is the “replicas” section under “wordpress.” In this configuration file, we define that the WordPress frontend will have a total of 3 replicas — that is 3 different containers will serve the PHP code that powers WordPress.

Next, execute docker stack deploy --compose-file=wordpress.yml wordpress. This is how we deploy our application to the Docker Swarm we just created.

After a minute or so, you will see port 8001 appear at the top of the page. Click on port 8001, and go through the WordPress installation steps (pick a language, blog title, login, etc). When you start clicking around the interface, you will have to keep logging in. This is because your browser is not logged in to the container servicing your request.

boxboat play with docker

Specifically, Docker Swarm is using round robin routing every time you access the blog. Because of this, your browser uses a different container for every request. After you login to the first container, your traffic is routed to the second — which you aren’t logged in to. And then the third, which you aren’t logged in to. After you’ve logged into all 3 of them, then everything works fine. Extremely useful for applications where you don’t login, but really annoying if you need to.

Next, execute docker stack rm wordpress. This will bring down WordPress. We’ll now deploy WordPress but use Traefik to serve as a reverse proxy, and configure sticky sessions. Create a file called traefik.yml and paste in the following content:

version: '3.0'

services:
  loadbalancer:
    image: traefik
    command: --docker \
      --docker.swarmmode \
      --docker.watch \
      --web \
      --loglevel=DEBUG
    ports:
      - 80:80
      - 9090:8080
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
    deploy:
      restart_policy:
        condition: any
      mode: replicated
      replicas: 1
      update_config:
        delay: 2s
      placement:
         constraints: [node.role == manager]
    networks:
      - net

networks:
    net:
      external: true

Now, execute docker stack deploy --compose-file=traefik.yml traefik. After 2 or 3 minutes, the Traefik reverse proxy will be running. Click on port 9090 to see the current status.

Now that we’ve deployed Traefik, we will deploy WordPress with a slightly modified configuration. Create another file, wordpress-sticky.yml and paste in the following contents:

version: "3.1"

services:
  db:
    image: mysql:5.7
    deploy:
      replicas: 1
      restart_policy:
        condition: on-failure
        max_attempts: 3
    volumes:
      - db_data:/var/lib/mysql
    networks:
      - net
    environment:
      MYSQL_ROOT_PASSWORD: wordpress
      MYSQL_DATABASE: wordpress
      MYSQL_USER: wordpress
      MYSQL_PASSWORD: wordpress
  wordpress:
    depends_on:
      - db
    image: wordpress:latest
    deploy:
      mode: replicated
      replicas: 3
      restart_policy:
        condition: on-failure
        max_attempts: 3
      placement:
        constraints: [node.role == worker]
      update_config:
        delay: 2s
      labels:
        - "traefik.docker.network=net"
        - "traefik.port=80"
        - "traefik.frontend.rule=PathPrefix:/"
        - "traefik.backend.loadbalancer.sticky=true"
    volumes:
      - wordpress_data:/var/www/html
    networks:
      - net
    ports:
      - "80"
    environment:
      WORDPRESS_DB_HOST: db:3306
      WORDPRESS_DB_PASSWORD: wordpress

networks:
  net:
    external: true

volumes:
  db_data:
  wordpress_data:

There are a few key differences between this version of the WordPress Docker Compose file, and the previous ones. The main differences are that this one defines labels in the deploy step, and forces the WordPress containers to run on worker nodes.

Now, execute docker stack deploy --compose-file=wordpress-sticky.yml wordpress-sticky. After a minute or so, click on port 80.

Now you can login and use WordPress as normal. At this point, we have deployed WordPress in high availability mode with sticky sessions enabled. This allows you to deliver a stateful web application to your users, using a high availability microservice setup. This enables you to deploy your applications that require logins as Docker containers in a high availability setup using Docker Swarm.

BoxBoat Accelerator

Learn how to best introduce Docker into your organization. Leave your name and email, and we'll get right back to you.

Thank you! Your submission has been received!
Oops! Something went wrong while submitting the form.