Skip to content

Instantly share code, notes, and snippets.

@Mau5Machine
Last active December 12, 2023 06:55
Show Gist options
  • Save Mau5Machine/00401feb19433cf0387cc66c8e90c26c to your computer and use it in GitHub Desktop.
Save Mau5Machine/00401feb19433cf0387cc66c8e90c26c to your computer and use it in GitHub Desktop.
Traefik Configuration and Setup
version: "3.3"
services:
################################################
#### Traefik Proxy Setup #####
###############################################
traefik:
image: traefik:v2.0
restart: always
container_name: traefik
ports:
- "80:80" # <== http
- "8080:8080" # <== :8080 is where the dashboard runs on
- "443:443" # <== https
command:
#### These are the CLI commands that will configure Traefik and tell it how to work! ####
## API Settings - https://docs.traefik.io/operations/api/, endpoints - https://docs.traefik.io/operations/api/#endpoints ##
- --api.insecure=true # <== Enabling insecure api, NOT RECOMMENDED FOR PRODUCTION
- --api.dashboard=true # <== Enabling the dashboard to view services, middlewares, routers, etc...
- --api.debug=true # <== Enabling additional endpoints for debugging and profiling
## Log Settings (options: ERROR, DEBUG, PANIC, FATAL, WARN, INFO) - https://docs.traefik.io/observability/logs/ ##
- --log.level=DEBUG # <== Setting the level of the logs from traefik
## Provider Settings - https://docs.traefik.io/providers/docker/#provider-configuration ##
- --providers.docker=true # <== Enabling docker as the provider for traefik
- --providers.docker.exposedbydefault=false # <== Don't expose every container to traefik, only expose enabled ones
- --providers.file.filename=/dynamic.yaml # <== Referring to a dynamic configuration file
- --providers.docker.network=web # <== Operate on the docker network named web
## Entrypoints Settings - https://docs.traefik.io/routing/entrypoints/#configuration ##
- --entrypoints.web.address=:80 # <== Defining an entrypoint for port :80 named web
- --entrypoints.web-secured.address=:443 # <== Defining an entrypoint for https on port :443 named web-secured
## Certificate Settings (Let's Encrypt) - https://docs.traefik.io/https/acme/#configuration-examples ##
- --certificatesresolvers.mytlschallenge.acme.tlschallenge=true # <== Enable TLS-ALPN-01 to generate and renew ACME certs
- --certificatesresolvers.mytlschallenge.acme.email=theafkdeveloper@gmail.com # <== Setting email for certs
- --certificatesresolvers.mytlschallenge.acme.storage=/letsencrypt/acme.json # <== Defining acme file to store cert information
volumes:
- ./letsencrypt:/letsencrypt # <== Volume for certs (TLS)
- /var/run/docker.sock:/var/run/docker.sock # <== Volume for docker admin
- ./dynamic.yaml:/dynamic.yaml # <== Volume for dynamic conf file, **ref: line 27
networks:
- web # <== Placing traefik on the network named web, to access containers on this network
labels:
#### Labels define the behavior and rules of the traefik proxy for this container ####
- "traefik.enable=true" # <== Enable traefik on itself to view dashboard and assign subdomain to view it
- "traefik.http.routers.api.rule=Host(`monitor.example.com`)" # <== Setting the domain for the dashboard
- "traefik.http.routers.api.service=api@internal" # <== Enabling the api to be a service to access
################################################
#### Site Setup Container #####
##############################################
wordpress: # <== we aren't going to open :80 here because traefik is going to serve this on entrypoint 'web'
## :80 is already exposed from within the container ##
image: wordpress
restart: always
container_name: wp
environment:
WORDPRESS_DB_HOST: db
WORDPRESS_DB_USER: exampleuser
WORDPRESS_DB_PASSWORD: examplepass
WORDPRESS_DB_NAME: exampledb
volumes:
- wordpress:/var/www/html
networks:
- web
- backend
labels:
#### Labels define the behavior and rules of the traefik proxy for this container ####
- "traefik.enable=true" # <== Enable traefik to proxy this container
- "traefik.http.routers.nginx-web.rule=Host(`example.com`)" # <== Your Domain Name goes here for the http rule
- "traefik.http.routers.nginx-web.entrypoints=web" # <== Defining the entrypoint for http, **ref: line 30
- "traefik.http.routers.nginx-web.middlewares=redirect@file" # <== This is a middleware to redirect to https
- "traefik.http.routers.nginx-secured.rule=Host(`example.com`)" # <== Your Domain Name for the https rule
- "traefik.http.routers.nginx-secured.entrypoints=web-secured" # <== Defining entrypoint for https, **ref: line 31
- "traefik.http.routers.nginx-secured.tls.certresolver=mytlschallenge" # <== Defining certsresolvers for https
################################################
#### DB Container not on traefik #####
##############################################
db:
image: mysql:5.7
restart: always
environment:
MYSQL_DATABASE: exampledb
MYSQL_USER: exampleuser
MYSQL_PASSWORD: examplepass
MYSQL_RANDOM_ROOT_PASSWORD: '1'
volumes:
- db:/var/lib/mysql
networks:
- backend
networks:
web:
external: true
backend:
external: false
volumes:
wordpress:
external: true
db:
external: true
@thejasonfisher
Copy link

