Traefik
Traefik’s errors middleware asks another service for a page whenever a backend
answers with a status you choose. Error Pages understands that request: Traefik asks
for /{status}.html and gets the page for that status.
Example
Section titled “Example”services: error-pages: image: noixdev/error-pages labels: - traefik.enable=true
# Backend errors 502-504 are answered by error-pages. - traefik.http.middlewares.ep-errors.errors.status=502-504 - traefik.http.middlewares.ep-errors.errors.service=error-pages - traefik.http.middlewares.ep-errors.errors.query=/{status}.html
# Compression: the pages are self-contained and about 100-200 KB each. - traefik.http.middlewares.ep-compress.compress=true
# Catch-all: anything no other router handles gets the 404 page. - traefik.http.middlewares.ep-404.replacepath.path=/404.html - traefik.http.routers.ep-catchall.rule=HostRegexp(`.+`) - traefik.http.routers.ep-catchall.priority=1 - traefik.http.routers.ep-catchall.middlewares=ep-404,ep-compress - traefik.http.services.error-pages.loadbalancer.server.port=8080Attach the ep-compress and ep-errors middlewares to your own routers with
middlewares=ep-compress,ep-errors. List ep-compress first so it also wraps the
pages the errors middleware fetches.
Compression
Section titled “Compression”Each page is self-contained and about 100-200 KB, because the fonts are inlined. They
compress well, so enable Traefik’s compress middleware on every router that serves
error pages, as in the example above. Error Pages does not compress responses itself.
On TLS-only setups the catch-all router also needs its entrypoint and TLS, for example traefik.http.routers.ep-catchall.entrypoints=websecure and traefik.http.routers.ep-catchall.tls=true.
The catch-all router
Section titled “The catch-all router”The catch-all router has the lowest priority, so it only receives requests that no
other router matched, for example a host name that points at Traefik but has no
service. Error Pages answers every path it does not know with its default page
(DEFAULT_PAGE, 404 unless you change it), but a visitor can still ask for a
specific code by path: example.org/500 would answer 500. The replacePath
middleware prevents that by always rewriting the path to one page, whatever the
visitor asked for.
Use /404.html for a plain “not found” page. For services that should only be
reachable from your internal network, point the rewrite at /internal.html
instead. That page is served with status 403 and explains that the service is
available internally only.
Unhealthy and starting containers: allowEmptyServices
Section titled “Unhealthy and starting containers: allowEmptyServices”The Docker provider only creates a router for a service that has a server. While a backend container is unhealthy or still starting, its router would vanish, the request would fall through to the catch-all router, and the visitor would see the 404 or internal-only page, which is misleading.
Set allowEmptyServices: true on the Traefik Docker provider:
providers: docker: allowEmptyServices: trueThe router then stays in place. With Traefik v3 it answers 500 when it has no
healthy server (observed on 3.7), not 503. The default 502-504 range of the errors
middleware does not include 500, so the visitor gets Traefik’s plain response instead of
the error page.
To show the page, add 500 to the status list:
- traefik.http.middlewares.ep-errors.errors.status=500,502-504The errors middleware then shows the 500 page, or the maintenance page while
maintenance mode is on. The
trade-off: the middleware cannot tell Traefik’s own 500 from one your application sent,
so every 500 from every backend behind it is replaced by the error page, and the
application’s own error body is lost. Add 500 only if you accept that. Without it, the
router still keeps the request away from the misleading 404 catch-all.
A stopped container is a different case: the Docker provider no longer sees it at
all, so its router is gone regardless of this setting and the catch-all page answers.
To show the 503 page (or, while maintenance mode is on, the maintenance page) for a
service that is switched off on purpose, keep a router for that host in the file
provider that points at the error-pages service and rewrites the path to /503.html.
Other proxies
Section titled “Other proxies”If your proxy keeps the original path and sends the status in an X-Code header
(as ingress-nginx does for custom errors), Error Pages uses that header. A path that
names a page, such as /404.html, always wins over X-Code. Otherwise any
proxy that can request /{status}.html from another service works the same way.