About Blog Contact
 
 

RSS

Sat, Feb 8, 2020
6 min read

How to use traefik as a reverse proxy in development

This is the fourth part of the series about local development with b5, docker and traefik. If you haven’t read the first three parts, you should do that to get the full context of this article.

How to resolve a custom top level domain to localhost

As a prerequisite, we need to install dnsmasq to resolve a custom tld to localhost. Throughout the whole series, I will expect that you are using a macOS (10.15.3 from the this was written) We use brew to install dnsmasq:

1brew install dnsmasq

Additionally, we have to add a dnsmasq.conf file with one line of configuration:

1echo 'address=/.test/127.0.0.1' > $(brew --prefix)/etc/dnsmasq.conf

This line configures dnsmasq to point all requests to domains ending on .test from 127.0.0.1 .

Add a custom macOS resolver

We also need to add a resolver to macOS:

1sudo mkdir -p /etc/resolver
2sudo bash -c 'echo "nameserver 127.0.0.1" > /etc/resolver/test'

Let dnsmasq automatically start on boot

To add dnsmasq to the auto start we use brew services:

1sudo brew services start dnsmasq

Reboot macOS that the changes take effect.

Test dnsmasq and the resolver

In order to test this part, we can simply ping a random .test domain. It should get an answer from 127.0.0.1.

1ping foobar.test
2PING foobar.test (127.0.0.1): 56 data bytes
364 bytes from 127.0.0.1: icmp_seq=0 ttl=64 time=0.038 ms

Set up the traefik project

In our setup, traefik is a dedicated b5 project that we will put it into a .b5 folder in our home directory. I will not go into details on the project structure because this is explained in detail in (this)[] article.

1mkdir ~/.b5/traefik && cd ~/.b5/traefik
2git init # b5 need a initialised repository in order to work

Project structure:

1- build
2 - config.yml
3 - docker-compose.yml
4 - Taskfile
5 - traefik.toml

config.yml

We use traefik as a project key and enable the docker module of b5.

1project:
2 key: traefik
3modules:
4 docker:

docker-compose.yml

In this tutorial, we will use version 1.7 of traefik. The latest version at the time that this article was written is 2.1. I tried for a few hours to figure out a working configuration for the latest version but it was all in vain. As soon as I have a working configuration, I will update this post.

1version: "3.7"
2 
3services:
4 
5 traefik:
6 image: traefik:1.7
7 restart: always
8 networks:
9 - gateway
10 volumes:
11 - /var/run/docker.sock:/var/run/docker.sock
12 - ./traefik.toml:/traefik.toml
13 ports:
14 - 80:80
15 - 443:443
16 - 8080:8080
17 
18networks:
19 gateway:

We have a docker-compose.yml with a single service named traefik. With the restart: always configuration, it will automatically start when docker starts. The service will be attached to the gateway network, which is defined at the end of the file. Traefik needs the docker socket to mount into the service next to the traefik.toml, which we create in the next step. We map the hosts port 80 and 443 to traefik because it will proxy all requests later. Port 8080 is for the traefik dashboard which gives us information about running services etc..

traefik.toml

1################################################################
2# Global configuration
3################################################################
4 
5# Enable debug mode
6#
7# Optional
8# Default: false
9#
10debug = true
11 
12# Entrypoints to be used by frontends that do not specify any entrypoint.
13# Each frontend can specify its own entrypoints.
14#
15# Optional
16# Default: ["http"]
17#
18#defaultEntryPoints = ["http"]
19defaultEntryPoints = ["http", "https"]
20 
21# Entrypoints definition
22#
23# Optional
24# Default:
25[entryPoints]
26 [entryPoints.http]
27 address = ":80"
28 [entryPoints.https]
29 address = ":443"
30 
31# Traefik logs
32# Enabled by default and log to stdout
33#
34# Optional
35#
36[traefikLog]
37 
38# Enable access logs
39# By default it will write to stdout and produce logs in the textual
40# Common Log Format (CLF), extended with additional fields.
41#
42# Optional
43#
44[accessLog]
45 
46################################################################
47# Web configuration backend
48################################################################
49 
50# Enable web configuration backend
51[web]
52 
53# Web administration port
54#
55# Required
56#
57address = ":8080"
58 
59################################################################
60# Docker configuration backend
61################################################################
62 
63# Enable Docker configuration backend
64[docker]
65 
66# Default domain used.
67# Can be overridden by setting the "traefik.domain" label on a container.
68#
69# Optional
70# Default: ""
71#
72domain = "test"
73 
74# Expose containers by default in traefik
75#
76# Optional
77# Default: true
78#
79exposedbydefault = false
80 
81watch = true