I had some interesting problems with networking and some applications giving gateway errors while others worked fine.

Ultimately, I separated everything into three docker-compose files and created one external traefik-proxy network.

  • The first with traefik and only the traefik_proxy external network defined.

  • The second with the application front-end -- Wordpress, etc. This used the existing traefik_proxy network (e.g. web here) and defined one new network just called "backend:" in the network definitions, no other args -- this used the directory name and ultimately created a self/'dynamic' network called wordpress_backend. Everything in this docker-compose was defined as network "- traefik_proxy" and "- backend", all - port lines were commented out or replaced with - expose.

  • The third with the application backend/databases -- these have "backend:" defined as "external: name: wordpress_backend" and everything is only on network: -backend.

Yes, you have to start the application front-end before the back-end.. and I did have the docker network defined, but it randomly dropped requests. I think having the web/proxy network as the only non-auto network helped?

@taro-cmd
Copy link

How are these labels translated into a yaml if i only want to use helm or kubectl create -f file?
If i tried to use labels such as these traefik.http.routers.nginx-web.rule=Host(example.com), i would get an syntax error as it does not accept colon and slashes in the yaml.

Also for traefik.http.routers.nginx-web.rule=Host(example.com, you placed nginx-web. Where is nginx-web coming from ? Is that any name for the routers?

@nlebellier
Copy link

I had some interesting problems with networking and some applications giving gateway errors while others worked fine.

Ultimately, I separated everything into three docker-compose files and created one external traefik-proxy network.

  • The first with traefik and only the traefik_proxy external network defined.
  • The second with the application front-end -- Wordpress, etc. This used the existing traefik_proxy network (e.g. web here) and defined one new network just called "backend:" in the network definitions, no other args -- this used the directory name and ultimately created a self/'dynamic' network called wordpress_backend. Everything in this docker-compose was defined as network "- traefik_proxy" and "- backend", all - port lines were commented out or replaced with - expose.
  • The third with the application backend/databases -- these have "backend:" defined as "external: name: wordpress_backend" and everything is only on network: -backend.

Yes, you have to start the application front-end before the back-end.. and I did have the docker network defined, but it randomly dropped requests. I think having the web/proxy network as the only non-auto network helped?

Hi. I met some issues about gateway. Does your solution is available somewhere ?

@PatrickLaabs
Copy link

Greetings,

I might found a mistyping on line 98.
Formatting seems not to be correct, and since I reformatted it, it seems
to work fine for me so far.

@mendelor
Copy link

ERROR: yaml.parser.ParserError: while parsing a block mapping
in "./docker-compose.yml", line 1, column 1
expected , but found ''
in "./docker-compose.yml", line 97, column 2

@PatrickLaabs
Copy link

ERROR: yaml.parser.ParserError: while parsing a block mapping
in "./docker-compose.yml", line 1, column 1
expected , but found ''
in "./docker-compose.yml", line 97, column 2

Remove the space on line 98 to align it with networks on line 92

@mendelor
Copy link

I Removed every spaces, still the same error.

ERROR: yaml.parser.ParserError: while parsing a block mapping
in "./docker-compose.yml", line 1, column 1
expected , but found ''
in "./docker-compose.yml", line 87, column 2

@mendelor
Copy link

version: '3.3'
services:
traefik:
image: traefik:v2.0
restart: always
container_name: traefik
ports:
- "80:80" # <== http
- "8080:8080" # <== :8080 is where the dashboard runs on
- "443:443" # <== https
command:
#### These are the CLI commands that will configure Traefik and tell it how to work! ####
## API Settings - https://docs.traefik.io/operations/api/, endpoints - https://docs.traefik.io/operations/api/#endpoints ##
- --api.insecure=true # <== Enabling insecure api, NOT RECOMMENDED FOR PRODUCTION
- --api.dashboard=true # <== Enabling the dashboard to view services, middlewares, routers, etc...
- --api.debug=true # <== Enabling additional endpoints for debugging and profiling
## Log Settings (options: ERROR, DEBUG, PANIC, FATAL, WARN, INFO) - https://docs.traefik.io/observability/logs/ ##
- --log.level=DEBUG # <== Setting the level of the logs from traefik
## Provider Settings - https://docs.traefik.io/providers/docker/#provider-configuration ##
- --providers.docker=true # <== Enabling docker as the provider for traefik
- --providers.docker.exposedbydefault=false # <== Don't expose every container to traefik, only expose enabled ones
- --providers.file.filename=/dynamic.yaml # <== Referring to a dynamic configuration file
- --providers.docker.network=web # <== Operate on the docker network named web
## Entrypoints Settings - https://docs.traefik.io/routing/entrypoints/#configuration ##
- --entrypoints.web.address=:80 # <== Defining an entrypoint for port :80 named web
- --entrypoints.web-secured.address=:443 # <== Defining an entrypoint for https on port :443 named web-secured
## Certificate Settings (Let's Encrypt) - https://docs.traefik.io/https/acme/#configuration-examples ##
- --certificatesresolvers.mytlschallenge.acme.tlschallenge=true # <== Enable TLS-ALPN-01 to generate and renew ACME certs
- --certificatesresolvers.mytlschallenge.acme.email=theafkdeveloper@gmail.com # <== Setting email for certs
- --certificatesresolvers.mytlschallenge.acme.storage=/letsencrypt/acme.json # <== Defining acme file to store cert information
volumes:
- ./letsencrypt:/letsencrypt # <== Volume for certs (TLS)
- /var/run/docker.sock:/var/run/docker.sock # <== Volume for docker admin
- ./dynamic.yaml:/dynamic.yaml # <== Volume for dynamic conf file, **ref: line 27
networks:
- web # <== Placing traefik on the network named web, to access containers on this network
labels:
#### Labels define the behavior and rules of the traefik proxy for this container ####
- "traefik.enable=true" # <== Enable traefik on itself to view dashboard and assign subdomain to view it
- "traefik.http.routers.api.rule=Host(monitor.example.com)" # <== Setting the domain for the dashboard
- "traefik.http.routers.api.service=api@internal" # <== Enabling the api to be a service to access
wordpress: # <== we aren't going to open :80 here because traefik is going to serve this on entrypoint 'web'

:80 is already exposed from within the container

image: wordpress
restart: always
container_name: wp
environment:
  WORDPRESS_DB_HOST: db
  WORDPRESS_DB_USER: exampleuser
  WORDPRESS_DB_PASSWORD: examplepass
  WORDPRESS_DB_NAME: exampledb
volumes:
  - wordpress:/var/www/html
networks:
  - web
  - backend
labels:
  #### Labels define the behavior and rules of the traefik proxy for this container ####
  - "traefik.enable=true" # <== Enable traefik to proxy this container
  - "traefik.http.routers.nginx-web.rule=Host(`example.com`)" # <== Your Domain Name goes here for the http rule
  - "traefik.http.routers.nginx-web.entrypoints=web" # <== Defining the entrypoint for http, **ref: line 30
  - "traefik.http.routers.nginx-web.middlewares=redirect@file" # <== This is a middleware to redirect to https
  - "traefik.http.routers.nginx-secured.rule=Host(`example.com`)" # <== Your Domain Name for the https rule 
  - "traefik.http.routers.nginx-secured.entrypoints=web-secured" # <== Defining entrypoint for https, **ref: line 31
  - "traefik.http.routers.nginx-secured.tls.certresolver=mytlschallenge" # <== Defining certsresolvers for https

db:
image: mysql:5.7
restart: always
environment:
MYSQL_DATABASE: exampledb
MYSQL_USER: exampleuser
MYSQL_PASSWORD: examplepass
MYSQL_RANDOM_ROOT_PASSWORD: '1'
volumes:
- db:/var/lib/mysql
networks:
- backend
networks:
web:
external: true
backend:
external: false
volumes:
wordpress:
external: true
db:
external: true

@mendelor
Copy link

Can you please write down the correct compose file?

@PatrickLaabs
Copy link

Can you please write down the correct compose file?

https://github.com/PatrickLaabs/traefik-proxy/blob/main/docker-compose.yml

@mendelor
Copy link

Thank you so much PatrickLaabs :)

