Map subdomains to docker containers with Traefik

Roman Coedo
Trabe
Published in
3 min readFeb 24, 2020
Photo by Cris Ovalle

I run a server at home where I host some services for myself. Among others, I run a calibre-web instance, a transmission instance, and a plex server.

I’ve been wanting to share access to these services with my family for some time now, but accessing the services via IP:PORT urls is a bit harsh for non tech users.

We are going to solve that by using a reverse proxy.

Mapping our services using a reverse proxy

A reverse proxy is a piece of software that listens for requests at some port, parses them, and based on the parsed information fetches data from some other servers.

This is easier to understand with an example. Let’s say we have our calibre service running at localhost:9083 and our transmission server at localhost:9091. What we want is to have books.mydomain.com pointing to localhost:9083 and torrents.mydomain.com pointing to localhost:9091. What our reverse proxy has to do in this case is: take the request, and based on the subdomain portion, forward the request to the right service.

Using Traefik as our reverse proxy

Traefik is a reverse proxy with auto discoverability. This means that it can analyse your network to find out which service should handle a request.

Traefik defines some abstractions that are used to configure your network:

  • Providers: Providers are used to discover what services are living in your infrastructure. There are providers for Docker, Kubernetes or file configuration.
  • Entry points: Entry points are the gates to Traefik. you have to define what ports is Traefik going to listening to.
  • Routers: Routers are the ones that take the request from an entry point, and based on a set of rules forward the request to a service.
  • Middlewares: Middleware are chainable components that can be used in routers. They can be used to add headers to the original request, do authentication, etc.
  • Services: These are the definitions of the services that will actually handle the request. In our example these would be our calibre, transmission or plex.

Our example scenario

In our example, the services are running as docker containers:

The running containers in our docker host

We are going to define a docker-compose.yml file for our Traefik service:

version: "3"services:
traefik:
image: traefik:v2.0
container_name: traefik
command:
- "--api.insecure=true"
- "--providers.docker=true"
- "--providers.docker.exposedbydefault=false"
- "--entrypoints.web.address=:80"
restart: unless-stopped
ports:
- "80:80"
- "8080:8080"
volumes:
- /var/run/docker.sock:/var/run/docker.sock

We are defining a traefik container and passing some flags to it. In the flags we define our provider (docker). Using this option Traefik will be watching our docker host to update services when they appear. For this option to work we need to mount the host docker socket.

We are also defining our entry point here. We are listening to incoming http requests on the port 80.

Adding Traefik’s labels to our existing containers

For Traefik to discover our services, all we have to do now is to add labels to them. In their docker-compose.yml definition we add this to their labels:

version: "3"services:
calibre:
image: linuxserver/calibre-web
container_name: calibre
restart: unless-stopped
ports:
- "9083:8083"
labels:
- "traefik.enable=true"
- "traefik.http.routers.cal.rule=Host(`books.mydomain.com`)"
- "traefik.http.routers.cal.entrypoints=web"
- "traefik.http.services.cal.loadbalancer.server.port=9083"

In these labels we added a new router cal connected to the web entry point, and it will use the Host(`books.mydomain.com`) rule. This rule will match that url and map the request to the 9083 port.

We need to add these labels to every docker container that we use and we’re good to go!

Wrapping it up

If you need a reverse proxy, Traefik is a good alternative, easier to configure than other classic tools like pound. Traefik is also able to do load balancing and you can even configure it to generate https certificates automatically using let’s encrypt.

I hope you enjoyed this post and see you in another one ;)

--

--