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 mycoolapp.com
and your application api on api.mycoolapp.com
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'
services:
proxy:
image: traefik:1.4-alpine
command: --web --docker --docker.domain=docker.localhost
networks:
- traefik
ports:
- 80:80
- 8080:8080
volumes:
- /var/run/docker.sock:/var/run/docker.sock
apache:
image: httpd:alpine
labels:
- "traefik.frontend.rule=Host:apache.localhost"
networks:
- traefik
nginx:
image: nginx:alpine
labels:
- "traefik.frontend.rule=Host:nginx.localhost"
networks:
- traefik
networks:
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.
Image image: traefik:1.4
Definition of the image used.
Command 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.
Ports This container maps the ports. 80
for the all default http requests 8080
the port Traefik uses for it's web interface.
Volumes - /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.
Network - 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 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.
Labels - "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.
Networks - 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.
To use the url's locally make sure apache.localhost and nginx.localhost are directed to 127.0.0.1. 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.
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.
Resources: 1. Traefik documentation 2. Example compose Gist 3. Docker compose documentation