@PatrickLaabs
Copy link

Thank you so much PatrickLaabs :)

You're welcome :)

@benrich
Copy link

benrich commented Jan 26, 2021

I have a problem that brought me to this example. This example has the same problem and I'm hoping it's a good place to fix it.

After running docker-compose up -d and installing wordpress. Go to backend > Tools > Site Health. Notice there are errors to do with port 443. I suspect it's because example.com resolves to localhost. Localhost doesn't handle SSL/TLS certs.

It's really easy to replicate with this example. Any clue what's going on? Thanks

@CarbonaraJack
Copy link

Thank you for this gist, it helped me understand traefik a bit better.

Just wanted to let you know that you can avoid the http -> https redirect middleware all-together if you remove the nginx-web router.
Traefik seems smart enough to do routing on its own if you do not have any router pointing to your 80 port.
Mind you, you still need to keep 80 open to get your certificates, but you can safely use web-secured for everything else.
I tested this on my server with traefik 2.4, so you might want to test it before adding it to the gist, as it might not work with 2.0.

Also, you might want to replace your email in the gist, or people might use it for their own certificates.

@Abhishek49
Copy link

Thanks for this gist. I have a use case where I don't want to expose few services to external web. I want these services to be called by other services inside the network. In other words, I only want to leverage the load balancer and traefik middlewares when calling these services from other services in the network. Is this possible?
Thanks in advance

@ozywuli
Copy link

ozywuli commented Jun 30, 2021

this was helpful for getting me up and running on traefik. much respect ✊

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment