Back again to this topic, cause I realized that the solution I described in the previous post is sub-optimal. Indeed, that was just a redirection but not a proper handling of not found errors. To improve that, the solution is attaching the ErrorPage middleware to the low-priority catchall router (Yes, I was wrong, you can definitely do that!).
Ok, let's recap:
In a nutshell: we are gonna define a low-priority catchall router rule that kicks in only if other routers for defined services can’t handle the request. Then, such an unknown request is handled by the ErrorPage middleware that tells Nginx to serve the error page.
This is how it works:
docker-compose.yml
version: '3.7'
services:
# A cool reverse-proxy / load balancer
traefik:
# The official v2 Traefik docker image
image: traefik:v2.2.7
container_name: traefik
security_opt:
- no-new-privileges:true
restart: always
volumes:
# So that Traefik can listen to the Docker events
- /var/run/docker.sock:/var/run/docker.sock:ro
ports:
# http
- 80:80
command:
###########################################
# Static Configuration harnessing CLI #
###########################################
# Activate dashboard.
- --api.dashboard=true
# Enable Docker backend with default settings.
- --providers.docker=true
# Do not expose containers by default.
- --providers.docker.exposedbydefault=false
# Default Docker network used.
- --providers.docker.network=proxy
# --entrypoints.<name>.address for ports
# 80 (i.e., name = webinsercure)
- --entrypoints.webinsecure.address=:80
networks:
# This is the network over which Traefik communicates with other containers.
- proxy
labels:
################################################
# Dynamic configuration with Docker Labels #
################################################
# You can tell Traefik to consider (or not) this container by setting traefik.enable to true or false.
# We need it for the dashboard
traefik.enable: true
# Dashboard
traefik.http.routers.traefik.rule: Host(`traefik.localhost`)
traefik.http.routers.traefik.service: api@internal
traefik.http.routers.traefik.entrypoints: webinsecure
# The error pages server
nginxError:
image: nginx:latest
volumes:
- ./error-pages:/usr/share/nginx/error-pages # error pages
- ./nginx/default.conf:/etc/nginx/conf.d/default.conf # default configuration
networks:
# This is the network over which Traefik communicates with other containers.
- proxy
labels:
traefik.enable: true
traefik.http.routers.error-router.rule: HostRegexp(`{host:.+}`)
traefik.http.routers.error-router.priority: 1
traefik.http.routers.error-router.entrypoints: webinsecure
traefik.http.routers.error-router.middlewares: error-pages-middleware
traefik.http.middlewares.error-pages-middleware.errors.status: 400-599
traefik.http.middlewares.error-pages-middleware.errors.service: error-pages-service
traefik.http.middlewares.error-pages-middleware.errors.query: /{status}.html
traefik.http.services.error-pages-service.loadbalancer.server.port: 80
# A defined service
my-test-app:
image: containous/whoami
networks:
# This is the network over which Traefik communicates with other containers.
- proxy
labels:
traefik.enable: true
traefik.http.routers.my-test-app.rule: Host(`test.localhost`)
traefik.http.routers.my-test-app.entrypoints: webinsecure
traefik.http.services.my-test-app.loadbalancer.server.port: 80
networks:
proxy:
external: true
You need also to confiugure Nginx to serve error pages
default.conf
server {
listen 80;
server_name localhost;
error_page 404 /404.html;
# other error pages here:
# error_page 403 /403.html;
location / {
root /usr/share/nginx/error-pages;
internal;
}
}
Read more:
- Here you can find static error pages (ready for Traefik) https://github.com/tarampampam/error-pages
- I wrote down some other examples here: https://imandrea.me/blog/traefik-custom-404/