I have been using Traefik with Docker for a while to host some personal projects, and to experiment with devops.

One thing I have always wanted to accomplish is full Continuous Deployment, with zero downtime, using Blue-Green Deployments, but I didn’t want all the extra overhead of setting up Swarm or Kubernetes.

Here’s how I recently accomplished this goal.

First, create a traefik.yml file for static configuration:

entryPoints:
  http:
    address: ":80"
  https:
    address: ":443"

providers:
  file:
    directory: /etc/traefik/dynamic
    watch: true

api:
  dashboard: true
  insecure: true

Then create a directory, dynamic for the dynamic configurations. There is nothing in it yet.

Next create a docker-compose.yml file to spin up Traefik and hook up some volumes:

services:
  traefik:
    image: traefik:v2.4
    ports:
      - 80:80
      - 443:443
      - 8080:8080
    volumes:
      - ./traefik.yml:/etc/traefik/traefik.yml
      - ./dynamic:/etc/traefik/dynamic:ro

Start it up, docker-compose up -d, and vist http://localhost:8080. If everything worked, you should see the Traefik dashboard!

Now we need our blue and green services. Create two simple html files, blue.html

<h2>Blue<h2>

and green.html.

<h2>Green<h2>

Then, create two simple Dockerfiles, Dockerfile.blue

FROM nginx
COPY blue.html /usr/share/nginx/html/index.html

and Dockerfile.green.

FROM nginx
COPY green.html /usr/share/nginx/html/index.html

Build and label the images:

docker build -t blue -f Dockerfile.blue .
docker build -t green -f Dockerfile.green .

Let’s test them out:

docker run -p 8081:80 --rm blue
docker run -p 8082:80 --rm green

Then, vist http://localhost:8081 and http://localhost:8082. Nice! Ok, lets shut down those containers, and update our docker-compose.yml file. Add the following:

blue:
  image: blue

green:
  image: green

Then start them, docker-compose up -d. If you run docker ps or docker-compose ps you should now see 3 containers running.

We need to tell Traefik about these services, so in the dynamic directory, we are going to add 4 files, http.services.blue.yml:

http:
  services:
    blue:
      loadBalancer:
        servers:
          - url: 'http://blue/'

http.services.green.yml:

http:
  services:
    green:
      loadBalancer:
        servers:
          - url: 'http://green/'

http.routers.blue-docker-localhost.yml:

http:
  routers:
    blue-docker-localhost:
      rule: Host(`blue.docker.localhost`)
      service: blue@file

http.routers.green-docker-localhost.yml:

http:
  routers:
    green-docker-localhost:
      rule: Host(`green.docker.localhost`)
      service: blue@file

Load the Traefik Dashboard, and you should see the routes and services defined. Visit blue.docker-localhost and green.docker.localhost.

Almost there! Just one final step. Add the following file http.routers.docker-localhost.yml:

http:
  routers:
    docker-localhost:
      rule: Host(`docker.localhost`)
      service: blue@file

See that last line? That’s where you decide which service, blue or green, maps to http://docker.localhost. When you want to change it, just change this one value. Traefik watches for changes in this directory, and updates almost immediately.

In a follow-up post, I will build a simple app that shows you which service is selected, and lets you change it.