Docker + Traefik: A Love Story

The Problem

Docker is an amazing tool on its own, but setting up a reverse proxy with Apache or Nginx to route requests to specific containers is a nightmare. The problem is Docker will not assign the same ip address to a container across restarts.

The Solution

So how can we configure a reverse proxy without static ip addresses? That's where traefik comes in. Traefik is a web server, just like Apache or Nginx, but its bread and butter is its ability to connect to the docker socket to dynamically generate a reverse proxy configuration.

The Setup

You'll need to have Docker and docker-compose installed if you want to follow along. First we need to create an external Docker network which traefik and our exposed applications can talk to each other. Create a network named web with the command docker network create web.

docker-compose.yml

version: '2'

services:
  traefik:
    image: traefik:1.5
    restart: always
    ports:
      - 80:80
      - 443:443
      - 8080:8080
    networks:
      - web
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
      - ./traefik.toml:/traefik.toml
      - ./acme.json:/acme.json
    container_name: traefik

networks:
  web:
    external: true

Here's a breakdown of what the previous docker-compose file does:

  • Create a container which runs Traefik version 1.5
  • Always restart the traefik container if it goes down
  • Map your machine's ports 80, 443, and 8080 to the container
  • Exist inside the web network we created earlier
  • Mount your machine's docker socket into the container to allow dynamic configuration
  • Mount a configuration file to control traefik behaviour
  • Mount a JSON file to store SSL information
  • Name the container traefik

traefik.toml

debug = false
checkNewVersion = true
logLevel = "ERROR"
defaultEntryPoints = ["http", "https"]
[entryPoints]
  [entryPoints.http]
  address = ":80"
    [entryPoints.http.redirect]
  [entryPoints.https]
  address = ":443"
    [entryPoints.https.tls]

[retry]

[docker]
endpoint = "unix:///var/run/docker.sock"
domain = "example.com"
watch = true
exposedbydefault = false

[web]
address = ":8080"

[acme]
email = "email@example.com"
storage = "acme.json"
entryPoint = "https"
OnHostRule = true

[accessLog]

This configuration uses the docker socket to gather information from containers. It creates a web dashboard available at localhost:8080 and automatically generates valid SSL certificates via LetsEncrypt. In this configuration all http requests are redirected to https.

In the same directory create a new file named acme.json with the command touch acme.json.

Configure Application Containers

Traefik uses Docker labels specified on each container to control routes and backends.

This docker-compose file creates a webserver accessible at fileserver.example.com. Container specific configuration labels can be found here.

version: '2'

services:
  fileserver:
    image: nginx
    restart: always
    expose:
      - 80
    labels:
      - "traefik.port=80"
      - "traefik.frontend.rule=Host:fileserver.example.com"
      - "traefik.backend=fileserver"
      - "traefik.docker.network=web"
      - "traefik.enable=true"

networks:
  default:
    external:
      name: web

The Conclusion

Once Traefik is set up, routing to your containerized applications is as simple as adding a few docker container labels and Traefik takes care of the rest.