January 3, 2018

Traefik reverse proxy & Docker

Route all your applications in an easy and flexible manner

Traefik reverse proxy & Docker

Route all your applications in an easy and flexible manner.

When building applications you might quickly run into issues like multiple co-dependent apps on the same environment/server/host.

A simple example is a website with an api. You might have a very cool Symfony application and you want to build a separate api.
You'll end up with your application on
and your application api on

These two apps can become two independent containers. But unfortunately port 80 (http) and 443 (https) can only be used once per host.

When you create a webserver container using docker you can use

docker run -d -p 80:80 nginx

This will start an nginx container on port 80. Imagine this being your application running on port 80. Nginx will be now visible on http://localhost

Now you have your second application. Also running a webserver on port 80. Mapping port 80 again won't work because it's already being used. Now you could map port 81 or 82 etc.. But let's be honest, that's just plain ugly (or so i think). And not usable in the long run, for development it can be ok. But in production you do not want to use url's with port suffixes.

This is where Traefik comes in the picture.
Traefik serves as reverse proxy. You'll use Traefik to catch all the requests and use rules to decide which request using what url will go to which application/Docker container.

In the following example we'll use Traefik to route the url http://apache.localhost to an Apache2 container and http://nginx.localhost tot a Nginx container.

Stop the running nginx container.

docker stop nginx

First we will create a virtual Docker network to work in.

docker network create traefik

This command does nothing more then create an empty network.

Then we will setup the different parts in the application.
My Docker compose file:

version: '3.4'

    image: traefik:1.4-alpine
    command: --web --docker --docker.domain=docker.localhost
      - traefik
      - 80:80
      - 8080:8080
      - /var/run/docker.sock:/var/run/docker.sock
    image: httpd:alpine
      - "traefik.frontend.rule=Host:apache.localhost"
      - traefik
    image: nginx:alpine
      - "traefik.frontend.rule=Host:nginx.localhost"
      - traefik

    external: true

Lets break this down a bit. At the bottom you see the definition of the external Traefik network. That's the one you've just created.

We have 3 services here.

  • proxy
  • apache
  • nginx


image: traefik:1.4
Definition of the image used.

command: --web --docker --docker.domain=docker.localhost
The command executed.

--web enables the web interface for Traefik on port 8080.
--docker tells Traefik you're using Docker configuration.
--docker.domain=docker.localhost sets all the default url's for containers on *.docker.localhost.

This container maps the ports.
80 for the all default http requests
8080 the port Traefik uses for it's web interface.


  • /var/run/docker.sock:/var/run/docker.sock

This gives the Traefik container access to the host Docker socket. Which it uses to route the right container.

- traefik
This one probably speaks for it self but is very important, this adds this container to the network we created. If Traefik wants to route something to a container, that container has to be in the same network. Otherwise it will fail.


The apache webserver container.

image: httpd:alpine
Apache2 image with alpine tag. Images based on Linux alpine are a lot smaller and for most usages a good way to go to keep the disk space usage low.


  • "traefik.frontend.rule=Host:apache.localhost"

This is were the Traefik magic comes in. Traefik uses this label to as a frontend rule. When the host catches a request with the uri apache.localhost, Traefik now knows that the request has to go to that container. Is it really that easy? Yes.

- traefik
Same story here. If this container is not in the same network Traefik cannot see it.


The nginx webserver container.

This is exactly the same with one difference. The traefik label is different. For this container we're telling Traefik to send it here when the uri is nginx.localhost using the label.

  • "traefik.frontend.rule=Host:nginx.localhost"


To use the url's locally make sure apache.localhost and nginx.localhost are directed to
Add these to your hosts file.

The only thing left is to head over to your terminal, navigate to the directory containing the docker-compose.yml file and run:

docker-compose up -d

That's it. The three containers will be started, and you can now go to

If everything works out you'll see the nginx start page and the apache start page on their respective url's.

The last one is the Traefik web interface which shows the containers traefik sees and which frontend rules maps to which backend container.

Just the start

There are a lot more configuration options with Traefik and a lot more possibilities. You can fully customize the usage of Traefik, enable automatic usage of Let's Encrypt for ssl certificates and more. But this is a good place to start.


  1. Traefik documentation
  2. Example compose Gist
  3. Docker compose documentation