Using Traefik to develop locally with Docker (Part 1/x)
This is the first technical post on the blog, I’ve been meaning to write about this for some time. At first I wanted to explain everything on one post but I think is going to work better if we split it into smaller parts so here goes part 1 out of X.
Traefik#
First, what is Traefik Proxy? Traefik Proxy is an open source Edge Router that is cloud native. It’s (sidenote: It's many more things, specially since they added the plugin support, but almost none needed for our usecase. ) but the most interesting thing about it for this article is its configuration discovery. What this means is that Traefik is able to discover the configuration of your services and automatically route requests to them without having to change anything on Traefik itself. In practice, you could say that it inverts the responsability of the configuration from what we’re used to.
If you come from something like Apache or Nginx, in order to add a new site you need to edit one of their config files,
(sidenote:
Unless you use .htaccess
, which is not always an option or event recommendable. It's only for Apache and can have a performance penalty, but it may also be forbidden due to security policies on your servers.
)
.
By using Traefik, the configuration is part of the service itself, that means it can be added to your repo and it’ll be available when new users start using the project. There is support for a bunch of providers but for this post we’ll be using only Docker
. Depending on the provider used, the configuration comes on different forms, in the case of Docker, it comes in the form of labels, but we’ll look into them later, let’s begin by starting up Traefik.
Set up#
First, let’s create a folder on a location of your choice.
mkdir traefik
cd traefik
I’m going to assume Docker and Docker Compose are already installed on your machine and you are somehow familiar with how they work. I’ll try to add all needed commands here but will save some explainations for brevity’s sake.
First of all, because of the way networking works when using Docker Compose, the first thing we are going to do is create a network so all our projects can use it.
docker network create --driver=bridge --attachable --internal=false gateway
The command above creates a network called gateway
which is attachable, external and uses the bridge driver.
Once that’s done, let’s create a basic docker-compose.yml
file and start defining our service:
services:
traefik:
# The official docker image for Traefik, 2.9 is the latest at the time of writing
image: traefik:v2.9
# Tell traefik we want to use Docker as a provider
command: --providers.docker
ports:
# Bind port 80 so it's accesible from outside the container
- "80:80"
volumes:
# Mount the docker socket so traefik can see changes in docker
- /var/run/docker.sock:/var/run/docker.sock:ro
# Make the network we created previously ("gateway") available as "default" network
networks:
default:
external: true
name: gateway
I’ve tried to comment the file as much as possible but in short, we’re creating a container out of the Traefik image, telling it to use the network that was previously created (the one we called gateway
),
(sidenote:
Networking in Docker is its own big topic and not within the scope of this post, but the thing to remember here is that port 80 needs to be free on your machine, so if you're already running a webserver this won't work and you need to stop it before starting the container.
)
, and mounting the Docker socket in the container so it can be read by Traefik in order to look for changes.
Now you can run docker-compose up -d
and traefik should be up and running. You can run docker-compose logs -f
to make sure there are no typos on the config and that Traefik is not complaining about anything.
Test the set up#
(sidenote:
You can of course use any other image that contains a webserver to test this, this is just a neat one to test with.
)
, we’re going to use Traefik’s own whoami. This is an image that contains a tiny webserver which, for every request, outputs information of the HTTP request itself and the OS.
Create another folder (outside of the traefik one) with another docker-compose.yml
:
services:
traefik:
image: traefik/whoami
labels:
# Enable traefik
- "traefik.enable=true"
# Tell traefik to route here all request which host is whoami.docker.localhost
- "traefik.http.routers.whoami.rule=Host(`whoami.docker.localhost`)"
networks:
default:
external: true
name: gateway
If we start the image (docker-compose up -d
) and try it out with curl (curl http://whoami.docker.localhost
) or your browser of choice (just visit http://whoami.docker.localhost). The response should look something like this:
Hostname: b7949f4a618b
IP: 127.0.0.1
IP: 172.31.0.2
RemoteAddr: 172.31.0.3:50568
GET / HTTP/1.1
Host: whoami.docker.localhost
User-Agent: curl/7.86.0
Accept: */*
Accept-Encoding: gzip
X-Forwarded-For: 172.31.0.1
X-Forwarded-Host: whoami.docker.localhost
X-Forwarded-Port: 80
X-Forwarded-Proto: http
X-Forwarded-Server: 5ba8a3b9813d
X-Real-Ip: 172.31.0.1
That’s it, from now on, if you have a project running in docker that needs to be accessed through HTTP, you can add the labels
to your docker-compose.yml
, that way you can have as many projects running at the same time as your machine can handle and don’t need to worry about what ports each one is using, because the only container with port 80 bound to your local 80, will be Traefik. The only thing you need to worry about is to have a different hostname/domain on each project and
(sidenote:
In most modern systems, any domain ending in .localhost
will point to 127.0.0.1
, so you can use any domain that makes sense for your project, just like we did with the whoami one. If you already own a domain, you can add an A entry with a subdomain pointing to 127.0.0.1
.
)
.
What’s next?#
For the following parts I’ll try to explain how to add an SSL cert to Traefik so we can use true HTTPS with our personal projects, how to make our own ngrok-like service so we can connect to our local services from outside (like a phone) or how to make two local projects talk to themselves.