This file contains the complete configuration for traefik to act as a reverse proxy for all our projects in development. The explanations are right in the file.

Taskfile

The Taskfile will only contain three commands which are self explanitory:

1task:run() {
2 docker:docker-compose up "$@"
3}
4 
5task:halt() {
6 docker:docker-compose down "$@"
7}
8 
9task:docker-compose() {
10 docker:docker-compose "$@"
11}

Start traefik

Now we can start the project with b5. We will demonise it with -d :

1b5 run -d

The dashboard should now be accessible on localhost:8080.

Configure our example project to use traefik

In the last article of this series, we built an example project with Laravel, phpMyAdmin and MailHog.

This is the current docker-compose.yml from our example project:

1version: "3.7"
2 
3services:
4 
5# ...
6 
7 web:
8 image: docker.team23.de/docker/apache:2.4-php
9 environment:
10 APACHE_DOCUMENT_ROOT: /app/web/public
11 volumes:
12 - ../:/app
13 ports:
14 - 8000:80
15 
16# ...
17 
18 phpmyadmin:
19 image: phpmyadmin/phpmyadmin:latest
20 environment:
21 PMA_HOST: mysql
22 PMA_USER: root
23 PMA_PASSWORD: secret
24 depends_on:
25 - mysql
26 ports:
27 - 8001:80
28 
29# ...
30 
31 mail:
32 image: mailhog/mailhog
33 ports:
34 - 8025:8025
35 
36# ...

Because we only need to enable traefik for services which need to be accessible from the host system, I have stripped out all services and volumes which are not relevant.

Add traefiks network

Since our traefik does not run inside this project but in its own project with its own namespace, we need to connect these docker networks. This can be achieved by the following configuration at the end of the docker-compose.yml:

1# ...
2 
3networks:
4 default:
5 traefik_gateway:
6 external: true

The default network is as its name says, the network which is created by default in any project. When we add a new network, we also have to list the default network to be created. Additionally, we add the traefik_gateway network which is the network that we defined in our traefik project and mark it as external.

Enable traefik for the web and the phpMyAdmin service

To enable traefik for the web service, we have to attach the traefik_gateway to it and add two labels:

1# ...
2 
3 web:
4 image: docker.team23.de/docker/apache:2.4-php
5 environment:
6 APACHE_DOCUMENT_ROOT: /app/web/public
7 volumes:
8 - ../:/app
9 # ports:
10 # - 8000:80
11 networks:
12 - default
13 - traefik_gateway
14 labels:
15 - traefik.enable=true
16 - traefik.docker.network=traefik_gateway
17 
18# ...
19 
20 phpmyadmin:
21 image: phpmyadmin/phpmyadmin:latest
22 environment:
23 PMA_HOST: mysql
24 PMA_USER: root
25 PMA_PASSWORD: secret
26 depends_on:
27 - mysql
28 # ports:
29 # - 8001:80
30 networks:
31 - default
32 - traefik_gateway
33 labels:
34 - traefik.enable=true
35 - traefik.docker.network=traefik_gateway
36 
37# ...

As you can see, we commented out the port mapping because we don't need this anymore. The configuration for both services is absolutely identical.

Enable traefik for MailHog

MailHog needs an additional configuration because it does not run on port 80 or 443 by default:

1# ...
2 
3 mail:
4 image: mailhog/mailhog
5 # ports:
6 # - 8001:80
7 networks:
8 - default
9 - traefik_gateway
10 labels:
11 - traefik.enable=true
12 - traefik.port=8025 # additional line
13 - traefik.docker.network=traefik_gateway
14 
15# ...

That's all. Now we can test the setup by executing b5 run. The new frontends and backends in traefik should now be visible n the dahboard.

The scheme regarding which url will be resolved is as follows:
{service}.{project_key}.test

This means we can access our three services with the following urls:

Recap

We configured dnsmasq and created an independent traefik service which is able to proxy requests for multiple projects at the same time. Since we do not need the port mappings anymore, we can start multiple projects at the same time without shifting the ports. As last step we configured our example project to use traefik for three different services.

Thanks for reading the article. If you have questions just drop me a line here.

Legal Notice  |  Privacy  |  RSS  |  © 2024 christlieb.eu