├── .github └── ISSUE_TEMPLATE │ ├── bug_report.md │ └── feature_request.md ├── 00-Setup-Lab-Environment └── setup.md ├── 01-Traefik-Overview ├── docker-compose.yml ├── traefik_overview.md └── whoami.yml ├── 02-Configure-Traefik ├── docker-compose.cli.yml ├── docker-compose.configuration.yml ├── docker-compose.env.yml ├── docker-compose.file.yml ├── traefik-configuration.md ├── traefik-entrypoints.yml └── traefik.yml ├── 03-Routers-and-Services ├── docker-compose.answers.yml ├── docker-compose.yml ├── traefik-routers-and-services.md └── traefik.yml ├── 04-HTTPS-TLS ├── docker-compose.dns.yml ├── docker-compose.http.yml ├── docker-compose.tls.yml ├── letsencrypt │ └── test ├── traefik-https-tls.md ├── traefik.dns.yml ├── traefik.http.yml └── traefik.tls.yml ├── 05-Middlewares ├── docker-compose.auth.yml ├── docker-compose.compress.yml ├── docker-compose.error.yml ├── docker-compose.ratelimit.yml ├── docker-compose.redirect.yml ├── traefik-middlewares.md ├── traefik.dns.yml └── traefik.yml ├── 06-Observability ├── docker-compose.access-log.yml ├── docker-compose.log.yml ├── docker-compose.metrics.yml ├── grafana │ ├── config.monitoring │ └── provisioning │ │ ├── dashboards │ │ ├── dashboard.yml │ │ └── traefik_rev4.json │ │ └── datasources │ │ └── datasource.yml ├── prometheus │ ├── alert.rules │ └── prometheus.yml ├── traefik-observability.md ├── traefik.access-log.yml ├── traefik.metrics.yml └── traefik.yml ├── 07-Operations ├── docker-compose.cli.yml ├── traefik-operations.md └── traefik.yml ├── 08-Advanced-Tips ├── docker-compose.pilot.yml ├── traefik-advanced-tips.md └── traefik.yml ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── LICENSE ├── README.md └── img ├── 56k-logo.svg ├── Traefik_training.png ├── catapp_router_error.png ├── catapp_router_service.png ├── catapp_router_service_name.png ├── traefik-dns-wildcard.png ├── traefik-dns.png ├── traefik-pilot-instance-registration.png └── traefik_logo.png /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | A clear and concise description of what the bug is. 12 | 13 | **To Reproduce** 14 | Steps to reproduce the behavior: 15 | 1. Go to '...' 16 | 2. Click on '....' 17 | 3. Scroll down to '....' 18 | 4. See error 19 | 20 | **Expected behavior** 21 | A clear and concise description of what you expected to happen. 22 | 23 | **Screenshots** 24 | If applicable, add screenshots to help explain your problem. 25 | 26 | **Desktop (please complete the following information):** 27 | - OS: [e.g. iOS] 28 | - Browser [e.g. chrome, safari] 29 | - Version [e.g. 22] 30 | 31 | **Smartphone (please complete the following information):** 32 | - Device: [e.g. iPhone6] 33 | - OS: [e.g. iOS8.1] 34 | - Browser [e.g. stock browser, safari] 35 | - Version [e.g. 22] 36 | 37 | **Additional context** 38 | Add any other context about the problem here. 39 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Is your feature request related to a problem? Please describe.** 11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 12 | 13 | **Describe the solution you'd like** 14 | A clear and concise description of what you want to happen. 15 | 16 | **Describe alternatives you've considered** 17 | A clear and concise description of any alternative solutions or features you've considered. 18 | 19 | **Additional context** 20 | Add any other context or screenshots about the feature request here. 21 | -------------------------------------------------------------------------------- /00-Setup-Lab-Environment/setup.md: -------------------------------------------------------------------------------- 1 | # Setup Lab Environment 2 | 3 | Traefik Logo 4 | 5 | ## LAB Prerequisites 6 | 7 | 1. Install Docker for Desktop Windows or Mac. 8 | 9 | **Linux** - Install your flavor of Docker for Linux https://docs.docker.com/engine/install/ 10 | 11 | **Mac** - https://docs.docker.com/docker-for-mac/install/ 12 | 13 | **Windows** - https://docs.docker.com/docker-for-windows/install/ 14 | 15 | **For Windows users, ensure you switch to Linux containers** - https://docs.docker.com/docker-for-windows/#switch-between-windows-and-linux-containers 16 | 17 | 2. Once Docker is installed, let's verify the docker installation. Open a terminal window (Windows users open Powershell with Admin rights). Next, run the following command 18 | 19 | ```docker 20 | docker run hello-world 21 | ``` 22 | 23 | 3. If the command completes successfully you should see a hello message from Docker. If the command failed, be sure to revisit the step 1 instructions on installing Docker for Desktop for your Operating System. 24 | 25 | 4. Install Git, so we can check out the Labs - https://git-scm.com/downloads or GitHub Desktop https://desktop.github.com/ 26 | 27 | What if Docker Desktop doesn't work? 28 | In some cases, Docker Desktop will not work due to the version of your operating system of IT policies in your company. Don't worry, we have a solution for this as well. 29 | 30 | You can use the online Docker console provided by Docker. This works entirely in your browser - https://labs.play-with-docker.com/ 31 | 32 | Check out the Labs 33 | Now, let's check out the Labs which contain all the resources for each lab. From your terminal window, Git client, GitHub Desktop, or Visual Studio code clone the Traefik Training Repo. 34 | 35 | ```bash 36 | git clone https://github.com/56kcloud/traefik-training.git 37 | ``` 38 | 39 | You can find the Traefik Training GitHub Repo here - https://github.com/56kcloud/traefik-training 40 | 41 | ## Questions 42 | If you have a question or need help, be sure to ask a question in the comments or reach out to our support team. 43 | 44 | # Continue to the Traefik Overview Lab 45 | 46 | ### Click here to continue -> [Configure Traefik](https://github.com/56kcloud/traefik-training/blob/master/01-Traefik-Overview/traefik_overview.md) -------------------------------------------------------------------------------- /01-Traefik-Overview/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3' 2 | 3 | services: 4 | traefik: 5 | # The latest official supported Traefik docker image 6 | image: traefik:v2.3 7 | # Enables the Traefik Dashboard and tells Traefik to listen to docker 8 | # --providers tell Traefik to connect to the Docker provider 9 | # enable --log.level=INFO so we can see what Traefik is doing in the log files 10 | command: --api.insecure=true --providers.docker --log.level=INFO 11 | ports: 12 | # Exposes port 80 for incoming web requests 13 | - "80:80" 14 | # The Web UI port http://0.0.0.0:8080 (enabled by --api.insecure=true) 15 | - "8080:8080" 16 | volumes: 17 | # So that Traefik can listen to the Docker events 18 | - /var/run/docker.sock:/var/run/docker.sock 19 | 20 | # Add the whoami service 21 | whoami: 22 | # A container that exposes an API to show its IP address 23 | image: containous/whoami 24 | # We set a label to tell Traefik to assign a hostname to the new service 25 | labels: 26 | - "traefik.http.routers.whoami.rule=Host(`whoami.docker.localhost`)" -------------------------------------------------------------------------------- /01-Traefik-Overview/traefik_overview.md: -------------------------------------------------------------------------------- 1 | # Getting Started with Traefik 2 | 3 | Traefik Logo 4 | 5 | 6 | ## 1. Starting Traefik for the first time 7 | 1. Open you Terminal window and change to the `01-Traefik-Overview` folder 8 | 2. Open the `docker-compose.yml` file in your favorite editor and review how Docker starts Traefik 9 | 3. From the `01-Traefik-Overview` directory execute this command -> `docker-compose up -d` 10 | 4. Review the logs output `docker-compose logs` 11 | 12 | ## 2. Connect a new service to Traefik 13 | 1. Uncomment the below whoami section inside the `docker-compose.yml`. Review the `whoami.yml` file for the complete solution. 14 | 15 | ```yaml 16 | whoami: 17 | # A container that exposes an API to show its IP address 18 | image: containous/whoami 19 | # We set a label to tell Traefik to assign a hostname to the new service 20 | labels: 21 | - "traefik.http.routers.whoami.rule=Host(`whoami.docker.localhost`)" 22 | ``` 23 | 24 | 2. Run `docker-compose up -d whoami` 25 | 3. Open a browser tab and paste `whoami.docker.localhost` or from a terminal window `curl -H Host:whoami.docker.localhost http://127.0.0.1` and you should see the below results but with your IP addresses. 26 | 27 | ```yml 28 | Hostname: 931789a57923 29 | IP: 127.0.0.1 30 | IP: 172.20.0.3 31 | RemoteAddr: 172.20.0.2:46648 32 | GET / HTTP/1.1 33 | Host: whoami.docker.localhost 34 | User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.89 Safari/537.36 35 | Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9 36 | Accept-Encoding: gzip, deflate, br 37 | Accept-Language: en-GB,en-US;q=0.9,en;q=0.8 38 | Cache-Control: max-age=0 39 | Sec-Fetch-Dest: document 40 | Sec-Fetch-Mode: navigate 41 | Sec-Fetch-Site: none 42 | Sec-Fetch-User: ?1 43 | Upgrade-Insecure-Requests: 1 44 | X-Forwarded-For: 172.20.0.1 45 | X-Forwarded-Host: whoami.docker.localhost 46 | X-Forwarded-Port: 80 47 | X-Forwarded-Proto: http 48 | X-Forwarded-Server: 07d5bffe1678 49 | X-Real-Ip: 172.20.0.1 50 | 51 | ``` 52 | 53 | ## 3. Scale the Whoami service to 3x 54 | 1. Open you Terminal window and change to the `01-Traefik-Overview` folder 55 | 2. Let's scale the `whoami` service to 3x instances by typing `docker-compose up -d --scale whoami=3` 56 | 3. Open a browser tab and paste `whoami.docker.localhost` or from a terminal window `curl -H Host:whoami.docker.localhost http://127.0.0.1` and you should see the 3rd IP address update based on which service is responding. 57 | 58 | ## 4. Get to know the Traefik Dashboard 59 | 1. Open a browser tab and type or click: http://0.0.0.0:8080 to open the Traefik Dashboard 60 | 61 | 62 | # Continue to the Configure Traefik Lab 63 | 64 | ### Click here to continue -> [Configure Traefik](https://github.com/56kcloud/traefik-training/blob/master/02-Configure-Traefik/traefik-configuration.md) 65 | -------------------------------------------------------------------------------- /01-Traefik-Overview/whoami.yml: -------------------------------------------------------------------------------- 1 | version: '3' 2 | 3 | services: 4 | traefik: 5 | # The latest official supported Traefik docker image 6 | image: traefik:v2.3 7 | # Enables the Traefik Dashboard and tells Traefik to listen to docker 8 | # --providers tell Traefik to connect to the Docker provider 9 | # enable --log.level=INFO so we can see what Traefik is doing in the log files 10 | command: --api.insecure=true --providers.docker --log.level=INFO 11 | ports: 12 | # Exposes port 80 for incoming web requests 13 | - "80:80" 14 | # The Web UI port http://0.0.0.0:8080 (enabled by --api.insecure=true) 15 | - "8080:8080" 16 | volumes: 17 | # So that Traefik can listen to the Docker events 18 | - /var/run/docker.sock:/var/run/docker.sock 19 | 20 | # Add the whoami service 21 | whoami: 22 | # A container that exposes an API to show its IP address 23 | image: containous/whoami 24 | # We set a label to tell Traefik to assign a hostname to the new service 25 | labels: 26 | - "traefik.http.routers.whoami.rule=Host(`whoami.docker.localhost`)" -------------------------------------------------------------------------------- /02-Configure-Traefik/docker-compose.cli.yml: -------------------------------------------------------------------------------- 1 | version: '3' 2 | 3 | services: 4 | traefik: 5 | # The latest official supported Traefik docker image 6 | image: traefik:v2.3 7 | # Enables the Traefik Dashboard and tells Traefik to listen to docker 8 | # --providers tell Traefik to connect to the Docker provider 9 | # enable --log.level=INFO so we can see what Traefik is doing in the log files 10 | command: 11 | - "--api.insecure=true" 12 | - "--providers.docker" 13 | - "--log.level=INFO" 14 | ports: 15 | # Exposes port 80 for incoming web requests 16 | - "80:80" 17 | # The Web UI port http://0.0.0.0:8080 (enabled by --api.insecure=true) 18 | - "8080:8080" 19 | volumes: 20 | # So that Traefik can listen to the Docker events 21 | - /var/run/docker.sock:/var/run/docker.sock 22 | 23 | # Add the whoami service 24 | whoami: 25 | # A container that exposes an API to show its IP address 26 | image: containous/whoami 27 | # We set a label to tell Traefik to assign a hostname to the new service 28 | labels: 29 | - "traefik.http.routers.whoami.rule=Host(`whoami.docker.localhost`)" -------------------------------------------------------------------------------- /02-Configure-Traefik/docker-compose.configuration.yml: -------------------------------------------------------------------------------- 1 | version: '3' 2 | 3 | services: 4 | traefik: 5 | # The latest official supported Traefik docker image 6 | image: traefik:v2.3 7 | # Enables the Traefik Dashboard and tells Traefik to listen to docker 8 | # enable --log.level=INFO so we can see what Traefik is doing in the log files 9 | ports: 10 | # Exposes port 80 for incoming web requests 11 | - "80:80" 12 | - "443:443" 13 | # The Web UI port http://0.0.0.0:8080 (enabled by --api.insecure=true) 14 | - "8080:8080" 15 | volumes: 16 | # So that Traefik can listen to the Docker events 17 | - /var/run/docker.sock:/var/run/docker.sock 18 | - ./traefik-entrypoints.yml:/etc/traefik/traefik.yml 19 | 20 | # Add the catapp service 21 | catapp: 22 | # A Random Cat GIF generator application 23 | image: mikesir87/cats:1.0 24 | # We set a label to tell Traefik to assign a hostname to the new service 25 | labels: 26 | - "traefik.enable=true" 27 | - "traefik.http.routers.catapp.rule=Host(`catapp.localhost`)" 28 | - "traefik.http.routers.catapp.entrypoints=web" 29 | - "traefik.http.services.catapp.loadbalancer.server.port=5000" 30 | -------------------------------------------------------------------------------- /02-Configure-Traefik/docker-compose.env.yml: -------------------------------------------------------------------------------- 1 | version: '3' 2 | 3 | services: 4 | traefik: 5 | # The latest official supported Traefik docker image 6 | image: traefik:v2.3 7 | # Enables the Traefik Dashboard and tells Traefik to listen to docker 8 | # --providers tell Traefik to connect to the Docker provider 9 | # enable --log.level=INFO so we can see what Traefik is doing in the log files 10 | environment: 11 | - TRAEFIK_API_INSECURE=true 12 | - TRAEFIK_PROVIDERS_DOCKER=true 13 | - TRAEFIK_LOG_LEVEL=INFO 14 | ports: 15 | # Exposes port 80 for incoming web requests 16 | - "80:80" 17 | # The Web UI port http://0.0.0.0:8080 (enabled by --api.insecure=true) 18 | - "8080:8080" 19 | volumes: 20 | # So that Traefik can listen to the Docker events 21 | - /var/run/docker.sock:/var/run/docker.sock 22 | 23 | # Add the whoami service 24 | whoami: 25 | # A container that exposes an API to show its IP address 26 | image: containous/whoami 27 | # We set a label to tell Traefik to assign a hostname to the new service 28 | labels: 29 | - "traefik.http.routers.whoami.rule=Host(`whoami.docker.localhost`)" -------------------------------------------------------------------------------- /02-Configure-Traefik/docker-compose.file.yml: -------------------------------------------------------------------------------- 1 | version: '3' 2 | 3 | services: 4 | traefik: 5 | # The latest official supported Traefik docker image 6 | image: traefik:v2.3 7 | # Enables the Traefik Dashboard and tells Traefik to listen to docker 8 | # enable --log.level=INFO so we can see what Traefik is doing in the log files 9 | ports: 10 | # Exposes port 80 for incoming web requests 11 | - "80:80" 12 | # The Web UI port http://0.0.0.0:8080 (enabled by --api.insecure=true) 13 | - "8080:8080" 14 | volumes: 15 | # So that Traefik can listen to the Docker events 16 | - /var/run/docker.sock:/var/run/docker.sock 17 | - ./traefik.yml:/etc/traefik/traefik.yml 18 | 19 | # Add the whoami service 20 | whoami: 21 | # A container that exposes an API to show its IP address 22 | image: containous/whoami 23 | # We set a label to tell Traefik to assign a hostname to the new service 24 | labels: 25 | - "traefik.http.routers.whoami.rule=Host(`whoami.docker.localhost`)" -------------------------------------------------------------------------------- /02-Configure-Traefik/traefik-configuration.md: -------------------------------------------------------------------------------- 1 | # Configure Traefik 2 | 3 | Traefik Logo 4 | 5 | 6 | ## 1. Static Configuration using File configuration 7 | 1. Clean up previous Lab. Open you Terminal window and change to the `01-Traefik-Overview` directory. Stop the previous section Lab `docker-compose stop` 8 | 2. Change to the `02-Configure-Traefik` folder 9 | 3. Open the `docker-compose.file.yml` file in your favorite editor and review how Docker starts Traefik using the file configuration 10 | 4. From the `02-Traefik-Overview` directory execute this command -> `docker-compose -f docker-compose.file.yml up -d` 11 | 5. Review the logs output `docker-compose -f docker-compose.file.yml logs` 12 | 6. Stop and clean-up `docker-compose -f docker-compose.file.yml stop` 13 | 14 | ### File static config code snippet 15 | 16 | ```yaml 17 | ################################################################ 18 | # API and dashboard configuration 19 | ################################################################ 20 | api: 21 | # Dashboard 22 | # 23 | # 24 | dashboard: true 25 | ################################################################ 26 | # Docker configuration backend 27 | ################################################################ 28 | providers: 29 | docker: 30 | watch: false 31 | exposedByDefault: false 32 | swarmMode: true 33 | ################################################################ 34 | # Traefik Logging 35 | ################################################################ 36 | log: 37 | level: INFO 38 | ``` 39 | 40 | 41 | ## 2. Static Configuration using CLI configuration 42 | 1. Open the `docker-compose.cli.yml` file in your favorite editor and review how Docker starts Traefik using the CLI configuration 43 | 2. From the `02-Configure-Traefik` directory execute this command -> `docker-compose -f docker-compose.cli.yml up -d` 44 | 3. Review the logs output `docker-compose -f docker-compose.cli.yml logs` 45 | 4. Stop and clean-up `docker-compose -f docker-compose.cli.yml stop` 46 | 47 | ### CLI static config code snippet 48 | 49 | ```yml 50 | services: 51 | traefik: 52 | # The latest official supported Traefik docker image 53 | image: traefik:v2.3 54 | # Enables the Traefik Dashboard and tells Traefik to listen to docker 55 | # --providers tell Traefik to connect to the Docker provider 56 | # enable --log.level=INFO so we can see what Traefik is doing in the log files 57 | command: 58 | - "--api.insecure=true" 59 | - "--providers.docker" 60 | - "--log.level=INFO" 61 | ``` 62 | 63 | ## 3. Static Configuration using Environment variables configuration 64 | 1. Open the `docker-compose.env.yml` file in your favorite editor and review how Docker starts Traefik using the Environment configuration 65 | 2. From the `02-Configure-Traefik` directory execute this command -> `docker-compose -f docker-compose.env.yml up -d` 66 | 3. Review the logs output `docker-compose -f docker-compose.env.yml logs` 67 | 4. Stop and clean-up `docker-compose -f docker-compose.env.yml stop` 68 | 69 | ### Environment variables static config code snippet 70 | ```yml 71 | services: 72 | traefik: 73 | # The latest official supported Traefik docker image 74 | image: traefik:v2.3 75 | # Enables the Traefik Dashboard and tells Traefik to listen to docker 76 | # --providers tell Traefik to connect to the Docker provider 77 | # enable --log.level=INFO so we can see what Traefik is doing in the log files 78 | environment: 79 | - TRAEFIK_API_INSECURE=true 80 | - TRAEFIK_PROVIDERS_DOCKER=true 81 | - TRAEFIK_LOG_LEVEL=INFO 82 | ``` 83 | 84 | ## 4. Static Configuration Entrypoint Lab 85 | In this section, we will start using Docker Swarm. Ensure you have followed the Prerequisites from the Lab Setup. This can be found in the Getting Started Section of the course if you need to revisit. If you have any issues please add a comment in the course. 86 | 87 | ## NOTE about Docker ## 88 | We use the `docker stack deploy -c ` command to deploy Swarm services. `docker stack ps ` is used to check if all services are running in the stack. Finally, `docker stack rm ` removes the entire stack. 89 | 90 | To check logs on a running service, `docker service ls` to retrieve the name of the service and `docker service logs ` to vier it's logs. 91 | 92 | Further Docker information can be found here for [Docker Stack](https://docs.docker.com/engine/reference/commandline/stack/) or [Docker services](https://docs.docker.com/engine/reference/commandline/service/) 93 | 94 | 1. Open the `traefik-entrypoints.yml` and `docker-compose.configuration.yml` files in your favorite editor and review how Entrypoints are created and how we are using the YML file in this Lab. 95 | 2. From the `02-Configure-Traefik` directory execute this command -> `docker stack deploy -c docker-compose.configuration.yml catapp` 96 | 3. Open the Traefik Dashboard [http://0.0.0.0:8080](http://0.0.0.0:8080) and review how the test service `catapp` is configured with **Entrypoints**. 97 | 4. Review the `catapp@docker` router and `catapp@docker` service in the Traefik Dashboard 98 | 5. Test the newly deployed `catapp` service [http://catapp.localhost/](http://catapp.localhost/) 99 | 6. Stop and clean-up `docker stack rm catapp` 100 | 101 | 102 | # Continue to the Next Lab Routers & Services 103 | 104 | ### Click here to continue -> [Routers & Services Lab](https://github.com/56kcloud/traefik-training/blob/master/03-Routers-and-Services/traefik-routers-and-services.md) -------------------------------------------------------------------------------- /02-Configure-Traefik/traefik-entrypoints.yml: -------------------------------------------------------------------------------- 1 | ################################################################ 2 | # API and dashboard configuration 3 | ################################################################ 4 | api: 5 | # Dashboard 6 | # 7 | # 8 | dashboard: true 9 | insecure: true 10 | ################################################################ 11 | # Docker configuration backend 12 | ################################################################ 13 | providers: 14 | docker: 15 | exposedByDefault: false 16 | ################################################################ 17 | # Traefik Logging 18 | ################################################################ 19 | log: 20 | level: DEBUG 21 | 22 | ################################################################ 23 | # Entrypoint 24 | ################################################################ 25 | entryPoints: 26 | web: 27 | address: ":80" 28 | websecure: 29 | address: ":443" 30 | -------------------------------------------------------------------------------- /02-Configure-Traefik/traefik.yml: -------------------------------------------------------------------------------- 1 | ################################################################ 2 | # API and dashboard configuration 3 | ################################################################ 4 | api: 5 | # Dashboard 6 | # 7 | # 8 | dashboard: true 9 | insecure: true 10 | ################################################################ 11 | # Docker configuration backend 12 | ################################################################ 13 | providers: 14 | docker: 15 | watch: true 16 | exposedByDefault: false 17 | swarmMode: true 18 | ################################################################ 19 | # Traefik Logging 20 | ################################################################ 21 | log: 22 | level: INFO -------------------------------------------------------------------------------- /03-Routers-and-Services/docker-compose.answers.yml: -------------------------------------------------------------------------------- 1 | version: '3' 2 | 3 | services: 4 | traefik: 5 | # The latest official supported Traefik docker image 6 | image: traefik:v2.3 7 | # Enables the Traefik Dashboard and tells Traefik to listen to docker 8 | # enable --log.level=INFO so we can see what Traefik is doing in the log files 9 | ports: 10 | # Exposes port 80 for incoming web requests 11 | - "80:80" 12 | - "443:443" 13 | # The Web UI port http://0.0.0.0:8080 (enabled by --api.insecure=true) 14 | - "8080:8080" 15 | volumes: 16 | # So that Traefik can listen to the Docker events 17 | - /var/run/docker.sock:/var/run/docker.sock 18 | - ./traefik.yml:/etc/traefik/traefik.yml 19 | 20 | # Add the catapp service 21 | catapp: 22 | # A Random Cat GIF generator application 23 | image: mikesir87/cats:1.0 24 | # We set a label to tell Traefik to assign a hostname to the new service 25 | labels: 26 | - "traefik.enable=true" 27 | - "traefik.http.routers.catapp.rule=Host(`catapp.localhost`)" 28 | - "traefik.http.routers.catapp.entrypoints=web" 29 | - "traefik.http.routers.catapp.service=catapp" 30 | - "traefik.http.services.catapp.loadbalancer.server.port=5000" 31 | -------------------------------------------------------------------------------- /03-Routers-and-Services/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3' 2 | 3 | services: 4 | traefik: 5 | # The latest official supported Traefik docker image 6 | image: traefik:v2.3 7 | # Enables the Traefik Dashboard and tells Traefik to listen to docker 8 | # enable --log.level=INFO so we can see what Traefik is doing in the log files 9 | ports: 10 | # Exposes port 80 for incoming web requests 11 | - "80:80" 12 | - "443:443" 13 | # The Web UI port http://0.0.0.0:8080 (enabled by --api.insecure=true) 14 | - "8080:8080" 15 | volumes: 16 | # So that Traefik can listen to the Docker events 17 | - /var/run/docker.sock:/var/run/docker.sock 18 | - ./traefik.yml:/etc/traefik/traefik.yml 19 | 20 | # Add the catapp service 21 | catapp: 22 | image: mikesir87/cats:1.0 23 | # labels: 24 | # - "traefik.enable=true" 25 | # - "traefik.http.routers.catapp.rule=Host(`catapp.localhost`)" 26 | # - "traefik.http.routers.catapp.entrypoints=web" 27 | # - "traefik.http.routers.catapp.service=catapp" 28 | # - "traefik.http.services.catapp.loadbalancer.server.port=5000" 29 | -------------------------------------------------------------------------------- /03-Routers-and-Services/traefik-routers-and-services.md: -------------------------------------------------------------------------------- 1 | # Traefik Routers & Services Lab 2 | 3 | Traefik Logo 4 | 5 | 6 | ## 1. Deploying a Traefik Router, Service, and Load balancer step-by-step 7 | 1. Before we begin, lets cleanup any running Docker stack `docker stack rm traefik` If you named you stack something else use your specified name. If you don't remember run `docker stack ls` 8 | 2. Change to the `03-Routers-and-Services` folder 9 | 3. Open the `docker-compose.yml` file in your favorite editor and review the `catapp` section 10 | 4. Start Traefik and the `catapp` but with no labels `docker stack deploy -c docker-compose.yml traefik` 11 | 5. Open the Traefik Dashboard [http://0.0.0.0:8080](http://0.0.0.0:8080) and verify Traefik is running and `catapp` does not have a router or service in Traefik. 12 | 6. From the `03-Routers-and-Services` edit the `docker-compose.yml` file and add our first label to the `catapp` as seen below. We are adding/removing the comment from the `labels:` option and uncomment the Traefik label `- "traefik.enable=true"` to enable catapp inside Traefik. 13 | 14 | ```yaml 15 | catapp: 16 | image: mikesir87/cats:1.0 17 | labels: 18 | - "traefik.enable=true" 19 | ``` 20 | 21 | 7. From the `03-Routers-and-Services` directory execute this command -> `docker stack deploy -c docker-compose.yml traefik` **this will update our Docker Swarm Stack with the new Label changes. Changes take about 10-15 seconds to apply** 22 | 8. Open the Traefik Dashboard [http://0.0.0.0:8080](http://0.0.0.0:8080) and review the `catapp` Router & Service. **What do you see?** 23 | 24 | `catapp`is now running but with default configurations provided from Traefik. Now, we will set additional Labels to define the Router Rule, Entrypoint, and service. 25 | 26 | 1. From the `03-Routers-and-Services` directory edit the `docker-compose.yml` file and add the Labels to the `catapp` for a Router rule, define the Entrypoint, and service as seen below. Uncomment the `- "traefik.http.routers.catapp.rule=Host(`catapp.localhost`)"` to define the hostname of our `catapp` as `catapp.localhost`. Next, we define which Entrypoint to use with the **Label** uncomment `- "traefik.http.routers.catapp.entrypoints=web"` to define HTTP/web Entrypoint. Finally, we uncommet the next label `- "traefik.http.routers.catapp.service=catapp"` to tell the Router which Service to use. This is for Demo purposes only as normally Traefik pulls this configuration automatically. The new `catapp` section the `docker-compose.yml` file should look like this: 27 | 28 | ```yaml 29 | catapp: 30 | image: mikesir87/cats:1.0 31 | labels: 32 | - "traefik.enable=true" 33 | - "traefik.http.routers.catapp.rule=Host(`catapp.localhost`)" 34 | - "traefik.http.routers.catapp.entrypoints=web" 35 | - "traefik.http.routers.catapp.service=catapp" 36 | ``` 37 | 38 | 10. From the `03-Routers-and-Services` directory execute this command -> `docker stack deploy -c docker-compose.yml traefik` **this will update our Docker Swarm Stack with the new Label changes. Changes take about 10-15 seconds to apply** 39 | 11. Review the logs output `docker service logs traefik_traefik` **Note the name comes from Stack name + service name. So if you used a different Stack name you need to run `docker service logs `** 40 | 12. The last line in the log file should indicate the issue 41 | 13. Open the Traefik Dashboard [http://0.0.0.0:8080](http://0.0.0.0:8080) and review the `catapp` Router & Service. **What do you see?** 42 | 43 | ## 2. Troubleshooting Router / Service configurations 44 | OK, so we broke our `catapp` What exactly shall we do? Let's investigate why `catapp`is not working with Traefk. 45 | 46 | 1. Open the Traefik Dashboard [http://0.0.0.0:8080](http://0.0.0.0:8080) and notice we have a Router Error. 47 | 2. Click on our **`catapp` Router** to view the error. **Do you notice the error is the same as what we saw in the logs?** 48 | 49 | Traefik Router Error 50 | 51 | 3. In the ****Router Details** of the `catapp` click the on the **Service** -> `catapp` **What do you see?** 52 | 53 | Click Traefik Router Service catapp 54 | 55 | 4. When you click the `catapp` service from the Router Details screen you should have been greeted by an error `Service not found catapp@docker` 56 | 5. In the Traefik Dashboard click the **HTTP Services** Menu 57 | 6. Look at the services, what do you notice about the `catapp` service? 58 | 59 | catapp service name is random 60 | 61 | **NOTE** Take a look at the name of the `catapp` service. You will notice the name is random generated. `traefik-catapp-random` 62 | 63 | 1. From the `03-Routers-and-Services` directory edit the `docker-compose.yml` file and add the Label to the `catapp` to define the Load Balancer port `- "traefik.http.services.catapp.loadbalancer.server.port=5000"` by removing the comment 64 | 2. From the `03-Routers-and-Services` directory execute this command -> `docker stack deploy -c docker-compose.yml traefik` **this will update our Docker Swarm Stack with the new Label changes.** 65 | 3. Open the Traefik Dashboard [http://0.0.0.0:8080](http://0.0.0.0:8080) and wait about 15-20 seconds for the changes to be visible in the dashboard. Notice that the Router error is now cleared. 66 | 4. Navigate to the **Router** menu and notice everything is now healthy 67 | 5. Navigate to the **Services** menu and notice the service is now named `catapp@docker` as intended 68 | 69 | ## 3. Make everything Dynamic 70 | In this Lab we will comment out the **Service** and **Load Balancer** Labels to see how Traefik will *Dynamically* create the service and **Load Balancer**. 71 | 72 | 1. From the `03-Routers-and-Services` directory edit the `docker-compose.yml` file and remove/add comment to the **Labels** `- "traefik.http.routers.catapp.service=catapp"` and `- "traefik.http.services.catapp.loadbalancer.server.port=5000"` from the `catapp`. The only **Labels** enabled as seen below: 73 | 74 | ```yaml 75 | catapp: 76 | image: mikesir87/cats:1.0 77 | labels: 78 | - "traefik.enable=true" 79 | - "traefik.http.routers.catapp.rule=Host(`catapp.localhost`)" 80 | - "traefik.http.routers.catapp.entrypoints=web" 81 | ``` 82 | 83 | 2. From the `03-Routers-and-Services` directory execute this command -> `docker stack deploy -c docker-compose.yml traefik` **this will update our Docker Swarm Stack with the new Label changes.** 84 | 3. Open the Traefik Dashboard [http://0.0.0.0:8080](http://0.0.0.0:8080) and wait about 15-20 seconds for the changes to be visible in the dashboard. 85 | 4. Navigate to the **HTTP Router** & **HTTP Services** menus. You should now see that Traefik Dynamically created service name which is now recognized by the **Router** 86 | 5. Stop and clean-up `docker stack rm traefik` 87 | 88 | ### Solution for the catapp Labels Lab 89 | 90 | Please check the `03-Routers-and-Services/docker-compose.answers.yml` if you get stuck anywhere during the lab or need a reference. 91 | 92 | ```yaml 93 | catapp: 94 | image: mikesir87/cats:1.0 95 | labels: 96 | - "traefik.enable=true" 97 | - "traefik.http.routers.catapp.rule=Host(`catapp.localhost`)" 98 | - "traefik.http.routers.catapp.entrypoints=web" 99 | - "traefik.http.routers.catapp.service=catapp" 100 | - "traefik.http.services.catapp.loadbalancer.server.port=5000" 101 | ``` 102 | 103 | # Continue to the Next Lab HTTPS / TLS / Let's Encrypt Lab 104 | 105 | ### Click here to continue -> [HTTPS & TLS](https://github.com/56kcloud/traefik-training/blob/master/04-HTTPS-TLS/traefik-https-tls.md) 106 | -------------------------------------------------------------------------------- /03-Routers-and-Services/traefik.yml: -------------------------------------------------------------------------------- 1 | ################################################################ 2 | # API and dashboard configuration 3 | ################################################################ 4 | api: 5 | # Dashboard 6 | # 7 | # 8 | dashboard: true 9 | insecure: true 10 | ################################################################ 11 | # Docker configuration backend 12 | ################################################################ 13 | providers: 14 | docker: 15 | exposedByDefault: false 16 | ################################################################ 17 | # Traefik Logging 18 | ################################################################ 19 | log: 20 | level: INFO 21 | 22 | ################################################################ 23 | # Entrypoint 24 | ################################################################ 25 | entryPoints: 26 | web: 27 | address: ":80" 28 | websecure: 29 | address: ":443" 30 | -------------------------------------------------------------------------------- /04-HTTPS-TLS/docker-compose.dns.yml: -------------------------------------------------------------------------------- 1 | version: '3' 2 | 3 | services: 4 | traefik: 5 | # The latest official supported Traefik docker image 6 | image: traefik:v2.3 7 | # Enables the Traefik Dashboard and tells Traefik to listen to docker 8 | # enable --log.level=INFO so we can see what Traefik is doing in the log files 9 | ports: 10 | # Exposes port 80 for incoming web requests 11 | - "80:80" 12 | - "443:443" 13 | # The Web UI port http://0.0.0.0:8080 (enabled by --api.insecure=true) 14 | - "8080:8080" 15 | volumes: 16 | # So that Traefik can listen to the Docker events 17 | - /var/run/docker.sock:/var/run/docker.sock 18 | # Copies the Let's Encrypt certificate locally for ease of backing up 19 | - ./letsencrypt:/letsencrypt 20 | # Mounts the Traefik static configuration inside the Traefik container 21 | - ./traefik.dns.yml:/etc/traefik/traefik.yml 22 | environment: 23 | - "DO_AUTH_TOKEN=" 24 | 25 | # Add the catapp service 26 | catapp: 27 | image: mikesir87/cats:1.0 28 | labels: 29 | - "traefik.enable=true" 30 | - "traefik.http.routers.catapp.rule=Host(`your_domain_here`)" 31 | - "traefik.http.routers.catapp.service=catapp" 32 | - "traefik.http.services.catapp.loadbalancer.server.port=5000" 33 | - "traefik.http.routers.catapp.entrypoints=websecure" 34 | - "traefik.http.routers.catapp.tls.certresolver=myresolver" 35 | -------------------------------------------------------------------------------- /04-HTTPS-TLS/docker-compose.http.yml: -------------------------------------------------------------------------------- 1 | version: '3' 2 | 3 | services: 4 | traefik: 5 | # The latest official supported Traefik docker image 6 | image: traefik:v2.3 7 | # Enables the Traefik Dashboard and tells Traefik to listen to docker 8 | # enable --log.level=INFO so we can see what Traefik is doing in the log files 9 | ports: 10 | # Exposes port 80 for incoming web requests 11 | - "80:80" 12 | - "443:443" 13 | # The Web UI port http://0.0.0.0:8080 (enabled by --api.insecure=true) 14 | - "8080:8080" 15 | volumes: 16 | # So that Traefik can listen to the Docker events 17 | - /var/run/docker.sock:/var/run/docker.sock 18 | # Copies the Let's Encrypt certificate locally for ease of backing up 19 | - ./letsencrypt:/letsencrypt 20 | # Mounts the Traefik static configuration inside the Traefik container 21 | - ./traefik.http.yml:/etc/traefik/traefik.yml 22 | 23 | # Add the catapp service 24 | catapp: 25 | image: mikesir87/cats:1.0 26 | labels: 27 | - "traefik.enable=true" 28 | - "traefik.http.routers.catapp.rule=Host(`your_domain_here`)" 29 | - "traefik.http.routers.catapp.service=catapp" 30 | - "traefik.http.services.catapp.loadbalancer.server.port=5000" 31 | - "traefik.http.routers.catapp.entrypoints=websecure" 32 | - "traefik.http.routers.catapp.tls.certresolver=myresolver" -------------------------------------------------------------------------------- /04-HTTPS-TLS/docker-compose.tls.yml: -------------------------------------------------------------------------------- 1 | version: '3' 2 | 3 | services: 4 | traefik: 5 | # The latest official supported Traefik docker image 6 | image: traefik:v2.3 7 | # Enables the Traefik Dashboard and tells Traefik to listen to docker 8 | # enable --log.level=INFO so we can see what Traefik is doing in the log files 9 | ports: 10 | # Exposes port 80 for incoming web requests 11 | - "80:80" 12 | - "443:443" 13 | # The Web UI port http://0.0.0.0:8080 (enabled by --api.insecure=true) 14 | - "8080:8080" 15 | volumes: 16 | # So that Traefik can listen to the Docker events 17 | - /var/run/docker.sock:/var/run/docker.sock 18 | # Copies the Let's Encrypt certificate locally for ease of backing up 19 | - ./letsencrypt:/letsencrypt 20 | # Mounts the Traefik static configuration inside the Traefik container 21 | - ./traefik.tls.yml:/etc/traefik/traefik.yml 22 | 23 | # Add the catapp service 24 | catapp: 25 | image: mikesir87/cats:1.0 26 | labels: 27 | - "traefik.enable=true" 28 | - "traefik.http.routers.catapp.rule=Host(`your_domain_here`)" 29 | - "traefik.http.routers.catapp.service=catapp" 30 | - "traefik.http.services.catapp.loadbalancer.server.port=5000" 31 | - "traefik.http.routers.catapp.entrypoints=websecure" 32 | - "traefik.http.routers.catapp.tls.certresolver=myresolver" -------------------------------------------------------------------------------- /04-HTTPS-TLS/letsencrypt/test: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/56kcloud/traefik-training/ea35f220dc306d05f69a73c8537da38953beca43/04-HTTPS-TLS/letsencrypt/test -------------------------------------------------------------------------------- /04-HTTPS-TLS/traefik-https-tls.md: -------------------------------------------------------------------------------- 1 | # Traefik HTTPS / TLS / Let’s Encrypt Lab 2 | 3 | Traefik Logo 4 | 5 | # Prerequisite 6 | 7 | **In order to complete this section of the lab you will need a domain name to use for testing. Additionally, ensure your DNS provider is listed in the available DNS Provider integrations section [https://docs.traefik.io/v2.3/https/acme/#providers](https://docs.traefik.io/v2.3/https/acme/#providers)** 8 | 9 | 1. Ensure you have a domain name for testing 10 | 2. Configure the DNS of your domain name to use your Docker server where you will run the below lab. Refer to your domain providers documentation. 11 | 3. I've created the following DNS entries in Digital Ocean to perform all 3 labs. Please adjust your DNS according to where you host Docker and your DNS: 12 | 13 | 14 | Traefik DNS 15 | 16 | 17 | ## 1. Deploy Traefik with Let's Encrypt HTTP Challenge 18 | 1. Before we begin, lets cleanup any running Docker stack `docker stack rm traefik` If you named you stack something else use your specified name. If you don't remember run `docker stack ls` 19 | 2. Change to the `04-HTTPS-and-TLS` folder 20 | 3. Open the `traefik.http.yml` file in your favorite editor and review the `Challenge HTTP` section 21 | 4. Edit the `traefik.http.yml` and edit your `email:` located in the `Challenge HTTP` section 22 | 5. Open the `docker-compose.http.yml` file in your favorite editor and review the `catapp` section 23 | 6. Edit the `docker-compose.http.yml` `catapp` section and add your domain here in the `- "traefik.http.routers.catapp.rule=Host(`your_domain_here`)"` label 24 | 7. Start Traefik and the `catapp` `docker stack deploy -c docker-compose.yml traefik` 25 | 8. Open the Traefik Dashboard [http://0.0.0.0:8080](http://0.0.0.0:8080) and verify Traefik is running and `catapp` has TLS enabled. 26 | 9. Open the `catapp` using the domain you filled in at step 6. Remember to use HTTPS now https://your_domain_here.com 27 | 10. You should now see the `catapp` served with HTTPS and a proper Let's Encrypt Certificate 28 | 29 | ## 2. Deploy Traefik with Let's Encrypt TLS Challenge 30 | 1. Before we begin, lets cleanup the HTTP stack `docker stack rm traefik` If you named you stack something else use your specified name. If you don't remember run `docker stack ls` 31 | 2. Change to the `04-HTTPS-and-TLS` folder 32 | 3. Open the `traefik.tls.yml` file in your favorite editor and review the `Challenge TLS` section 33 | 4. Edit the `traefik.tls.yml` and edit your `email:` located in the `Challenge TLS` section 34 | 5. Open the `docker-compose.http.yml` file in your favorite editor and review the `catapp` section 35 | 6. Edit the `docker-compose.http.yml` `catapp` section and add your domain here in the `- "traefik.http.routers.catapp.rule=Host(`your_domain_here`)"` label 36 | 7. Start Traefik and the `catapp` `docker stack deploy -c docker-compose.yml traefik` 37 | 8. Open the Traefik Dashboard `http://your_domain_here:8080` and verify Traefik is running and `catapp` has TLS enabled. 38 | 9. Open the `catapp` using the domain you filled in at step 6. Remember to use HTTPS now https://your_domain_here.com 39 | 10. You should now see the `catapp` served with HTTPS and a proper Let's Encrypt Certificate 40 | 41 | ## 3. Deploy Traefik with Let's Encrypt DNS Challenge 42 | 1. Before we begin, lets cleanup the TLS stack `docker stack rm traefik` If you named you stack something else use your specified name. If you don't remember run `docker stack ls` 43 | 2. Change to the `04-HTTPS-and-TLS` folder 44 | 3. Log in to your DNS provider and collect the Authorization Tokens for your provider. Review the [https://docs.traefik.io/v2.3/https/acme/#providers](https://docs.traefik.io/v2.3/https/acme/#providers) list to see which tokens you require for your provider. This step is unique to the DNS provider you are using. 45 | 4. Copy the Authorization Tokens from your provider 46 | 5. Open the `docker-compose.dns.yml` file in your favorite editor and review the `traefik` section 47 | 6. Edit the `Environment` section under the `Traefik` service. 48 | 7. Paste the Authorization Tokens from your provider in this section. You may need different and/or additional fields here based on your provider. 49 | 50 | ```yml 51 | environment: 52 | - "DO_AUTH_TOKEN=" 53 | ``` 54 | 55 | 8. In the same `docker-compose.dns.yml` edit the `catapp` section and add your domain here in the `- "traefik.http.routers.catapp.rule=Host(`your_domain_here`)"` label 56 | 9. Open the `traefik.dns.yml` file in your favorite editor and review the `Challenge DNS` section 57 | 10. Edit the `traefik.dns.yml` and edit your `email:` located in the `Challenge DNS` section 58 | 11. Start Traefik and the `catapp` `docker stack deploy -c docker-compose.yml traefik` 59 | 12. Open the Traefik Dashboard `http://your_domain_here:8080` and verify Traefik is running and `catapp` has TLS enabled. 60 | 13. Open the `catapp` using the domain you filled in at step 6. Remember to use HTTPS now https://your_domain_here.com 61 | 14. You should now see the `catapp` served with HTTPS and a proper Let's Encrypt Certificate 62 | 63 | ## 3.1 Use Wildcard Let's Encrypt Certificate 64 | 65 | Traefik DNS 66 | 67 | 1. Add a new DNS record to your DNS provider. Add `*.` in front of your domain `*.you_domain.com` which enables all sub-domain certificates 68 | 2. Now that the Wildcard is configured for DNS, we can edit the Edit the `docker-compose.dns.yml` `catapp` section and add your domain here in the `- "traefik.http.routers.catapp.rule=Host(`your_domain_here`)"` label. This time we will update the domain to `training.your_domain_here.com` 69 | 3. Open up `https://training.your_domain_here` 70 | 71 | # Continue to the Next Lab Middlewares 72 | 73 | ### Click here to continue -> [Middlewares Lab](https://github.com/56kcloud/traefik-training/blob/master/05-Middlewares/traefik-middlewares.md) 74 | -------------------------------------------------------------------------------- /04-HTTPS-TLS/traefik.dns.yml: -------------------------------------------------------------------------------- 1 | ################################################################ 2 | # API and dashboard configuration 3 | ################################################################ 4 | api: 5 | # Dashboard 6 | # 7 | # 8 | dashboard: true 9 | insecure: true 10 | ################################################################ 11 | # Docker configuration backend 12 | ################################################################ 13 | providers: 14 | docker: 15 | exposedByDefault: false 16 | ################################################################ 17 | # Traefik Logging 18 | ################################################################ 19 | log: 20 | level: INFO 21 | 22 | ################################################################ 23 | # Entrypoint 24 | ################################################################ 25 | entryPoints: 26 | web: 27 | address: ":80" 28 | websecure: 29 | address: ":443" 30 | 31 | ################################################################ 32 | # Challenge DNS 33 | ################################################################ 34 | certificatesResolvers: 35 | myresolver: 36 | acme: 37 | email: your_email@example.com 38 | storage: acme.json 39 | dnsChallenge: 40 | provider: digitalocean 41 | delayBeforeCheck: 0 42 | -------------------------------------------------------------------------------- /04-HTTPS-TLS/traefik.http.yml: -------------------------------------------------------------------------------- 1 | ################################################################ 2 | # API and dashboard configuration 3 | ################################################################ 4 | api: 5 | # Dashboard 6 | # 7 | # 8 | dashboard: true 9 | insecure: true 10 | ################################################################ 11 | # Docker configuration backend 12 | ################################################################ 13 | providers: 14 | docker: 15 | exposedByDefault: false 16 | ################################################################ 17 | # Traefik Logging 18 | ################################################################ 19 | log: 20 | level: INFO 21 | 22 | ################################################################ 23 | # Entrypoint 24 | ################################################################ 25 | entryPoints: 26 | web: 27 | address: ":80" 28 | websecure: 29 | address: ":443" 30 | 31 | ################################################################ 32 | # Challenge HTTP 33 | ################################################################ 34 | certificatesResolvers: 35 | myresolver: 36 | acme: 37 | email: your_email@example.com 38 | storage: acme.json 39 | httpChallenge: 40 | entryPoint: web -------------------------------------------------------------------------------- /04-HTTPS-TLS/traefik.tls.yml: -------------------------------------------------------------------------------- 1 | ################################################################ 2 | # API and dashboard configuration 3 | ################################################################ 4 | api: 5 | # Dashboard 6 | # 7 | # 8 | dashboard: true 9 | insecure: true 10 | ################################################################ 11 | # Docker configuration backend 12 | ################################################################ 13 | providers: 14 | docker: 15 | exposedByDefault: false 16 | ################################################################ 17 | # Traefik Logging 18 | ################################################################ 19 | log: 20 | level: INFO 21 | 22 | ################################################################ 23 | # Entrypoint 24 | ################################################################ 25 | entryPoints: 26 | web: 27 | address: ":80" 28 | websecure: 29 | address: ":443" 30 | 31 | ################################################################ 32 | # Challenge TLS 33 | ################################################################ 34 | certificatesResolvers: 35 | myresolver: 36 | acme: 37 | email: your_email@example.com 38 | storage: acme.json 39 | tlsChallenge: true 40 | # # used during the challenge 41 | # entryPoint: web 42 | -------------------------------------------------------------------------------- /05-Middlewares/docker-compose.auth.yml: -------------------------------------------------------------------------------- 1 | version: '3' 2 | 3 | services: 4 | traefik: 5 | # The latest official supported Traefik docker image 6 | image: traefik:v2.3 7 | # Enables the Traefik Dashboard and tells Traefik to listen to docker 8 | # enable --log.level=INFO so we can see what Traefik is doing in the log files 9 | ports: 10 | # Exposes port 80 for incoming web requests 11 | - "80:80" 12 | - "443:443" 13 | # The Web UI port http://0.0.0.0:8080 (enabled by --api.insecure=true) 14 | - "8080:8080" 15 | volumes: 16 | # So that Traefik can listen to the Docker events 17 | - /var/run/docker.sock:/var/run/docker.sock 18 | # Mounts the Traefik static configuration inside the Traefik container 19 | - ./traefik.yml:/etc/traefik/traefik.yml 20 | 21 | # Add the catapp service 22 | catapp: 23 | image: mikesir87/cats:1.0 24 | labels: 25 | - "traefik.enable=true" 26 | # Routers 27 | - "traefik.http.routers.catapp.rule=Host(`catapp.localhost`)" 28 | - "traefik.http.routers.catapp.service=catapp" 29 | - "traefik.http.routers.catapp.entrypoints=web" 30 | - "traefik.http.routers.catapp.middlewares=test-auth" 31 | # Services 32 | - "traefik.http.services.catapp.loadbalancer.server.port=5000" 33 | # Middleware BasicAuth 34 | - "traefik.http.middlewares.test-auth.basicauth.users=traefik:$$apr1$$.zPbdVg8$$LcHeyCZElH.JfxkxxlMPI.,user2:$$apr1$$XDrP1Fb1$$SZqSEjvNYW44vgJgI3iEP0" 35 | # user1: traefik password: training 36 | # user2: user2 password: test123 37 | # Create hash password -> echo $(htpasswd -nb user2 test123) | sed -e s/\\$/\\$\\$/g -------------------------------------------------------------------------------- /05-Middlewares/docker-compose.compress.yml: -------------------------------------------------------------------------------- 1 | version: '3' 2 | 3 | services: 4 | traefik: 5 | # The latest official supported Traefik docker image 6 | image: traefik:v2.3 7 | # Enables the Traefik Dashboard and tells Traefik to listen to docker 8 | # enable --log.level=INFO so we can see what Traefik is doing in the log files 9 | ports: 10 | # Exposes port 80 for incoming web requests 11 | - "80:80" 12 | - "443:443" 13 | # The Web UI port http://0.0.0.0:8080 (enabled by --api.insecure=true) 14 | - "8080:8080" 15 | volumes: 16 | # So that Traefik can listen to the Docker events 17 | - /var/run/docker.sock:/var/run/docker.sock 18 | # Mounts the Traefik static configuration inside the Traefik container 19 | - ./traefik.yml:/etc/traefik/traefik.yml 20 | 21 | # Add the catapp service 22 | catapp: 23 | image: mikesir87/cats:1.0 24 | labels: 25 | - "traefik.enable=true" 26 | # Routers 27 | - "traefik.http.routers.catapp.rule=Host(`catapp.localhost`)" 28 | - "traefik.http.routers.catapp.service=catapp" 29 | - "traefik.http.routers.catapp.entrypoints=web" 30 | - "traefik.http.routers.catapp.middlewares=test-auth,test-compress" 31 | # Services 32 | - "traefik.http.services.catapp.loadbalancer.server.port=5000" 33 | # Middleware BasicAuth 34 | - "traefik.http.middlewares.test-auth.basicauth.users=traefik:$$apr1$$.zPbdVg8$$LcHeyCZElH.JfxkxxlMPI.,user2:$$apr1$$XDrP1Fb1$$SZqSEjvNYW44vgJgI3iEP0" 35 | # user1: traefik password: training 36 | # user2: user2 password: test123 37 | # Create hash password -> echo $(htpasswd -nb user2 test123) | sed -e s/\\$/\\$\\$/g 38 | # Compress Middleware 39 | - "traefik.http.middlewares.test-compress.compress=true" -------------------------------------------------------------------------------- /05-Middlewares/docker-compose.error.yml: -------------------------------------------------------------------------------- 1 | version: '3' 2 | 3 | services: 4 | traefik: 5 | # The latest official supported Traefik docker image 6 | image: traefik:v2.3 7 | # Enables the Traefik Dashboard and tells Traefik to listen to docker 8 | # enable --log.level=INFO so we can see what Traefik is doing in the log files 9 | ports: 10 | # Exposes port 80 for incoming web requests 11 | - "80:80" 12 | - "443:443" 13 | # The Web UI port http://0.0.0.0:8080 (enabled by --api.insecure=true) 14 | - "8080:8080" 15 | volumes: 16 | # So that Traefik can listen to the Docker events 17 | - /var/run/docker.sock:/var/run/docker.sock 18 | # Mounts the Traefik static configuration inside the Traefik container 19 | - ./traefik.yml:/etc/traefik/traefik.yml 20 | 21 | # Add the catapp service 22 | catapp: 23 | image: mikesir87/cats:1.0 24 | labels: 25 | - "traefik.enable=true" 26 | # Routers 27 | - "traefik.http.routers.catapp.rule=Host(`catapp.localhost`)" 28 | - "traefik.http.routers.catapp.service=catapp" 29 | - "traefik.http.routers.catapp.entrypoints=web" 30 | - "traefik.http.routers.catapp.middlewares=test-auth,test-compress,test-errorpages" 31 | # Services 32 | - "traefik.http.services.catapp.loadbalancer.server.port=5000" 33 | # Middleware BasicAuth 34 | - "traefik.http.middlewares.test-auth.basicauth.users=traefik:$$apr1$$.zPbdVg8$$LcHeyCZElH.JfxkxxlMPI.,user2:$$apr1$$XDrP1Fb1$$SZqSEjvNYW44vgJgI3iEP0" 35 | # user1: traefik password: training 36 | # user2: user2 password: test123 37 | # Create hash password -> echo $(htpasswd -nb user2 test123) | sed -e s/\\$/\\$\\$/g 38 | # Compress Middleware 39 | - "traefik.http.middlewares.test-compress.compress=true" 40 | # Error Pages Middleware 41 | - "traefik.http.middlewares.test-errorpages.errors.status=400-599" 42 | - "traefik.http.middlewares.test-errorpages.errors.service=error" 43 | - "traefik.http.middlewares.test-errorpages.errors.query=/{status}.html" 44 | 45 | # Error Page service 46 | error: 47 | image: guillaumebriday/traefik-custom-error-pages 48 | labels: 49 | - "traefik.enable=true" 50 | - "traefik.http.routers.error.rule=Host(`error.localhost`)" 51 | - "traefik.http.routers.error.service=error" 52 | - "traefik.http.services.error.loadbalancer.server.port=80" 53 | - "traefik.http.routers.error.entrypoints=web" 54 | -------------------------------------------------------------------------------- /05-Middlewares/docker-compose.ratelimit.yml: -------------------------------------------------------------------------------- 1 | version: '3' 2 | 3 | services: 4 | traefik: 5 | # The latest official supported Traefik docker image 6 | image: traefik:v2.3 7 | # Enables the Traefik Dashboard and tells Traefik to listen to docker 8 | # enable --log.level=INFO so we can see what Traefik is doing in the log files 9 | ports: 10 | # Exposes port 80 for incoming web requests 11 | - "80:80" 12 | - "443:443" 13 | # The Web UI port http://0.0.0.0:8080 (enabled by --api.insecure=true) 14 | - "8080:8080" 15 | volumes: 16 | # So that Traefik can listen to the Docker events 17 | - /var/run/docker.sock:/var/run/docker.sock 18 | # Mounts the Traefik static configuration inside the Traefik container 19 | - ./traefik.yml:/etc/traefik/traefik.yml 20 | 21 | # Add the catapp service 22 | catapp: 23 | image: mikesir87/cats:1.0 24 | labels: 25 | - "traefik.enable=true" 26 | # Routers 27 | - "traefik.http.routers.catapp.rule=Host(`catapp.localhost`)" 28 | - "traefik.http.routers.catapp.service=catapp" 29 | - "traefik.http.routers.catapp.entrypoints=web" 30 | - "traefik.http.routers.catapp.middlewares=test-auth,test-compress,test-errorpages,test-ratelimit" 31 | # Services 32 | - "traefik.http.services.catapp.loadbalancer.server.port=5000" 33 | # Middleware BasicAuth 34 | - "traefik.http.middlewares.test-auth.basicauth.users=traefik:$$apr1$$.zPbdVg8$$LcHeyCZElH.JfxkxxlMPI.,user2:$$apr1$$XDrP1Fb1$$SZqSEjvNYW44vgJgI3iEP0" 35 | # user1: traefik password: training 36 | # user2: user2 password: test123 37 | # Create hash password -> echo $(htpasswd -nb user2 test123) | sed -e s/\\$/\\$\\$/g 38 | # Compress Middleware 39 | - "traefik.http.middlewares.test-compress.compress=true" 40 | # Error Pages Middleware 41 | - "traefik.http.middlewares.test-errorpages.errors.status=400-599" 42 | - "traefik.http.middlewares.test-errorpages.errors.service=error" 43 | - "traefik.http.middlewares.test-errorpages.errors.query=/{status}.html" 44 | # Rate Limit Middleware 45 | - "traefik.http.middlewares.test-ratelimit.ratelimit.average=2" 46 | 47 | # Error Page service 48 | error: 49 | image: guillaumebriday/traefik-custom-error-pages 50 | labels: 51 | - "traefik.enable=true" 52 | - "traefik.http.routers.error.rule=Host(`error.localhost`)" 53 | - "traefik.http.routers.error.service=error" 54 | - "traefik.http.services.error.loadbalancer.server.port=80" 55 | # - traefik.frontend.rule=PathPrefixStrip:/wait 56 | - "traefik.http.routers.error.entrypoints=web" -------------------------------------------------------------------------------- /05-Middlewares/docker-compose.redirect.yml: -------------------------------------------------------------------------------- 1 | version: '3' 2 | 3 | services: 4 | traefik: 5 | # The latest official supported Traefik docker image 6 | image: traefik:v2.3 7 | # Enables the Traefik Dashboard and tells Traefik to listen to docker 8 | # enable --log.level=INFO so we can see what Traefik is doing in the log files 9 | ports: 10 | # Exposes port 80 for incoming web requests 11 | - "80:80" 12 | - "443:443" 13 | # The Web UI port http://0.0.0.0:8080 (enabled by --api.insecure=true) 14 | - "8080:8080" 15 | volumes: 16 | # So that Traefik can listen to the Docker events 17 | - /var/run/docker.sock:/var/run/docker.sock 18 | # Copies the Let's Encrypt certificate locally for ease of backing up 19 | - ./letsencrypt:/letsencrypt 20 | # Mounts the Traefik static configuration inside the Traefik container 21 | - ./traefik.dns.yml:/etc/traefik/traefik.yml 22 | environment: 23 | - "DO_AUTH_TOKEN=" 24 | 25 | # Add the catapp service 26 | catapp: 27 | image: mikesir87/cats:1.0 28 | labels: 29 | - "traefik.enable=true" 30 | # Routers 31 | - "traefik.http.routers.catapp.rule=Host(``)" 32 | - "traefik.http.routers.catapp.entrypoints=web" 33 | - "traefik.http.routers.catapp.middlewares=test-redirectscheme" 34 | - "traefik.http.routers.catapp-secure.rule=Host(``)" 35 | - "traefik.http.routers.catapp-secure.entrypoints=websecure" 36 | - "traefik.http.routers.catapp-secure.tls.certresolver=myresolver" 37 | - "traefik.http.routers.catapp-secure.middlewares=test-auth,test-compress,test-errorpages,test-ratelimit" 38 | # Services 39 | - "traefik.http.services.catapp-secure.loadbalancer.server.port=5000" 40 | # Middleware BasicAuth 41 | - "traefik.http.middlewares.test-auth.basicauth.users=traefik:$$apr1$$.zPbdVg8$$LcHeyCZElH.JfxkxxlMPI.,user2:$$apr1$$XDrP1Fb1$$SZqSEjvNYW44vgJgI3iEP0" 42 | # user1: traefik password: training 43 | # user2: user2 password: test123 44 | # Create hash password -> echo $(htpasswd -nb user2 test123) | sed -e s/\\$/\\$\\$/g 45 | # Compress Middleware 46 | - "traefik.http.middlewares.test-compress.compress=true" 47 | # Error Pages Middleware 48 | - "traefik.http.middlewares.test-errorpages.errors.status=400-599" 49 | - "traefik.http.middlewares.test-errorpages.errors.service=error" 50 | - "traefik.http.middlewares.test-errorpages.errors.query=/{status}.html" 51 | # Rate Limit Middleware 52 | - "traefik.http.middlewares.test-ratelimit.ratelimit.average=2" 53 | # Redirect Scheme HTTP -> HTTPS 54 | - "traefik.http.middlewares.test-redirectscheme.redirectscheme.scheme=https" 55 | - "traefik.http.middlewares.test-redirectscheme.redirectscheme.permanent=true" 56 | 57 | # Error Page service 58 | error: 59 | image: guillaumebriday/traefik-custom-error-pages 60 | labels: 61 | - "traefik.enable=true" 62 | - "traefik.http.routers.error.rule=Host(`error.localhost`)" 63 | - "traefik.http.routers.error.service=error" 64 | - "traefik.http.services.error.loadbalancer.server.port=80" 65 | # - traefik.frontend.rule=PathPrefixStrip:/wait 66 | - "traefik.http.routers.error.entrypoints=web" -------------------------------------------------------------------------------- /05-Middlewares/traefik-middlewares.md: -------------------------------------------------------------------------------- 1 | # Traefik Middlewares Lab 2 | 3 | Traefik Logo 4 | 5 | ## 1. Add Basic Authentication to our CatApp 6 | 1. Before we begin, lets cleanup any running Docker stack `docker stack rm traefik` If you named you stack something else use your specified name. If you don't remember run `docker stack ls` 7 | 2. Change to the `05-Middlewares` folder 8 | 3. Generate a new password for our `catapp` by running `echo $(htpasswd -nb traefik training) | sed -e s/\\$/\\$\\$/g` 9 | 4. Every `$` in the password needs to have double `$$` to escape the characters correctly. 10 | 11 | Run the `htpasswd` command 12 | 13 | ```bash 14 | echo $(htpasswd -nb traefik training) | sed -e s/\\$/\\$\\$/g 15 | traefik:$apr1$.zPbdVg8$LcHeyCZElH.JfxkxxlMPI. 16 | 17 | ``` 18 | 19 | 5. Open the `docker-compose.auth.yml` file in your favorite editor and review the `catapp` section 20 | 6. Edit the `docker-compose.auth.yml` `catapp` section and add the Auth Middleware to our `catapp` router `- "traefik.http.middlewares.test-auth.basicauth.users=traefik:$$apr1$$.zPbdVg8$$LcHeyCZElH.JfxkxxlMPI."` 21 | 7. Update the **Router** to point to the new Middleware `- "traefik.http.routers.catapp.middlewares=test-auth"` 22 | 8. Start Traefik and the `catapp` `docker stack deploy -c docker-compose.auth.yml traefik` 23 | 9. Open the Traefik Dashboard [http://0.0.0.0:8080](http://0.0.0.0:8080) and verify the new `test-auth` **Middleware** is running and and assigned to the `catapp` service 24 | 10. Open the `catapp` application in a new browser tab [http://catapp.localhost](http://catapp.localhost) 25 | 11. Enter the user `traefik` and password `training` to visit your `catapp` application 26 | 27 | ## 2. Add Compression Middleware to our CatApp 28 | 1. Before we begin, lets cleanup the HTTP stack `docker stack rm traefik` If you named you stack something else use your specified name. If you don't remember run `docker stack ls` 29 | 2. Change to the `05-HTTPS-and-TLS` folder 30 | 3. Open the `docker-compose.compress.yml` file in your favorite editor and review the `catapp` section 31 | 4. Add the **Compress Middleware** to our `catapp` section `- "traefik.http.middlewares.test-compress.compress=true"` 32 | 5. Update the router to include the **Compress Middleware** ` - "traefik.http.routers.catapp.middlewares=test-auth,test-compress"` 33 | 6. Start Traefik and the `catapp` `docker stack deploy -c docker-compose.compress.yml traefik` 34 | 7. Open the Traefik Dashboard [http://0.0.0.0:8080](http://0.0.0.0:8080) and verify the new `test-compress` **Middleware** is running and and assigned to the `catapp` service 35 | 8. Open the `catapp` application in a new browser tab [http://catapp.localhost](http://catapp.localhost) 36 | 37 | ## 3. Add Error Pages Middleware 38 | 1. Before we begin, lets cleanup the HTTP stack `docker stack rm traefik` If you named you stack something else use your specified name. If you don't remember run `docker stack ls` 39 | 2. Change to the `05-HTTPS-and-TLS` folder 40 | 3. Open the `docker-compose.error.yml` file in your favorite editor and review the `catapp` section 41 | 4. Add the Error Page service below the `catapp`. We are using the [Traefik Custom Error Page service](https://github.com/guillaumebriday/traefik-custom-error-pages) check out the Repo for more details how to modify the Error pages. 42 | 43 | ```yaml 44 | # Error Page service 45 | error: 46 | image: guillaumebriday/traefik-custom-error-pages 47 | labels: 48 | - "traefik.enable=true" 49 | - "traefik.http.routers.error.rule=Host(`error.localhost`)" 50 | - "traefik.http.routers.error.service=error" 51 | - "traefik.http.services.error.loadbalancer.server.port=80" 52 | - "traefik.http.routers.error.entrypoints=web" 53 | ``` 54 | 55 | 4. Add the **Error Page Middleware** to our `catapp` section 56 | 57 | ```yaml 58 | # Error Pages Middleware 59 | - "traefik.http.middlewares.test-errorpages.errors.status=400-599" 60 | - "traefik.http.middlewares.test-errorpages.errors.service=error" 61 | - "traefik.http.middlewares.test-errorpages.errors.query=/{status}.html" 62 | ``` 63 | 64 | 65 | 5. Update the router to include the **Error Page middleware** ` - "traefik.http.routers.catapp.middlewares=test-auth,test-compress,test-errorpages"` 66 | 6. Start Traefik and the `catapp` `docker stack deploy -c docker-compose.error.yml traefik` 67 | 7. Open the Traefik Dashboard [http://0.0.0.0:8080](http://0.0.0.0:8080) and verify the new `test-errorpages` **Middleware** is running and and assigned to the `catapp` service 68 | 8. Open the `catapp` application in a new browser tab [http://catapp.localhost](http://catapp.localhost) 69 | 9. Let's produce a 404 error to see our error page in actions. Open a new browser tab [http://catapp.localhost/broken](http://catapp.localhost/broken) 70 | 71 | ## 4. Add Rate Limit Middleware 72 | 1. Before we begin, lets cleanup the HTTP stack `docker stack rm traefik` If you named you stack something else use your specified name. If you don't remember run `docker stack ls` 73 | 2. Change to the `05-HTTPS-and-TLS` folder 74 | 3. Open the `docker-compose.ratelimit.yml` file in your favorite editor and review the `catapp` section 75 | 4. Add the **Rate Limit Middleware** to our `catapp` section `- "traefik.http.middlewares.test-ratelimit.ratelimit.average=2"` 76 | 5. Update the router to include the **Rate Limit middleware** ` - "traefik.http.routers.catapp.middlewares=test-auth,test-compress,test-ratelimit"` 77 | 6. Start Traefik and the `catapp` `docker stack deploy -c docker-compose.ratelimit.yml traefik` 78 | 7. Open the Traefik Dashboard [http://0.0.0.0:8080](http://0.0.0.0:8080) and verify the new `test-ratelimit` **Middleware** is running and and assigned to the `catapp` service 79 | 8. Open the `catapp` application in a new browser tab [http://catapp.localhost](http://catapp.localhost) 80 | 9. Refresh the `catapp` page quickly to see the Rate Limit error 81 | 82 | ## 5. Add Redirect Middleware 83 | 84 | **This section we need your DNS settings again from Section `04-HTTPS-TLS` We will use the DNS settings to test the HTTP -> HTTPS redirect. Ensure your DNS settings are configured in the `docker-compose.redirect.yml`** 85 | 86 | 1. Before we begin, lets cleanup the HTTP stack `docker stack rm traefik` If you named you stack something else use your specified name. If you don't remember run `docker stack ls` 87 | 2. Change to the `05-HTTPS-and-TLS` folder 88 | 3. Open the `docker-compose.redirect.yml` file in your favorite editor and review the `catapp` section 89 | 4. Next, we need to separate the two entrypoints for HTTP and HTTPS. First, we relable HTTP 90 | 91 | 92 | ```yaml 93 | # Routers 94 | - "traefik.http.routers.catapp.rule=Host(``)" 95 | - "traefik.http.routers.catapp.entrypoints=web" 96 | - "traefik.http.routers.catapp.middlewares=redirect" 97 | ``` 98 | 5. Relabel the entrypoint labels for HTTPS using `catapp-secure` 99 | 100 | ```yaml 101 | - "traefik.http.routers.catapp-secure.rule=Host(``)" 102 | - "traefik.http.routers.catapp-secure.entrypoints=websecure" 103 | - "traefik.http.routers.catapp-secure.tls.certresolver=myresolver" 104 | - "traefik.http.routers.catapp-secure.middlewares=test-auth,test-compress,test-errorpages,test-ratelimit" 105 | ``` 106 | 107 | 6. Add the **Redirect Scheme middleware** to our `catapp` section 108 | 109 | ```yaml 110 | - "traefik.http.middlewares.test-redirectscheme.redirectscheme.scheme=https" 111 | - "traefik.http.middlewares.test-redirectscheme.redirectscheme.permanent=true" 112 | ``` 113 | 114 | 7. Update your domain name in `- "traefik.http.routers.catapp.rule=Host(``)"` and here `- "traefik.http.routers.catapp-secure.rule=Host(``)"` 115 | 8. Add your DNS tokens to the Environment section of Traefik 116 | 9. Start Traefik and the `catapp` `docker stack deploy -c docker-compose.redirect.yml traefik` 117 | 10. Open the Traefik Dashboard [http://0.0.0.0:8080](http://0.0.0.0:8080) and verify the new `test-redirectscheme` **Middleware** is running and and assigned to the `catapp` service 118 | 11. Open the `catapp` application in a new browser tab and open `your-domain` configured in the DNS section 119 | 12. You should see your `catapp` domain redirect from HTTP -> HTTPS automagically. 120 | 121 | # Continue to the Next Observability 122 | 123 | ### Click here to continue -> [Observability Lab](https://github.com/56kcloud/traefik-training/blob/master/06-Observability/traefik-observability.md) 124 | -------------------------------------------------------------------------------- /05-Middlewares/traefik.dns.yml: -------------------------------------------------------------------------------- 1 | ################################################################ 2 | # API and dashboard configuration 3 | ################################################################ 4 | api: 5 | # Dashboard 6 | # 7 | # 8 | dashboard: true 9 | insecure: true 10 | ################################################################ 11 | # Docker configuration backend 12 | ################################################################ 13 | providers: 14 | docker: 15 | exposedByDefault: false 16 | ################################################################ 17 | # Traefik Logging 18 | ################################################################ 19 | log: 20 | level: INFO 21 | 22 | ################################################################ 23 | # Entrypoint 24 | ################################################################ 25 | entryPoints: 26 | web: 27 | address: ":80" 28 | websecure: 29 | address: ":443" 30 | 31 | ############################################################### 32 | # Challenge DNS 33 | ############################################################### 34 | certificatesResolvers: 35 | myresolver: 36 | acme: 37 | email: brian@56k.cloud 38 | storage: acme.json 39 | dnsChallenge: 40 | provider: digitalocean 41 | delayBeforeCheck: 0 42 | -------------------------------------------------------------------------------- /05-Middlewares/traefik.yml: -------------------------------------------------------------------------------- 1 | ################################################################ 2 | # API and dashboard configuration 3 | ################################################################ 4 | api: 5 | # Dashboard 6 | # 7 | # 8 | dashboard: true 9 | insecure: true 10 | ################################################################ 11 | # Docker configuration backend 12 | ################################################################ 13 | providers: 14 | docker: 15 | exposedByDefault: false 16 | ################################################################ 17 | # Traefik Logging 18 | ################################################################ 19 | log: 20 | level: INFO 21 | 22 | ################################################################ 23 | # Entrypoint 24 | ################################################################ 25 | entryPoints: 26 | web: 27 | address: ":80" 28 | websecure: 29 | address: ":443" 30 | 31 | ################################################################ 32 | # Challenge DNS 33 | ################################################################ 34 | # certificatesResolvers: 35 | # myresolver: 36 | # acme: 37 | # email: your_email@example.com 38 | # storage: acme.json 39 | # dnsChallenge: 40 | # provider: digitalocean 41 | # delayBeforeCheck: 0 42 | -------------------------------------------------------------------------------- /06-Observability/docker-compose.access-log.yml: -------------------------------------------------------------------------------- 1 | version: '3' 2 | 3 | services: 4 | traefik: 5 | # The latest official supported Traefik docker image 6 | image: traefik:v2.3 7 | # Enables the Traefik Dashboard and tells Traefik to listen to docker 8 | # enable --log.level=INFO so we can see what Traefik is doing in the log files 9 | ports: 10 | # Exposes port 80 for incoming web requests 11 | - "80:80" 12 | - "443:443" 13 | # The Web UI port http://0.0.0.0:8080 (enabled by --api.insecure=true) 14 | - "8080:8080" 15 | volumes: 16 | # So that Traefik can listen to the Docker events 17 | - /var/run/docker.sock:/var/run/docker.sock 18 | # Mounts the Traefik static configuration inside the Traefik container 19 | - ./traefik.access-log.yml:/etc/traefik/traefik.yml 20 | 21 | # Add the catapp service 22 | catapp: 23 | image: mikesir87/cats:1.0 24 | labels: 25 | - "traefik.enable=true" 26 | # Routers 27 | - "traefik.http.routers.catapp.rule=Host(`catapp.localhost`)" 28 | - "traefik.http.routers.catapp.service=catapp" 29 | - "traefik.http.routers.catapp.entrypoints=web" 30 | - "traefik.http.routers.catapp.middlewares=test-compress,test-errorpages" 31 | # Services 32 | - "traefik.http.services.catapp.loadbalancer.server.port=5000" 33 | # Compress Middleware 34 | - "traefik.http.middlewares.test-compress.compress=true" 35 | # Error Pages Middleware 36 | - "traefik.http.middlewares.test-errorpages.errors.status=400-599" 37 | - "traefik.http.middlewares.test-errorpages.errors.service=error" 38 | - "traefik.http.middlewares.test-errorpages.errors.query=/{status}.html" 39 | 40 | # Error Page service 41 | error: 42 | image: guillaumebriday/traefik-custom-error-pages 43 | labels: 44 | - "traefik.enable=true" 45 | - "traefik.http.routers.error.rule=Host(`error.localhost`)" 46 | - "traefik.http.routers.error.service=error" 47 | - "traefik.http.services.error.loadbalancer.server.port=80" 48 | - "traefik.http.routers.error.entrypoints=web" 49 | -------------------------------------------------------------------------------- /06-Observability/docker-compose.log.yml: -------------------------------------------------------------------------------- 1 | version: '3' 2 | 3 | services: 4 | traefik: 5 | # The latest official supported Traefik docker image 6 | image: traefik:v2.3 7 | # Enables the Traefik Dashboard and tells Traefik to listen to docker 8 | # enable --log.level=INFO so we can see what Traefik is doing in the log files 9 | ports: 10 | # Exposes port 80 for incoming web requests 11 | - "80:80" 12 | - "443:443" 13 | # The Web UI port http://0.0.0.0:8080 (enabled by --api.insecure=true) 14 | - "8080:8080" 15 | volumes: 16 | # So that Traefik can listen to the Docker events 17 | - /var/run/docker.sock:/var/run/docker.sock 18 | # Mounts the Traefik static configuration inside the Traefik container 19 | - ./traefik.yml:/etc/traefik/traefik.yml 20 | 21 | # Add the catapp service 22 | catapp: 23 | image: mikesir87/cats:1.0 24 | labels: 25 | - "traefik.enable=true" 26 | # Routers 27 | - "traefik.http.routers.catapp.rule=Host(`catapp.localhost`)" 28 | - "traefik.http.routers.catapp.service=catapp" 29 | - "traefik.http.routers.catapp.entrypoints=web" 30 | - "traefik.http.routers.catapp.middlewares=test-auth,test-compress,test-errorpages" 31 | # Services 32 | - "traefik.http.services.catapp.loadbalancer.server.port=5000" 33 | # Middleware BasicAuth 34 | - "traefik.http.middlewares.test-auth.basicauth.users=traefik:$$apr1$$.zPbdVg8$$LcHeyCZElH.JfxkxxlMPI.,user2:$$apr1$$XDrP1Fb1$$SZqSEjvNYW44vgJgI3iEP0" 35 | # user1: traefik password: training 36 | # user2: user2 password: test123 37 | # Create hash password -> echo $(htpasswd -nb user2 test123) | sed -e s/\\$/\\$\\$/g 38 | # Compress Middleware 39 | - "traefik.http.middlewares.test-compress.compress=true" 40 | # Error Pages Middleware 41 | - "traefik.http.middlewares.test-errorpages.errors.status=400-599" 42 | - "traefik.http.middlewares.test-errorpages.errors.service=error" 43 | - "traefik.http.middlewares.test-errorpages.errors.query=/{status}.html" 44 | 45 | # Error Page service 46 | error: 47 | image: guillaumebriday/traefik-custom-error-pages 48 | labels: 49 | - "traefik.enable=true" 50 | - "traefik.http.routers.error.rule=Host(`error.localhost`)" 51 | - "traefik.http.routers.error.service=error" 52 | - "traefik.http.services.error.loadbalancer.server.port=80" 53 | - "traefik.http.routers.error.entrypoints=web" 54 | -------------------------------------------------------------------------------- /06-Observability/docker-compose.metrics.yml: -------------------------------------------------------------------------------- 1 | version: '3.7' 2 | 3 | services: 4 | traefik: 5 | # The latest official supported Traefik docker image 6 | image: traefik:v2.3 7 | networks: 8 | - traefik 9 | - inbound 10 | # Enables the Traefik Dashboard and tells Traefik to listen to docker 11 | # enable --log.level=INFO so we can see what Traefik is doing in the log files 12 | ports: 13 | # Exposes port 80 for incoming web requests 14 | - "80:80" 15 | - "443:443" 16 | # The Web UI port http://0.0.0.0:8080 (enabled by --api.insecure=true) 17 | - "8080:8080" 18 | volumes: 19 | # So that Traefik can listen to the Docker events 20 | - /var/run/docker.sock:/var/run/docker.sock 21 | # Mounts the Traefik static configuration inside the Traefik container 22 | - ./traefik.metrics.yml:/etc/traefik/traefik.yml 23 | 24 | prometheus: 25 | image: prom/prometheus:v2.22.1 26 | networks: 27 | - inbound 28 | volumes: 29 | - ./prometheus/:/etc/prometheus/ 30 | - prometheus_data:/prometheus 31 | command: 32 | - '--config.file=/etc/prometheus/prometheus.yml' 33 | - '--storage.tsdb.path=/prometheus' 34 | - '--web.console.libraries=/usr/share/prometheus/console_libraries' 35 | - '--web.console.templates=/usr/share/prometheus/consoles' 36 | deploy: 37 | labels: 38 | - "traefik.http.routers.prometheus.rule=Host(`prometheus.localhost`)" 39 | - "traefik.http.routers.prometheus.service=prometheus" 40 | - "traefik.http.routers.prometheus.entrypoints=web" 41 | - "traefik.http.services.prometheus.loadbalancer.server.port=9090" 42 | - "traefik.docker.network=inbound" 43 | placement: 44 | constraints: 45 | - node.role==manager 46 | restart_policy: 47 | condition: on-failure 48 | 49 | grafana: 50 | image: grafana/grafana:7.3.1 51 | networks: 52 | - inbound 53 | depends_on: 54 | - prometheus 55 | volumes: 56 | - grafana_data:/var/lib/grafana 57 | - ./grafana/provisioning/:/etc/grafana/provisioning/ 58 | env_file: 59 | - ./grafana/config.monitoring 60 | user: "104" 61 | deploy: 62 | labels: 63 | - "traefik.http.routers.grafana.rule=Host(`grafana.localhost`)" 64 | - "traefik.http.routers.grafana.service=grafana" 65 | - "traefik.http.routers.grafana.entrypoints=web" 66 | - "traefik.http.services.grafana.loadbalancer.server.port=3000" 67 | - "traefik.docker.network=inbound" 68 | placement: 69 | constraints: 70 | - node.role == manager 71 | restart_policy: 72 | condition: on-failure 73 | 74 | # Add the catapp service 75 | catapp: 76 | image: mikesir87/cats:1.0 77 | networks: 78 | - inbound 79 | deploy: 80 | labels: 81 | - "traefik.http.routers.catapp.rule=Host(`catapp.localhost`)" 82 | - "traefik.http.routers.catapp.service=catapp" 83 | - "traefik.http.routers.catapp.entrypoints=web" 84 | - "traefik.http.routers.catapp.middlewares=test-compress,test-errorpages" 85 | - "traefik.http.services.catapp.loadbalancer.server.port=5000" 86 | - "traefik.http.middlewares.test-compress.compress=true" 87 | - "traefik.http.middlewares.test-errorpages.errors.status=400-599" 88 | - "traefik.http.middlewares.test-errorpages.errors.service=error" 89 | - "traefik.http.middlewares.test-errorpages.errors.query=/{status}.html" 90 | - "traefik.docker.network=inbound" 91 | 92 | # Error Page service 93 | error: 94 | image: guillaumebriday/traefik-custom-error-pages 95 | networks: 96 | - inbound 97 | deploy: 98 | labels: 99 | - "traefik.enable=true" 100 | - "traefik.http.routers.error.rule=Host(`error.localhost`)" 101 | - "traefik.http.routers.error.service=error" 102 | - "traefik.http.services.error.loadbalancer.server.port=80" 103 | - "traefik.http.routers.error.entrypoints=web" 104 | - "traefik.docker.network=inbound" 105 | 106 | networks: 107 | traefik: 108 | driver: overlay 109 | name: traefik 110 | inbound: 111 | driver: overlay 112 | name: inbound 113 | 114 | volumes: 115 | prometheus_data: {} 116 | grafana_data: {} 117 | -------------------------------------------------------------------------------- /06-Observability/grafana/config.monitoring: -------------------------------------------------------------------------------- 1 | GF_SECURITY_ADMIN_PASSWORD=foobar 2 | GF_USERS_ALLOW_SIGN_UP=false 3 | GF_INSTALL_PLUGINS=grafana-piechart-panel -------------------------------------------------------------------------------- /06-Observability/grafana/provisioning/dashboards/dashboard.yml: -------------------------------------------------------------------------------- 1 | apiVersion: 1 2 | 3 | providers: 4 | # provider name 5 | - name: 'default' 6 | # org id. will default to orgId 1 if not specified 7 | orgId: 1 8 | # name of the dashboard folder. Required 9 | folder: '' 10 | # folder UID. will be automatically generated if not specified 11 | folderUid: '' 12 | # provider type. Required 13 | type: file 14 | # disable dashboard deletion 15 | disableDeletion: false 16 | # enable dashboard editing 17 | editable: true 18 | # how often Grafana will scan for changed dashboards 19 | updateIntervalSeconds: 10 20 | options: 21 | path: /etc/grafana/provisioning/dashboards -------------------------------------------------------------------------------- /06-Observability/grafana/provisioning/dashboards/traefik_rev4.json: -------------------------------------------------------------------------------- 1 | { 2 | "annotations": { 3 | "list": [ 4 | { 5 | "builtIn": 1, 6 | "datasource": "-- Grafana --", 7 | "enable": true, 8 | "hide": true, 9 | "iconColor": "rgba(0, 211, 255, 1)", 10 | "name": "Annotations & Alerts", 11 | "type": "dashboard" 12 | } 13 | ] 14 | }, 15 | "description": "Traefik dashboard prometheus", 16 | "editable": true, 17 | "gnetId": 4475, 18 | "graphTooltip": 0, 19 | "iteration": 1599460963100, 20 | "links": [], 21 | "panels": [ 22 | { 23 | "datasource": null, 24 | "gridPos": { 25 | "h": 1, 26 | "w": 24, 27 | "x": 0, 28 | "y": 0 29 | }, 30 | "id": 10, 31 | "title": "$service stats", 32 | "type": "row" 33 | }, 34 | { 35 | "cacheTimeout": null, 36 | "colorBackground": false, 37 | "colorValue": true, 38 | "colors": [ 39 | "#d44a3a", 40 | "rgba(237, 129, 40, 0.89)", 41 | "#299c46" 42 | ], 43 | "datasource": "Prometheus", 44 | "fieldConfig": { 45 | "defaults": { 46 | "custom": {} 47 | }, 48 | "overrides": [] 49 | }, 50 | "format": "none", 51 | "gauge": { 52 | "maxValue": 100, 53 | "minValue": 0, 54 | "show": false, 55 | "thresholdLabels": false, 56 | "thresholdMarkers": true 57 | }, 58 | "gridPos": { 59 | "h": 7, 60 | "w": 8, 61 | "x": 0, 62 | "y": 1 63 | }, 64 | "id": 1, 65 | "interval": null, 66 | "links": [], 67 | "mappingType": 1, 68 | "mappingTypes": [ 69 | { 70 | "name": "value to text", 71 | "value": 1 72 | }, 73 | { 74 | "name": "range to text", 75 | "value": 2 76 | } 77 | ], 78 | "maxDataPoints": 100, 79 | "nullPointMode": "connected", 80 | "nullText": null, 81 | "postfix": "", 82 | "postfixFontSize": "50%", 83 | "prefix": "", 84 | "prefixFontSize": "50%", 85 | "rangeMaps": [ 86 | { 87 | "from": "null", 88 | "text": "N/A", 89 | "to": "null" 90 | } 91 | ], 92 | "sparkline": { 93 | "fillColor": "rgba(31, 118, 189, 0.18)", 94 | "full": false, 95 | "lineColor": "rgb(31, 120, 193)", 96 | "show": false 97 | }, 98 | "tableColumn": "", 99 | "targets": [ 100 | { 101 | "expr": "count(traefik_service_open_connections)", 102 | "format": "time_series", 103 | "intervalFactor": 2, 104 | "refId": "A" 105 | } 106 | ], 107 | "thresholds": "0,1", 108 | "title": "Number of Traefik Services ", 109 | "type": "singlestat", 110 | "valueFontSize": "80%", 111 | "valueMaps": [ 112 | { 113 | "op": "=", 114 | "text": "OK", 115 | "value": "1" 116 | } 117 | ], 118 | "valueName": "current" 119 | }, 120 | { 121 | "cacheTimeout": null, 122 | "datasource": "Prometheus", 123 | "fieldConfig": { 124 | "defaults": { 125 | "color": { 126 | "mode": "thresholds" 127 | }, 128 | "custom": {}, 129 | "mappings": [ 130 | { 131 | "id": 0, 132 | "op": "=", 133 | "text": "N/A", 134 | "type": 1, 135 | "value": "null" 136 | } 137 | ], 138 | "max": 5, 139 | "min": 0, 140 | "nullValueMode": "connected", 141 | "thresholds": { 142 | "mode": "absolute", 143 | "steps": [ 144 | { 145 | "color": "green", 146 | "value": null 147 | }, 148 | { 149 | "color": "red", 150 | "value": 3 151 | } 152 | ] 153 | }, 154 | "unit": "none" 155 | }, 156 | "overrides": [] 157 | }, 158 | "gridPos": { 159 | "h": 7, 160 | "w": 8, 161 | "x": 8, 162 | "y": 1 163 | }, 164 | "id": 2, 165 | "links": [], 166 | "options": { 167 | "reduceOptions": { 168 | "calcs": [ 169 | "mean" 170 | ], 171 | "fields": "", 172 | "values": false 173 | }, 174 | "showThresholdLabels": false, 175 | "showThresholdMarkers": true 176 | }, 177 | "pluginVersion": "7.1.5", 178 | "targets": [ 179 | { 180 | "expr": "avg(traefik_service_request_duration_seconds_sum{service=\"$service\"})", 181 | "format": "time_series", 182 | "interval": "", 183 | "intervalFactor": 2, 184 | "legendFormat": "{{service}} | {{method}}", 185 | "refId": "A" 186 | } 187 | ], 188 | "timeFrom": null, 189 | "timeShift": null, 190 | "title": "Average response time", 191 | "type": "gauge" 192 | }, 193 | { 194 | "aliasColors": {}, 195 | "breakPoint": "50%", 196 | "cacheTimeout": null, 197 | "combine": { 198 | "label": "Others", 199 | "threshold": 0 200 | }, 201 | "datasource": "Prometheus", 202 | "fieldConfig": { 203 | "defaults": { 204 | "custom": {} 205 | }, 206 | "overrides": [] 207 | }, 208 | "fontSize": "80%", 209 | "format": "short", 210 | "gridPos": { 211 | "h": 7, 212 | "w": 8, 213 | "x": 16, 214 | "y": 1 215 | }, 216 | "id": 4, 217 | "interval": null, 218 | "legend": { 219 | "show": true, 220 | "values": true 221 | }, 222 | "legendType": "Under graph", 223 | "links": [], 224 | "maxDataPoints": 3, 225 | "nullPointMode": "connected", 226 | "pieType": "pie", 227 | "pluginVersion": "6.5.0", 228 | "strokeWidth": 1, 229 | "targets": [ 230 | { 231 | "expr": "avg_over_time(traefik_service_request_duration_seconds_sum{service=\"$service\"}[5m])", 232 | "format": "time_series", 233 | "intervalFactor": 2, 234 | "legendFormat": "{{service}}", 235 | "refId": "A" 236 | } 237 | ], 238 | "title": "Average Service response time", 239 | "type": "grafana-piechart-panel", 240 | "valueName": "current" 241 | }, 242 | { 243 | "cacheTimeout": null, 244 | "datasource": "Prometheus", 245 | "fieldConfig": { 246 | "defaults": { 247 | "color": { 248 | "mode": "thresholds" 249 | }, 250 | "custom": {}, 251 | "mappings": [], 252 | "max": 100, 253 | "min": 0, 254 | "thresholds": { 255 | "mode": "absolute", 256 | "steps": [ 257 | { 258 | "color": "green", 259 | "value": null 260 | } 261 | ] 262 | }, 263 | "unit": "short" 264 | }, 265 | "overrides": [] 266 | }, 267 | "gridPos": { 268 | "h": 7, 269 | "w": 24, 270 | "x": 0, 271 | "y": 8 272 | }, 273 | "id": 3, 274 | "links": [], 275 | "options": { 276 | "displayMode": "basic", 277 | "orientation": "horizontal", 278 | "reduceOptions": { 279 | "calcs": [ 280 | "range" 281 | ], 282 | "fields": "", 283 | "values": false 284 | }, 285 | "showUnfilled": true 286 | }, 287 | "pluginVersion": "7.1.5", 288 | "targets": [ 289 | { 290 | "expr": "avg(traefik_service_requests_total{service=\"$service\"})", 291 | "format": "time_series", 292 | "intervalFactor": 2, 293 | "legendFormat": "{{$service}} | {{method}}", 294 | "refId": "A" 295 | } 296 | ], 297 | "timeFrom": null, 298 | "timeShift": null, 299 | "title": "Total requests over 5min $service", 300 | "type": "bargauge" 301 | }, 302 | { 303 | "collapsed": false, 304 | "datasource": null, 305 | "gridPos": { 306 | "h": 1, 307 | "w": 24, 308 | "x": 0, 309 | "y": 15 310 | }, 311 | "id": 12, 312 | "panels": [], 313 | "title": "Global stats", 314 | "type": "row" 315 | }, 316 | { 317 | "aliasColors": {}, 318 | "bars": true, 319 | "dashLength": 10, 320 | "dashes": false, 321 | "datasource": "Prometheus", 322 | "fieldConfig": { 323 | "defaults": { 324 | "custom": {}, 325 | "links": [] 326 | }, 327 | "overrides": [] 328 | }, 329 | "fill": 1, 330 | "fillGradient": 0, 331 | "gridPos": { 332 | "h": 7, 333 | "w": 12, 334 | "x": 0, 335 | "y": 16 336 | }, 337 | "hiddenSeries": false, 338 | "id": 5, 339 | "legend": { 340 | "alignAsTable": true, 341 | "avg": false, 342 | "current": true, 343 | "max": true, 344 | "min": true, 345 | "rightSide": true, 346 | "show": true, 347 | "total": false, 348 | "values": true 349 | }, 350 | "lines": false, 351 | "linewidth": 1, 352 | "links": [], 353 | "nullPointMode": "null", 354 | "percentage": false, 355 | "pluginVersion": "7.1.5", 356 | "pointradius": 5, 357 | "points": false, 358 | "renderer": "flot", 359 | "seriesOverrides": [], 360 | "spaceLength": 10, 361 | "stack": true, 362 | "steppedLine": false, 363 | "targets": [ 364 | { 365 | "expr": "rate(traefik_entrypoint_requests_total{entrypoint=~\"$entrypoint\",code=\"200\"}[5m])", 366 | "format": "time_series", 367 | "intervalFactor": 2, 368 | "legendFormat": "{{method}} : {{code}}", 369 | "refId": "A" 370 | } 371 | ], 372 | "thresholds": [], 373 | "timeFrom": null, 374 | "timeRegions": [], 375 | "timeShift": null, 376 | "title": "Status code 200 over 5min", 377 | "tooltip": { 378 | "shared": true, 379 | "sort": 0, 380 | "value_type": "individual" 381 | }, 382 | "type": "graph", 383 | "xaxis": { 384 | "buckets": null, 385 | "mode": "time", 386 | "name": null, 387 | "show": true, 388 | "values": [] 389 | }, 390 | "yaxes": [ 391 | { 392 | "decimals": null, 393 | "format": "short", 394 | "label": null, 395 | "logBase": 1, 396 | "max": null, 397 | "min": null, 398 | "show": true 399 | }, 400 | { 401 | "decimals": null, 402 | "format": "short", 403 | "label": "", 404 | "logBase": 1, 405 | "max": null, 406 | "min": null, 407 | "show": true 408 | } 409 | ], 410 | "yaxis": { 411 | "align": false, 412 | "alignLevel": null 413 | } 414 | }, 415 | { 416 | "aliasColors": {}, 417 | "breakPoint": "50%", 418 | "cacheTimeout": null, 419 | "combine": { 420 | "label": "Others", 421 | "threshold": 0 422 | }, 423 | "datasource": "Prometheus", 424 | "fieldConfig": { 425 | "defaults": { 426 | "color": { 427 | "mode": "thresholds" 428 | }, 429 | "custom": {}, 430 | "decimals": 0, 431 | "mappings": [], 432 | "max": 100, 433 | "min": 0, 434 | "thresholds": { 435 | "mode": "absolute", 436 | "steps": [ 437 | { 438 | "color": "green", 439 | "value": null 440 | } 441 | ] 442 | }, 443 | "unit": "short" 444 | }, 445 | "overrides": [] 446 | }, 447 | "fontSize": "80%", 448 | "format": "short", 449 | "gridPos": { 450 | "h": 7, 451 | "w": 12, 452 | "x": 12, 453 | "y": 16 454 | }, 455 | "id": 6, 456 | "interval": null, 457 | "legend": { 458 | "show": true, 459 | "values": true 460 | }, 461 | "legendType": "Under graph", 462 | "links": [], 463 | "nullPointMode": "connected", 464 | "pieType": "pie", 465 | "pluginVersion": "7.1.5", 466 | "strokeWidth": 1, 467 | "targets": [ 468 | { 469 | "expr": "rate(traefik_entrypoint_requests_total{entrypoint=\"web\",code!=\"200\"}[5m]) * 100", 470 | "format": "time_series", 471 | "instant": false, 472 | "interval": "", 473 | "intervalFactor": 2, 474 | "legendFormat": "{{ method }} : {{code}}", 475 | "refId": "A" 476 | }, 477 | { 478 | "expr": "avg_over_time", 479 | "refId": "B" 480 | } 481 | ], 482 | "timeFrom": null, 483 | "timeShift": null, 484 | "title": "Entrypoint Error Codes", 485 | "type": "grafana-piechart-panel", 486 | "valueName": "current" 487 | }, 488 | { 489 | "aliasColors": {}, 490 | "breakPoint": "50%", 491 | "cacheTimeout": null, 492 | "combine": { 493 | "label": "Others", 494 | "threshold": 0 495 | }, 496 | "datasource": "Prometheus", 497 | "fieldConfig": { 498 | "defaults": { 499 | "custom": {} 500 | }, 501 | "overrides": [] 502 | }, 503 | "fontSize": "80%", 504 | "format": "short", 505 | "gridPos": { 506 | "h": 7, 507 | "w": 12, 508 | "x": 0, 509 | "y": 23 510 | }, 511 | "id": 7, 512 | "interval": null, 513 | "legend": { 514 | "show": true, 515 | "values": true 516 | }, 517 | "legendType": "Right side", 518 | "links": [], 519 | "maxDataPoints": 3, 520 | "nullPointMode": "connected", 521 | "pieType": "pie", 522 | "strokeWidth": 1, 523 | "targets": [ 524 | { 525 | "expr": "sum(rate(traefik_service_requests_total[5m])* 100) by (service) ", 526 | "format": "time_series", 527 | "interval": "", 528 | "intervalFactor": 2, 529 | "legendFormat": "{{ service }}", 530 | "refId": "A" 531 | } 532 | ], 533 | "title": "Requests by service", 534 | "type": "grafana-piechart-panel", 535 | "valueName": "total" 536 | }, 537 | { 538 | "aliasColors": {}, 539 | "breakPoint": "50%", 540 | "cacheTimeout": null, 541 | "combine": { 542 | "label": "Others", 543 | "threshold": 0 544 | }, 545 | "datasource": "Prometheus", 546 | "fieldConfig": { 547 | "defaults": { 548 | "custom": {} 549 | }, 550 | "overrides": [] 551 | }, 552 | "fontSize": "80%", 553 | "format": "short", 554 | "gridPos": { 555 | "h": 7, 556 | "w": 12, 557 | "x": 12, 558 | "y": 23 559 | }, 560 | "id": 8, 561 | "interval": null, 562 | "legend": { 563 | "show": true, 564 | "values": true 565 | }, 566 | "legendType": "Right side", 567 | "links": [], 568 | "maxDataPoints": 3, 569 | "nullPointMode": "connected", 570 | "pieType": "pie", 571 | "strokeWidth": 1, 572 | "targets": [ 573 | { 574 | "expr": "sum(rate(traefik_entrypoint_requests_total{entrypoint =~ \"$entrypoint\"}[5m]) * 100) by (entrypoint) ", 575 | "format": "time_series", 576 | "instant": false, 577 | "interval": "", 578 | "intervalFactor": 1, 579 | "legendFormat": "{{ entrypoint }}", 580 | "refId": "A" 581 | } 582 | ], 583 | "title": "Requests by protocol", 584 | "type": "grafana-piechart-panel", 585 | "valueName": "total" 586 | } 587 | ], 588 | "schemaVersion": 26, 589 | "style": "dark", 590 | "tags": [ 591 | "traefik", 592 | "prometheus" 593 | ], 594 | "templating": { 595 | "list": [ 596 | { 597 | "allValue": null, 598 | "current": { 599 | "selected": true, 600 | "text": "catapp@docker", 601 | "value": "catapp@docker" 602 | }, 603 | "datasource": "Prometheus", 604 | "definition": "label_values(service)", 605 | "hide": 0, 606 | "includeAll": true, 607 | "label": null, 608 | "multi": false, 609 | "name": "service", 610 | "options": [], 611 | "query": "label_values(service)", 612 | "refresh": 1, 613 | "regex": "", 614 | "skipUrlSync": false, 615 | "sort": 0, 616 | "tagValuesQuery": "", 617 | "tags": [], 618 | "tagsQuery": "", 619 | "type": "query", 620 | "useTags": false 621 | }, 622 | { 623 | "allValue": null, 624 | "current": { 625 | "selected": true, 626 | "tags": [], 627 | "text": [ 628 | "traefik", 629 | "web" 630 | ], 631 | "value": [ 632 | "traefik", 633 | "web" 634 | ] 635 | }, 636 | "datasource": "Prometheus", 637 | "definition": "label_values(entrypoint)", 638 | "hide": 0, 639 | "includeAll": true, 640 | "label": null, 641 | "multi": true, 642 | "name": "entrypoint", 643 | "options": [], 644 | "query": "label_values(entrypoint)", 645 | "refresh": 1, 646 | "regex": "", 647 | "skipUrlSync": false, 648 | "sort": 0, 649 | "tagValuesQuery": "", 650 | "tags": [], 651 | "tagsQuery": "", 652 | "type": "query", 653 | "useTags": false 654 | }, 655 | { 656 | "allValue": null, 657 | "current": { 658 | "text": "200", 659 | "value": "200" 660 | }, 661 | "datasource": "Prometheus", 662 | "definition": "label_values(code)", 663 | "hide": 2, 664 | "includeAll": false, 665 | "label": null, 666 | "multi": false, 667 | "name": "code", 668 | "options": [ 669 | { 670 | "selected": true, 671 | "text": "200", 672 | "value": "200" 673 | }, 674 | { 675 | "selected": false, 676 | "text": "302", 677 | "value": "302" 678 | }, 679 | { 680 | "selected": false, 681 | "text": "304", 682 | "value": "304" 683 | }, 684 | { 685 | "selected": false, 686 | "text": "400", 687 | "value": "400" 688 | }, 689 | { 690 | "selected": false, 691 | "text": "404", 692 | "value": "404" 693 | }, 694 | { 695 | "selected": false, 696 | "text": "429", 697 | "value": "429" 698 | }, 699 | { 700 | "selected": false, 701 | "text": "499", 702 | "value": "499" 703 | }, 704 | { 705 | "selected": false, 706 | "text": "500", 707 | "value": "500" 708 | }, 709 | { 710 | "selected": false, 711 | "text": "503", 712 | "value": "503" 713 | } 714 | ], 715 | "query": "label_values(code)", 716 | "refresh": 0, 717 | "regex": "", 718 | "skipUrlSync": false, 719 | "sort": 0, 720 | "tagValuesQuery": "", 721 | "tags": [], 722 | "tagsQuery": "", 723 | "type": "query", 724 | "useTags": false 725 | } 726 | ] 727 | }, 728 | "time": { 729 | "from": "now-5m", 730 | "to": "now" 731 | }, 732 | "timepicker": { 733 | "refresh_intervals": [ 734 | "5s", 735 | "10s", 736 | "30s", 737 | "1m", 738 | "5m", 739 | "15m", 740 | "30m", 741 | "1h", 742 | "2h", 743 | "1d" 744 | ], 745 | "time_options": [ 746 | "5m", 747 | "15m", 748 | "1h", 749 | "6h", 750 | "12h", 751 | "24h", 752 | "2d", 753 | "7d", 754 | "30d" 755 | ] 756 | }, 757 | "timezone": "", 758 | "title": "Traefik2", 759 | "uid": "qPdAviJmz1", 760 | "version": 1 761 | } -------------------------------------------------------------------------------- /06-Observability/grafana/provisioning/datasources/datasource.yml: -------------------------------------------------------------------------------- 1 | # config file version 2 | apiVersion: 1 3 | 4 | # list of datasources that should be deleted from the database 5 | deleteDatasources: 6 | - name: Prometheus 7 | orgId: 1 8 | 9 | # list of datasources to insert/update depending 10 | # whats available in the database 11 | datasources: 12 | # name of the datasource. Required 13 | - name: Prometheus 14 | # datasource type. Required 15 | type: prometheus 16 | # access mode. direct or proxy. Required 17 | access: direct 18 | # org id. will default to orgId 1 if not specified 19 | orgId: 1 20 | # url 21 | url: http://prometheus.localhost 22 | # database password, if used 23 | password: 24 | # database user, if used 25 | user: 26 | # database name, if used 27 | database: 28 | # enable/disable basic auth 29 | basicAuth: false 30 | # basic auth username 31 | basicAuthUser: admin 32 | # basic auth password 33 | basicAuthPassword: foobar 34 | # enable/disable with credentials headers 35 | withCredentials: 36 | # mark as default datasource. Max one per org 37 | isDefault: true 38 | # fields that will be converted to json and stored in json_data 39 | jsonData: 40 | graphiteVersion: "1.1" 41 | tlsAuth: false 42 | tlsAuthWithCACert: false 43 | # json object of data that will be encrypted. 44 | secureJsonData: 45 | tlsCACert: "..." 46 | tlsClientCert: "..." 47 | tlsClientKey: "..." 48 | version: 1 49 | # allow users to edit datasources from the UI. 50 | editable: true 51 | -------------------------------------------------------------------------------- /06-Observability/prometheus/alert.rules: -------------------------------------------------------------------------------- 1 | groups: 2 | - name: example 3 | rules: 4 | 5 | # Alert for any instance that is unreachable for >2 minutes. 6 | - alert: service_down 7 | expr: up == 0 8 | for: 2m 9 | labels: 10 | severity: page 11 | annotations: 12 | summary: "Instance {{ $labels.instance }} down" 13 | description: "{{ $labels.instance }} of job {{ $labels.job }} has been down for more than 2 minutes." 14 | 15 | - alert: high_load 16 | expr: node_load1 > 0.5 17 | for: 2m 18 | labels: 19 | severity: page 20 | annotations: 21 | summary: "Instance {{ $labels.instance }} under high load" 22 | description: "{{ $labels.instance }} of job {{ $labels.job }} is under high load." -------------------------------------------------------------------------------- /06-Observability/prometheus/prometheus.yml: -------------------------------------------------------------------------------- 1 | # my global config 2 | global: 3 | scrape_interval: 15s # By default, scrape targets every 15 seconds. 4 | evaluation_interval: 15s # By default, scrape targets every 15 seconds. 5 | # scrape_timeout is set to the global default (10s). 6 | 7 | # Attach these labels to any time series or alerts when communicating with 8 | # external systems (federation, remote storage, Alertmanager). 9 | external_labels: 10 | monitor: 'my-project' 11 | 12 | # Load and evaluate rules in this file every 'evaluation_interval' seconds. 13 | rule_files: 14 | - 'alert.rules' 15 | # - "first.rules" 16 | # - "second.rules" 17 | 18 | # alert 19 | # alerting: 20 | # alertmanagers: 21 | # - scheme: http 22 | # static_configs: 23 | # - targets: 24 | # - "alertmanager:9093" 25 | 26 | # A scrape configuration containing exactly one endpoint to scrape: 27 | # Here it's Prometheus itself. 28 | scrape_configs: 29 | # The job name is added as a label `job=` to any timeseries scraped from this config. 30 | 31 | - job_name: 'prometheus' 32 | 33 | # Override the global default and scrape targets from this job every 5 seconds. 34 | scrape_interval: 5s 35 | 36 | static_configs: 37 | - targets: ['localhost:9090'] 38 | 39 | 40 | - job_name: 'traefik' 41 | 42 | # Override the global default and scrape targets from this job every 5 seconds. 43 | scrape_interval: 5s 44 | 45 | dns_sd_configs: 46 | - names: 47 | - 'tasks.traefik' 48 | type: 'A' 49 | port: 8080 -------------------------------------------------------------------------------- /06-Observability/traefik-observability.md: -------------------------------------------------------------------------------- 1 | # Traefik Observability Lab 2 | 3 | Traefik Logo 4 | 5 | ## 1. Enable Debug logging for Traefik 6 | 1. Before we begin, lets cleanup any running Docker stack `docker stack rm traefik` If you named you stack something else use your specified name. If you don't remember run `docker stack ls` 7 | 2. Change to the `06-Observability` folder 8 | 3. Open the `traefik.yml` file in your favorite editor and review the `Traefik Logging` section 9 | 4. Change the Log level from `INFO` to `DEBUG` 10 | 11 | ```yml 12 | log: 13 | level: DEBUG 14 | ``` 15 | 16 | 5. Start Traefik and the `catapp` `docker stack deploy -c docker-compose.log.yml traefik` 17 | 6. View the Debug logs `docker service logs traefik_traefik` 18 | 7. Once we are done with Debug switch Traefik back to default logging. Open `traefik.yml` and change the Log level from `DEBUG` to `INFO` 19 | 20 | ```yml 21 | log: 22 | level: INFO 23 | ``` 24 | 25 | 8. Remove Traefik `docker stack rm traefik` 26 | 9. Redeploy Traefik with the updated Log Level `docker stack deploy -c docker-compose.log.yml traefik` 27 | 10. View the `ERROR` Log level for Traefik `docker service logs traefik_traefik` 28 | 29 | 30 | ## 2. Enable Access Logs 31 | 1. Before we begin, lets cleanup the HTTP stack `docker stack rm traefik` If you named you stack something else use your specified name. If you don't remember run `docker stack ls` 32 | 2. Change to the `06-Observability` folder 33 | 3. Open the `traefik.access-log.yml` file in your favorite editor and review the `Access Logging` section 34 | 4. Uncomment the `accessLog` line to enable Access Logging 35 | 36 | ```yml 37 | # enable Access logs 38 | accessLog: {} 39 | ``` 40 | 41 | 5. Start Traefik with `Access Log` enabled `docker stack deploy -c docker-compose.access-log.yml traefik` 42 | 6. Open [http://catapp.localhost](http://catapp.localhost) and refresh the page a couple times 43 | 7. View the `Access Log` using `docker service logs traefik_traefik` see the example below of a `200` status message 44 | 45 | 46 | ```apache 47 | traefik_traefik.1.zaxcbu7aplii@docker-desktop | 10.0.0.2 - traefik [04/Sep/2020:07:52:41 +0000] "GET / HTTP/1.1" 200 760 "-" "-" 1 "catapp@docker" "http://10.0.8.6:5000" 14ms 48 | ``` 49 | 50 | 8. Let's enable filtering to see just `404` status messages. Edit the `Access Log` filter configuration in `traefik.access-log.yml`and comment the `Access Log` and uncomment the filtering section 51 | 52 | ```yml 53 | # accessLog: {} 54 | #Configuring Multiple Filters 55 | accessLog: 56 | filters: 57 | statusCodes: 58 | - "404" 59 | retryAttempts: true 60 | minDuration: "10ms" 61 | ``` 62 | 63 | 8. Remove Traefik `docker stack rm traefik` 64 | 9. Redeploy Traefik with the updated `Access Log` filter `docker stack deploy -c docker-compose.access-log.yml traefik` 65 | 10. Open [http://catapp.localhost](http://catapp.localhost) and refresh the page a couple times 66 | 11. View the `Access Log` using `docker service logs traefik_traefik` see the example below of a `200` status message 67 | 12. Create a `404` error by opening a missing path [http://catapp.localhost/missing](http://catapp.localhost/missing) 68 | 13. View the `Access Log` using `docker service logs traefik_traefik` and we should only see a `404` status message 69 | 70 | 71 | ## 3. Enable Traefik Metrics 72 | 1. Before we begin, lets cleanup the HTTP stack `docker stack rm traefik` If you named you stack something else use your specified name. If you don't remember run `docker stack ls` 73 | 2. Change to the `06-Observability` folder 74 | 3. Open the `traefik.metrics.yml` file in your favorite editor and review the `Prometheus Metrics` section. The buckets Prometheus metrics buckets have been enabled for the different time series in seconds. 75 | 76 | ```yml 77 | metrics: 78 | prometheus: 79 | buckets: 80 | - 0.1 81 | - 0.3 82 | - 1.2 83 | - 5.0 84 | ``` 85 | 4. Start Traefik with `Metrics` enabled `docker stack deploy -c docker-compose.metrics.yml traefik` 86 | 87 | **NOTE: This will take a couple minutes as Prometheus and Grafana need to download and start** 88 | 89 | 5. Login to Promethes [prometheus.localhost](http://prometheus.localhost) 90 | 6. Review the available metrics imported into Prometheus by opening Graph and then click the dropdown and scroll to the bottom to find Traefik metrics 91 | 7. Login to Grafana [grafana.localhost](http://grafana.localhost) 92 | 8. Grafana user is `admin` and password is `foobar` 93 | 9. Open the Dashboard `Traefik2` 94 | 10. Visualize the Stats from Traefik 95 | 96 | # Continue to the Next Operations 97 | 98 | ### Click here to continue -> [Operations Lab](https://github.com/56kcloud/traefik-training/blob/master/07-Operations/traefik-operations.md) 99 | -------------------------------------------------------------------------------- /06-Observability/traefik.access-log.yml: -------------------------------------------------------------------------------- 1 | ################################################################ 2 | # API and dashboard configuration 3 | ################################################################ 4 | api: 5 | # Dashboard 6 | # 7 | # 8 | dashboard: true 9 | insecure: true 10 | ################################################################ 11 | # Docker configuration backend 12 | ################################################################ 13 | providers: 14 | docker: 15 | exposedByDefault: false 16 | 17 | ################################################################ 18 | # Access Logging 19 | ################################################################ 20 | # enable Access logs 21 | accessLog: {} 22 | #Configuring Multiple Filters 23 | # accessLog: 24 | # filters: 25 | # statusCodes: 26 | # - "404" 27 | # retryAttempts: true 28 | # minDuration: "10ms" 29 | 30 | ################################################################ 31 | # Traefik Logging - DEBUG, PANIC, FATAL, ERROR, WARN, and INFO (DEFAULT is ERROR) 32 | ################################################################ 33 | log: 34 | level: INFO 35 | 36 | ################################################################ 37 | # Entrypoint 38 | ################################################################ 39 | entryPoints: 40 | web: 41 | address: ":80" 42 | websecure: 43 | address: ":443" 44 | 45 | ################################################################ 46 | # Challenge DNS 47 | ################################################################ 48 | # certificatesResolvers: 49 | # myresolver: 50 | # acme: 51 | # email: your_email@example.com 52 | # storage: acme.json 53 | # dnsChallenge: 54 | # provider: digitalocean 55 | # delayBeforeCheck: 0 56 | -------------------------------------------------------------------------------- /06-Observability/traefik.metrics.yml: -------------------------------------------------------------------------------- 1 | ################################################################ 2 | # API and dashboard configuration 3 | ################################################################ 4 | api: 5 | # Dashboard 6 | # 7 | # 8 | dashboard: true 9 | insecure: true 10 | ################################################################ 11 | # Docker configuration backend 12 | ################################################################ 13 | providers: 14 | docker: 15 | swarmMode: true 16 | 17 | ################################################################ 18 | # Access Logging 19 | ################################################################ 20 | # enable Access logs 21 | accessLog: {} 22 | #Configuring Multiple Filters 23 | # accessLog: 24 | # filters: 25 | # statusCodes: 26 | # - "404" 27 | # retryAttempts: true 28 | # minDuration: "10ms" 29 | 30 | ################################################################ 31 | # Traefik Logging - DEBUG, PANIC, FATAL, ERROR, WARN, and INFO (DEFAULT is ERROR) 32 | ################################################################ 33 | log: 34 | level: INFO 35 | 36 | ################################################################ 37 | # Prometheus Metrics 38 | ################################################################ 39 | metrics: 40 | prometheus: 41 | buckets: 42 | - 0.1 43 | - 0.3 44 | - 1.2 45 | - 5.0 46 | 47 | ################################################################ 48 | # Entrypoint 49 | ################################################################ 50 | entryPoints: 51 | web: 52 | address: ":80" 53 | websecure: 54 | address: ":443" 55 | 56 | ################################################################ 57 | # Challenge DNS 58 | ################################################################ 59 | # certificatesResolvers: 60 | # myresolver: 61 | # acme: 62 | # email: your_email@example.com 63 | # storage: acme.json 64 | # dnsChallenge: 65 | # provider: digitalocean 66 | # delayBeforeCheck: 0 67 | -------------------------------------------------------------------------------- /06-Observability/traefik.yml: -------------------------------------------------------------------------------- 1 | ################################################################ 2 | # API and dashboard configuration 3 | ################################################################ 4 | api: 5 | # Dashboard 6 | # 7 | # 8 | dashboard: true 9 | insecure: true 10 | ################################################################ 11 | # Docker configuration backend 12 | ################################################################ 13 | providers: 14 | docker: 15 | exposedByDefault: false 16 | 17 | ################################################################ 18 | # Traefik Logging - DEBUG, PANIC, FATAL, ERROR, WARN, and INFO (DEFAULT is ERROR) 19 | ################################################################ 20 | log: 21 | level: ERROR 22 | 23 | ################################################################ 24 | # Entrypoint 25 | ################################################################ 26 | entryPoints: 27 | web: 28 | address: ":80" 29 | websecure: 30 | address: ":443" 31 | 32 | ################################################################ 33 | # Challenge DNS 34 | ################################################################ 35 | # certificatesResolvers: 36 | # myresolver: 37 | # acme: 38 | # email: your_email@example.com 39 | # storage: acme.json 40 | # dnsChallenge: 41 | # provider: digitalocean 42 | # delayBeforeCheck: 0 43 | -------------------------------------------------------------------------------- /07-Operations/docker-compose.cli.yml: -------------------------------------------------------------------------------- 1 | version: '3.7' 2 | 3 | services: 4 | traefik: 5 | # The latest official supported Traefik docker image 6 | image: traefik:v2.3 7 | # Enables the Traefik Dashboard and tells Traefik to listen to docker 8 | # enable --log.level=INFO so we can see what Traefik is doing in the log files 9 | ports: 10 | # Exposes port 80 for incoming web requests 11 | - "80:80" 12 | - "443:443" 13 | # The Web UI port http://0.0.0.0:8080 (enabled by --api.insecure=true) 14 | - "8080:8080" 15 | volumes: 16 | # So that Traefik can listen to the Docker events 17 | - /var/run/docker.sock:/var/run/docker.sock 18 | # Mounts the Traefik static configuration inside the Traefik container 19 | - ./traefik.yml:/etc/traefik/traefik.yml 20 | - ../04-HTTPS-TLS/letsencrypt:/letsencrypt 21 | healthcheck: 22 | test: ["CMD", "traefik", "healthcheck"] 23 | interval: 10s 24 | timeout: 2s 25 | retries: 3 26 | start_period: 5s 27 | environment: 28 | - "DO_AUTH_TOKEN=" 29 | deploy: 30 | labels: 31 | - "traefik.enable=true" 32 | - "traefik.http.routers.dashboard.rule=Host(``) && (PathPrefix(`/api`) || PathPrefix(`/dashboard`))" 33 | - "traefik.http.routers.dashboard.service=api@internal" 34 | - "traefik.http.routers.dashboard.entrypoints=websecure" 35 | - traefik.http.routers.dashboard.tls=true 36 | - traefik.http.routers.dashboard.tls.certresolver=myresolver 37 | - "traefik.http.routers.dashboard.middlewares=auth" 38 | - "traefik.http.middlewares.auth.basicauth.users=traefik:$$apr1$$cIc2751d$$HejlZ4u/fLP1JrVO6sJO1/" 39 | - "traefik.http.services.dashboard.loadbalancer.server.port=8080" 40 | 41 | 42 | # Add the catapp service 43 | catapp: 44 | image: mikesir87/cats:1.0 45 | labels: 46 | - "traefik.enable=true" 47 | # Routers 48 | - "traefik.http.routers.catapp.rule=Host(`catapp.localhost`)" 49 | - "traefik.http.routers.catapp.service=catapp" 50 | - "traefik.http.routers.catapp.entrypoints=web" 51 | - "traefik.http.routers.catapp.middlewares=test-compress,test-errorpages" 52 | # Services 53 | - "traefik.http.services.catapp.loadbalancer.server.port=5000" 54 | # Compress Middleware 55 | - "traefik.http.middlewares.test-compress.compress=true" 56 | # Error Pages Middleware 57 | - "traefik.http.middlewares.test-errorpages.errors.status=400-599" 58 | - "traefik.http.middlewares.test-errorpages.errors.service=error" 59 | - "traefik.http.middlewares.test-errorpages.errors.query=/{status}.html" 60 | 61 | # Error Page service 62 | error: 63 | image: guillaumebriday/traefik-custom-error-pages 64 | labels: 65 | - "traefik.enable=true" 66 | - "traefik.http.routers.error.rule=Host(`error.localhost`)" 67 | - "traefik.http.routers.error.service=error" 68 | - "traefik.http.services.error.loadbalancer.server.port=80" 69 | - "traefik.http.routers.error.entrypoints=web" 70 | -------------------------------------------------------------------------------- /07-Operations/traefik-operations.md: -------------------------------------------------------------------------------- 1 | # Traefik Operations Lab 2 | 3 | Traefik Logo 4 | 5 | ## 1. Enable Healthcheck with CLI & Ping, Docker HEALTHCHECK, and Secure Dashboard/API 6 | 1. Before we begin, lets cleanup any running Docker stack `docker stack rm traefik` If you named you stack something else use your specified name. If you don't remember run `docker stack ls` 7 | 2. Change to the `07-Operations` folder 8 | 3. Open the `traefik.yml` file in your favorite editor and review the `Traefik API, Dashboard & Ping sections` section 9 | 4. In the API section Change `insecure` from `true` to `false` which is default 10 | 11 | ```yml 12 | api: 13 | # Dashboard 14 | # true = default 15 | # 16 | dashboard: true 17 | # 18 | # insecure: false is default 19 | # 20 | insecure: false 21 | ``` 22 | 23 | 5. Review the docker `HEALTHCHECK` in `docker-compose.cli.yml` 24 | 25 | ```yml 26 | healthcheck: 27 | test: ["CMD", "traefik", "healthcheck"] 28 | interval: 10s 29 | timeout: 2s 30 | retries: 3 31 | start_period: 5s 32 | ``` 33 | 34 | 6. Start Traefik with Ping endpoint, Secure Mode ,and Docker `HEALTHCHECK ` -> `docker stack deploy -c docker-compose.cli.yml traefik` 35 | 7. Run `docker ps` notice the traefik container status now has Health status 36 | 8. Open the Ping endpoint [http://your_domain_here/ping](http://traefik.localhost/ping) 37 | 9. Make an API request [http://your_domain_here:8080/api/http/routers](http://traefik.localhost:8080/api/http/routers) 38 | 10. Open the Dashboard. Ensure to have the trailing "/" [http://your_domain_here/dashboard/](http://traefik.localhost/dashboard/) 39 | 11. The full list of API requests can be found here [https://docs.traefik.io/operations/api/](https://docs.traefik.io/operations/api/) 40 | 41 | 42 | # Continue to the Next to Advance Tips 43 | 44 | ### Click here to continue -> [Advanced Tips](https://github.com/56kcloud/traefik-training/blob/master/08-Advanced-Tips/traefik-advanced-tips.md) 45 | -------------------------------------------------------------------------------- /07-Operations/traefik.yml: -------------------------------------------------------------------------------- 1 | ################################################################ 2 | # API and dashboard configuration 3 | ################################################################ 4 | api: 5 | # Dashboard 6 | # true = default 7 | # 8 | dashboard: true 9 | # 10 | # insecure: false is default 11 | # 12 | insecure: true 13 | 14 | ################################################################ 15 | # Enable Healthcheck 16 | ################################################################ 17 | ping: {} 18 | 19 | ################################################################ 20 | # Docker configuration backend 21 | ################################################################ 22 | providers: 23 | docker: 24 | exposedByDefault: false 25 | swarmMode: true 26 | 27 | ################################################################ 28 | # Traefik Logging - DEBUG, PANIC, FATAL, ERROR, WARN, and INFO (DEFAULT is ERROR) 29 | ################################################################ 30 | log: 31 | level: ERROR 32 | 33 | ################################################################ 34 | # Entrypoint 35 | ################################################################ 36 | entryPoints: 37 | web: 38 | address: ":80" 39 | websecure: 40 | address: ":443" 41 | 42 | ################################################################ 43 | # Challenge DNS 44 | ################################################################ 45 | certificatesResolvers: 46 | myresolver: 47 | acme: 48 | email: brian@56k.cloud 49 | storage: acme.json 50 | dnsChallenge: 51 | provider: digitalocean 52 | delayBeforeCheck: 0 53 | -------------------------------------------------------------------------------- /08-Advanced-Tips/docker-compose.pilot.yml: -------------------------------------------------------------------------------- 1 | version: '3.7' 2 | 3 | services: 4 | traefik: 5 | # The latest official supported Traefik docker image 6 | image: traefik:v2.3 7 | # Enables the Traefik Dashboard and tells Traefik to listen to docker 8 | # enable --log.level=INFO so we can see what Traefik is doing in the log files 9 | ports: 10 | # Exposes port 80 for incoming web requests 11 | - "80:80" 12 | - "443:443" 13 | # The Web UI port http://0.0.0.0:8080 (enabled by --api.insecure=true) 14 | - "8080:8080" 15 | volumes: 16 | # So that Traefik can listen to the Docker events 17 | - /var/run/docker.sock:/var/run/docker.sock 18 | # Mounts the Traefik static configuration inside the Traefik container 19 | - ./traefik.yml:/etc/traefik/traefik.yml 20 | 21 | # Add the catapp service 22 | catapp: 23 | image: mikesir87/cats:1.0 24 | labels: 25 | - "traefik.enable=true" 26 | # Routers 27 | - "traefik.http.routers.catapp.rule=Host(`catapp.localhost`)" 28 | - "traefik.http.routers.catapp.service=catapp" 29 | - "traefik.http.routers.catapp.entrypoints=web" 30 | - "traefik.http.routers.catapp.middlewares=test-compress,test-errorpages" 31 | # Services 32 | - "traefik.http.services.catapp.loadbalancer.server.port=5000" 33 | # Compress Middleware 34 | - "traefik.http.middlewares.test-compress.compress=true" 35 | # Error Pages Middleware 36 | - "traefik.http.middlewares.test-errorpages.errors.status=400-599" 37 | - "traefik.http.middlewares.test-errorpages.errors.service=error" 38 | - "traefik.http.middlewares.test-errorpages.errors.query=/{status}.html" 39 | 40 | # Error Page service 41 | error: 42 | image: guillaumebriday/traefik-custom-error-pages 43 | labels: 44 | - "traefik.enable=true" 45 | - "traefik.http.routers.error.rule=Host(`error.localhost`)" 46 | - "traefik.http.routers.error.service=error" 47 | - "traefik.http.services.error.loadbalancer.server.port=80" 48 | - "traefik.http.routers.error.entrypoints=web" 49 | -------------------------------------------------------------------------------- /08-Advanced-Tips/traefik-advanced-tips.md: -------------------------------------------------------------------------------- 1 | # Traefik Advanced Tips 2 | 3 | Traefik Logo 4 | 5 | ## 1. Enable Traefik Pilot 6 | 1. Before we begin, lets cleanup any running Docker stack `docker stack rm traefik` If you named you stack something else use your specified name. If you don't remember run `docker stack ls` 7 | 2. Change to the `08-Advanced-Tips` folder 8 | 3. Start Traefik `docker stack deploy -c docker-compose.pilot.yml traefik` 9 | 4. Open the Traefik dashboard [0.0.0.0:8080](http://0.0.0.0:8080) 10 | 5. At the top of the Dashboard click `Register Traefik Instance` 11 | 6. Fill in step 1 token name 12 | 7. Step 2 copy the static configuration in file(YAML) format and pasted in the `traefik.yml` file in the `Enable Traefik Pilot` section 13 | 14 | ```yml 15 | ################################################################ 16 | # Enable Traefik Pilot 17 | ################################################################ 18 | experimental: 19 | pilot: 20 | token: "" 21 | ``` 22 | 23 | Traefik Pilot Registration 24 | 25 | 8. Stop Traefik `docker stack rm traerfik` 26 | 9. Redeploy Traefik `docker stack deploy -c docker-compose.pilot.yml traefik` 27 | 10. Open the Traefik dashboard [0.0.0.0:8080](http://0.0.0.0:8080) 28 | 11. Open Traefik Pilot by clicking on your username in the upper right hand corner. 29 | 30 | 31 | 32 | # Continue to the Next to Advance Tips 33 | 34 | ### Click here to continue -> [Advanced Tips](https://github.com/56kcloud/traefik-training/blob/master/08-Advanced-Tips/traefik-advanced-tips.md) 35 | -------------------------------------------------------------------------------- /08-Advanced-Tips/traefik.yml: -------------------------------------------------------------------------------- 1 | ################################################################ 2 | # API and dashboard configuration 3 | ################################################################ 4 | api: 5 | # Dashboard 6 | # true = default 7 | # 8 | dashboard: true 9 | # 10 | # insecure: false is default 11 | # 12 | insecure: false 13 | 14 | ################################################################ 15 | # Enable Traefik Pilot 16 | ################################################################ 17 | experimental: 18 | pilot: 19 | token: "" 20 | ################################################################ 21 | # Enable Healthcheck 22 | ################################################################ 23 | ping: {} 24 | 25 | ################################################################ 26 | # Docker configuration backend 27 | ################################################################ 28 | providers: 29 | docker: 30 | exposedByDefault: false 31 | swarmMode: true 32 | 33 | ################################################################ 34 | # Traefik Logging - DEBUG, PANIC, FATAL, ERROR, WARN, and INFO (DEFAULT is ERROR) 35 | ################################################################ 36 | log: 37 | level: ERROR 38 | 39 | ################################################################ 40 | # Entrypoint 41 | ################################################################ 42 | entryPoints: 43 | web: 44 | address: ":80" 45 | websecure: 46 | address: ":443" 47 | 48 | ################################################################ 49 | # Challenge DNS 50 | ################################################################ 51 | # certificatesResolvers: 52 | # myresolver: 53 | # acme: 54 | # email: brian@56k.cloud 55 | # storage: acme.json 56 | # dnsChallenge: 57 | # provider: digitalocean 58 | # delayBeforeCheck: 0 59 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Citizen Code of Conduct 2 | 3 | ## 1. Purpose 4 | 5 | A primary goal of Traefik Training is to be inclusive to the largest number of contributors, with the most varied and diverse backgrounds possible. As such, we are committed to providing a friendly, safe and welcoming environment for all, regardless of gender, sexual orientation, ability, ethnicity, socioeconomic status, and religion (or lack thereof). 6 | 7 | This code of conduct outlines our expectations for all those who participate in our community, as well as the consequences for unacceptable behavior. 8 | 9 | We invite all those who participate in Traefik Training to help us create safe and positive experiences for everyone. 10 | 11 | ## 2. Open [Source/Culture/Tech] Citizenship 12 | 13 | A supplemental goal of this Code of Conduct is to increase open [source/culture/tech] citizenship by encouraging participants to recognize and strengthen the relationships between our actions and their effects on our community. 14 | 15 | Communities mirror the societies in which they exist and positive action is essential to counteract the many forms of inequality and abuses of power that exist in society. 16 | 17 | If you see someone who is making an extra effort to ensure our community is welcoming, friendly, and encourages all participants to contribute to the fullest extent, we want to know. 18 | 19 | ## 3. Expected Behavior 20 | 21 | The following behaviors are expected and requested of all community members: 22 | 23 | * Participate in an authentic and active way. In doing so, you contribute to the health and longevity of this community. 24 | * Exercise consideration and respect in your speech and actions. 25 | * Attempt collaboration before conflict. 26 | * Refrain from demeaning, discriminatory, or harassing behavior and speech. 27 | * Be mindful of your surroundings and of your fellow participants. Alert community leaders if you notice a dangerous situation, someone in distress, or violations of this Code of Conduct, even if they seem inconsequential. 28 | * Remember that community event venues may be shared with members of the public; please be respectful to all patrons of these locations. 29 | 30 | ## 4. Unacceptable Behavior 31 | 32 | The following behaviors are considered harassment and are unacceptable within our community: 33 | 34 | * Violence, threats of violence or violent language directed against another person. 35 | * Sexist, racist, homophobic, transphobic, ableist or otherwise discriminatory jokes and language. 36 | * Posting or displaying sexually explicit or violent material. 37 | * Posting or threatening to post other people's personally identifying information ("doxing"). 38 | * Personal insults, particularly those related to gender, sexual orientation, race, religion, or disability. 39 | * Inappropriate photography or recording. 40 | * Inappropriate physical contact. You should have someone's consent before touching them. 41 | * Unwelcome sexual attention. This includes, sexualized comments or jokes; inappropriate touching, groping, and unwelcomed sexual advances. 42 | * Deliberate intimidation, stalking or following (online or in person). 43 | * Advocating for, or encouraging, any of the above behavior. 44 | * Sustained disruption of community events, including talks and presentations. 45 | 46 | ## 5. Weapons Policy 47 | 48 | No weapons will be allowed at Traefik Training events, community spaces, or in other spaces covered by the scope of this Code of Conduct. Weapons include but are not limited to guns, explosives (including fireworks), and large knives such as those used for hunting or display, as well as any other item used for the purpose of causing injury or harm to others. Anyone seen in possession of one of these items will be asked to leave immediately, and will only be allowed to return without the weapon. Community members are further expected to comply with all state and local laws on this matter. 49 | 50 | ## 6. Consequences of Unacceptable Behavior 51 | 52 | Unacceptable behavior from any community member, including sponsors and those with decision-making authority, will not be tolerated. 53 | 54 | Anyone asked to stop unacceptable behavior is expected to comply immediately. 55 | 56 | If a community member engages in unacceptable behavior, the community organizers may take any action they deem appropriate, up to and including a temporary ban or permanent expulsion from the community without warning (and without refund in the case of a paid event). 57 | 58 | ## 7. Reporting Guidelines 59 | 60 | If you are subject to or witness unacceptable behavior, or have any other concerns, please notify a community organizer as soon as possible. info@56k.cloud. 61 | 62 | 63 | 64 | Additionally, community organizers are available to help community members engage with local law enforcement or to otherwise help those experiencing unacceptable behavior feel safe. In the context of in-person events, organizers will also provide escorts as desired by the person experiencing distress. 65 | 66 | ## 8. Addressing Grievances 67 | 68 | If you feel you have been falsely or unfairly accused of violating this Code of Conduct, you should notify 56kcloud with a concise description of your grievance. Your grievance will be handled in accordance with our existing governing policies. 69 | 70 | 71 | 72 | ## 9. Scope 73 | 74 | We expect all community participants (contributors, paid or otherwise; sponsors; and other guests) to abide by this Code of Conduct in all community venues--online and in-person--as well as in all one-on-one communications pertaining to community business. 75 | 76 | This code of conduct and its related procedures also applies to unacceptable behavior occurring outside the scope of community activities when such behavior has the potential to adversely affect the safety and well-being of community members. 77 | 78 | ## 10. Contact info 79 | 80 | info@56k.cloud 81 | 82 | ## 11. License and attribution 83 | 84 | The Citizen Code of Conduct is distributed by [Stumptown Syndicate](http://stumptownsyndicate.org) under a [Creative Commons Attribution-ShareAlike license](http://creativecommons.org/licenses/by-sa/3.0/). 85 | 86 | Portions of text derived from the [Django Code of Conduct](https://www.djangoproject.com/conduct/) and the [Geek Feminism Anti-Harassment Policy](http://geekfeminism.wikia.com/wiki/Conference_anti-harassment/Policy). 87 | 88 | _Revision 2.3. Posted 6 March 2017._ 89 | 90 | _Revision 2.2. Posted 4 February 2016._ 91 | 92 | _Revision 2.1. Posted 23 June 2014._ 93 | 94 | _Revision 2.0, adopted by the [Stumptown Syndicate](http://stumptownsyndicate.org) board on 10 January 2013. Posted 17 March 2013._ 95 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | Thank you so much for your interest in contributing to [56K.Cloud Training](https://training.56k.cloud) tutorials. We want to give back to the Open Source community what we have learned and taught over the years. We offer training to companies, organizations, and individuals. 56K believes that everything should be Open Source and it is an integral part of our company including the training we offer. 2 | 3 | Just a few quick things to be aware of before you get started. 4 | 5 | We welcome issues and pull requests for either adding a new tutorial, or fixing a problem with an existing tutorial. This is a repository for tutorials that uses the native components of Docker & Kubernetes based projects as much as possible. So if there’s a Docker or Kubernetes tool for what you’re describing, please use that. 6 | 7 | Anything you contribute will be under an Apache license. Anything posted here may be forked by anyone on GitHub. 8 | 9 | We will be following the lightweight version of the Docker contribution policies and procedures as explained in 10 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 56K Cloud 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 56K.Cloud Traefik Training Course Resources 2 | 3 | Traefik Logo 4 | 5 | Welcome to [56K.Cloud](https://www.56k.cloud) Traefik Training & Labs. This repo contains [Traefik](https://containo.us/traefik/) course resources for the [Traefik Training](https://www.thebyte.io/traefik-training) course authored both by the respective companies or organizations, and by members of the community. We welcome contributions and want to grow the repo. 6 | 7 | ## Traefik Training Course 8 | 9 | ## 00. Setup Lab Environment 10 | * [Setup Lab Environment](./00-Setup-Lab-Environment/setup.md) 11 | 12 | ## 1. Getting Started with Traefik 13 | * [Getting Started with Traefik](./01-Traefik-Overview/traefik_overview.md) 14 | 15 | ## 2. Configure Traefik 16 | * [Traefik Static & Dynamic Configuration](./02-Configure-Traefik/traefik-configuration.md) 17 | 18 | ## 3. Traefik Routing & Loadbalancing 19 | * [Traefik Routing & Loadbalancing](./03-Routers-and-Services/traefik-routers-and-services.md) 20 | 21 | ## 4. HTTPS / TLS / Let's Encrypt 22 | * [Traefik DNS, HTTPS, and TLS](./04-HTTPS-TLS/traefik-https-tls.md) 23 | 24 | ## 5. Traefik Middlewares 25 | * [Traefik Middlewares](./05-Middlewares/traefik-middlewares.md) 26 | 27 | ## 6. Traefik Observability 28 | * [Traefik Observability](./06-Observability/traefik-observability.md) 29 | 30 | 31 | ## 7. Traefik Operations 32 | * [Traefik Operations](./07-Operations/traefik-operations.md) 33 | 34 | ## 8. Traefik Advanced Tips 35 | * [Traefik Advanced Tips](./08-Advanced-Tips/traefik-advanced-tips.md) 36 | 39 | 40 | 41 | #### Contributing 42 | 43 | If you see an error or something needs updating please contribute back to the repo 44 | 45 | [Guide to submitting your own tutorial](contribute.md) 46 | 47 | 48 | 49 | -------------------------------------------------------------------------------- /img/56k-logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 11 | 12 | 14 | 15 | 17 | 20 | 22 | 25 | 26 | 29 | 31 | 33 | 34 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /img/Traefik_training.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/56kcloud/traefik-training/ea35f220dc306d05f69a73c8537da38953beca43/img/Traefik_training.png -------------------------------------------------------------------------------- /img/catapp_router_error.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/56kcloud/traefik-training/ea35f220dc306d05f69a73c8537da38953beca43/img/catapp_router_error.png -------------------------------------------------------------------------------- /img/catapp_router_service.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/56kcloud/traefik-training/ea35f220dc306d05f69a73c8537da38953beca43/img/catapp_router_service.png -------------------------------------------------------------------------------- /img/catapp_router_service_name.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/56kcloud/traefik-training/ea35f220dc306d05f69a73c8537da38953beca43/img/catapp_router_service_name.png -------------------------------------------------------------------------------- /img/traefik-dns-wildcard.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/56kcloud/traefik-training/ea35f220dc306d05f69a73c8537da38953beca43/img/traefik-dns-wildcard.png -------------------------------------------------------------------------------- /img/traefik-dns.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/56kcloud/traefik-training/ea35f220dc306d05f69a73c8537da38953beca43/img/traefik-dns.png -------------------------------------------------------------------------------- /img/traefik-pilot-instance-registration.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/56kcloud/traefik-training/ea35f220dc306d05f69a73c8537da38953beca43/img/traefik-pilot-instance-registration.png -------------------------------------------------------------------------------- /img/traefik_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/56kcloud/traefik-training/ea35f220dc306d05f69a73c8537da38953beca43/img/traefik_logo.png --------------------------------------------------------------------------------