Traefik - Dev environment on steroids

Webcu • January 8, 2021

traefik devops dev_env

The project you're currently working on is configured with docker-compose. Everything is working perfectly. Then suddenly you need to do an urgent fix in the project you finished six months ago. The old project was perfectly configured with docker-compose as well and was working smoothly, but now isn't. What happened? Well, both projects have services that are using the same ports. That story sounds familiar to you? If you're working on multiple projects is very common. You need to configure services to use different ports if you want to keep all of them running, or if not stop one before start the other. I find that kind of annoying. Searching for a way to solve this issue I found Traefik.

Traefik is modern reverse proxy and load balancer that configures itself automatically and dynamically. It has a lot of nice features like: - Load Balancing - Api Gateway - Certificate management - and more

For the sake of this article we're going to focus in Traefik's capability to uses service discovery to configure itself dynamically from the services themselves. That is the one that allow us to have multiple services running even if they listen in the same port. When configuring the services behind Traefik we don't need to specify in which port they're going to be listening, Traefik will configure them dynamically!

However the images that uses the services need to have exposed the ports, to Traefik be able to effectively communicate with them. Check the Troubleshooting section for more details.

Installation

We can follow the basic example of Traefik with Docker to have it running in our dev env.

Basic Example

version: "3.3"

services:

  traefik:
    image: "traefik"
    container_name: "traefik"
    command:
      - "--api.insecure=true"
      - "--providers.docker=true"
      - "--providers.docker.exposedbydefault=false"
      - "--entrypoints.web.address=:80"
    ports:
      - "80:80"
      - "8080:8080"
    volumes:
      - "/var/run/docker.sock:/var/run/docker.sock:ro"
    networks: 
      - traefik

  whoami:
    image: "containous/whoami"
    container_name: "simple-service"
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.whoami.rule=Host(`whoami.localhost`)"
      - "traefik.http.routers.whoami.entrypoints=web"
      - "traefik.docker.network=traefik"
    networks: 
      - traefik

networks: 
  traefik:
    external: true

Service discovery in action

In the basic example we can observe that the service whoami uses the labels to configure how it'll communicate with Traefik:

whoami:
        ...
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.whoami.rule=Host(`whoami.localhost`)"
      - "traefik.http.routers.whoami.entrypoints=web"
      - "traefik.docker.network=traefik"
        ...

After executing docker-compose up -d you will be able to access whoami.localhost in your browser.

In the custom basic example I created, I added the external network traefik, to allow services defined in other docker-compose files to communicate effectively with Traefik. It's possible define all the services that we use in a single docker-compose file, but I personally prefer to define the services needed for each of my projects in a dedicated docker-compose file.

I used traefik as the network's name, but it can have any name.

This is an example of a docker-compose file I'm using in my project Habits-Inventivery

version: "3.8"

services:
  php:
    image: webcu/laravel-installer
    restart: always
    working_dir: /laravel
    volumes:
        - .:/laravel
        - ./docker/xdebug.ini:/usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.habits.rule=Host(`habits.localhost`)"
      - "traefik.http.routers.habits.entrypoints=web"
      - "traefik.docker.network=traefik"
    networks:
      - traefik
      - mysql
    entrypoint: ["php", "-S", "0.0.0.0:80", "-t", "public", "server.php"]

networks:
  traefik:
    external: true
  mysql:
    external: true

After having Traefik up and running start a new project from the point of view of dev env is really quick. We create a docker-compose file inside of the project, define the services we need, linked the ones that need to be linked to Traefik using the external network, and we can start to focus in delivering the product.

Troubleshooting

Conclusions

Traefik allows us to create dynamic dev environments, thanks to its ability to configure itself automatically and dynamically. It is a really powerful tool, with an incredible set of features that expand much more than our local dev env.

References