Traefik two frontends on one backend different ports - docker-compose

I'm running traefik 1.7.8 and created a container via docker-compose with following labels and frontend rules:
labels:
- "traefik.enable=true"
- "traefik.data.frontend.rule=Host:data.${DOMAINNAME}"
- "traefik.data.port=324"
- "traefik.data.protocol=http"
- "traefik.webtools.frontend.rule=Host:webtools.${DOMAINNAME}"
- "traefik.webtools.port=334"
- "traefik.webtools.protocol=http"
- "traefik.docker.network=traefik_proxy"
- "traefik.frontend.headers.SSLRedirect=true"
- "traefik.frontend.headers.STSSeconds=315360000"
- "traefik.frontend.headers.browserXSSFilter=true"
- "traefik.frontend.headers.contentTypeNosniff=true"
- "traefik.frontend.headers.forceSTSHeader=true"
- "traefik.frontend.headers.SSLHost=DOMAIN.COM"
- "traefik.frontend.headers.STSIncludeSubdomains=true"
- "traefik.frontend.headers.STSPreload=true"
- "traefik.frontend.headers.frameDeny=true"
I would like to access via data.DOMAIN.COM port 324 of the container and via webtools.DOMAIN.COM port 334 of the container.
After everything has started up I have one frontend and one backend for the rule "data" but the "webtools" is missing.
Based on the documentation it should just work out fine: https://docs.traefik.io/configuration/backends/docker/#on-containers-with-multiple-ports-segment-labels
Do i miss an obvious mistake?
Thank you!
EDIT:
a shutdown and restart of all containers has resolved the issue.

Related

Attempt to rewrite minimal Traefik example to use TLS does not work

The minimal example from https://doc.traefik.io/traefik/user-guides/docker-compose/basic-example/ works on my local machine. However, when I try to adapt this to use TLS I run into an issue. I'm a Traefik newbie, so I might be doing a stupid mistake.
This is my attempt:
version: "3.3"
services:
traefik:
image: "traefik:v2.8"
container_name: "traefik"
command:
- "--log.level=DEBUG"
- "--accesslog=true"
- "--api.insecure=true"
- "--providers.docker=true"
- "--providers.docker.exposedbydefault=false"
- "--entrypoints.web.address=:80"
- "--entrypoints.websecure.address=:443"
ports:
- "443:443"
- "8080:8080"
volumes:
- "/var/run/docker.sock:/var/run/docker.sock:ro"
whoami:
image: "traefik/whoami"
container_name: "simple-service"
labels:
- "traefik.enable=true"
- "traefik.http.routers.whoami.rule=Host(`127.0.0.1`)"
- "traefik.http.routers.whoami.entrypoints=websecure"
So the major modification is to use "traefik.http.routers.whoami.entrypoints=websecure" instead of "traefik.http.routers.whoami.entrypoints=web"
Running
$ curl -k https://127.0.0.1
I get
404 page not found
The traefik log shows no routing related issues and the internal traefik setup for routing etc shown using curl https://127.0.0.1:8080/api/rawdata | jq . looks the same as the one of the working example, except the changed port.
So I opted for new answer instead of just editing the old answer. (Reason being even incorrect answers teach something).
My reference is this great post by Marc Mogdanz (link: https://marcmogdanz.de/posts/infrastructure-with-traefik-and-cloudflare/).
The direct answer to your query is:
Expose port 8080 but do not publish it
Add a host name rule. This will allow Traefik to route a URL request to its own port 8080.
The affected part of the compose file would be as follows (assuming that the URL https://dashboard.example.com is the desired URL to reach the dashboard):
expose:
- 8080
...
labels:
- "traefik.enable=true"
- "traefik.http.routers.traefik.rule=Host(`dashboard.example.com`)"
- "traefik.http.routers.traefik.tls=true"
- "traefik.http.services.traefik.loadbalancer.server.port=8080"
Finally, I noticed you are testing on localhost. If you are testing on a local machine, use localhost for the dashboard and keep 127.0.0.1 for whoami.
Or, alternately, add a static entry for a subdomain (see https://stackoverflow.com/a/19016600).
Either way, Traefik is looking at the SNI requested - not necessarily the IP address - when matching the Host rule.
Request ----> Docker:443 ---> {Traefik}-"SNI?"---"127.0.0.1"---> {whoami}
| \
| \
8080<---"dashboard.localhost"
Add the following entry to your Traefik:
"--entrypoints.websecure.address=:8080"
Normally it would be 8080 for http and 8443 for https alternative ports, but since your example specifically states https://~:8080, I have adapted it accordingly.

Bad Gateway with Traefik and Docker Compose

I'm trying to deploy a React + FastApi + Postgres application on docker compose with Traefik as the reverse proxy. I'm running into issues with Bad Gateway errors. Running my FastAPI locally runs it on port 8888 and exposes the path /docs to view the api documentation. I'd like to eventually have the application running on example.local with the docs available on example.local/api/docs. My docker-compose.yaml is as follows (loosely based on this one):
version: '3.8'
services:
proxy:
image: traefik:v2.4
networks:
- web
volumes:
- /var/run/docker.sock:/var/run/docker.sock
ports:
- '80:80'
- '8080:8080'
- '443:443'
command:
- --providers.docker
- --api.insecure=true
- --providers.docker.exposedbydefault=false
- --providers.docker.network=web
- --entrypoints.web.address=:80
labels:
- traefik.enable=true
- traefik.http.routers.example-proxy-http.rule=Host(`example.local`)
- traefik.http.routers.example-proxy-http.entrypoints=web
- traefik.http.services.example-proxy.loadbalancer.server.port=80
backend:
build:
context: ./backend
dockerfile: Dockerfile
command: python app/main.py
volumes:
- ./backend/app:/app
env_file:
- .env
networks:
- web
- backend
labels:
- traefik.enable=true
- traefik.http.routers.example-backend-http.rule=PathPrefix(`api/docs`)
- traefik.http.routers.example-backend-http.entrypoints=web
- traefik.http.services.example-backend.loadbalancer.server.port=8888
networks:
web:
external: true
backend:
external: false
I've added 127.0.0.1 example.local to my /etc/hosts file.
From reading around it seems like Bad Gateway errors tend to occur from traefik and related services not being on the same network, or traefik routing traffic to the wrong port on the service container. However if I set ports: - '8888:8888' in my backend service I can access the docs from localhost:8888/docs so I'm pretty sure 8888 is the correct port for the backend loadbalancer. From what I can see traefik and the backend service are on the same network too and I've set it as the default traefik network with --providers.docker.network=web. Interestingly if I visit localhost/api/docs in my browser I'm served up a page from FastAPI. So it could be an issue with my traefik http router labels? I'm quite new to traefik and proxies so would appreciate any help or guidance, thanks!
UPDATE
If I specify the host for the backend by adding
- traefik.http.routers.infilmation-backend-http.rule=Host(`example.local`) && PathPrefix(`/docs`)
to the backend service labels, then visiting example.local/docs does serve up page from FastApi. So I guess my question would be what is the best way of setting up a host for this application? Is there a way I can specify a default host for all services then any PathPrefix rules would be in relation to that host?

Port forwarding with traefik and docker-compose

I would like to serve a docker-compose service through traefik with port-forwarding. I had many tries and the best I could achieve from now is described below:
First I create two networks:
docker network create frontend # To expose traefik
docker network create backend # To bind backend services
The traefik configuration is about (development, dashboard enabled at :8080):
version: "3.6"
services:
proxy:
image: traefik:latest
restart: unless-stopped
command:
- "--log.level=DEBUG"
- "--api"
- "--api.dashboard"
- "--api.insecure"
- "--providers.docker"
- "--providers.docker.exposedbydefault=false"
# Service entrypoint:
- "--entrypoints.lora-server.address=:8090"
volumes:
- "/var/run/docker.sock:/var/run/docker.sock:ro"
labels:
- "traefik.enable=true"
- "traefik.docker.network=frontend"
- "traefik.http.routers.traefik.entrypoints=traefik"
- "traefik.http.routers.traefik.service=api#internal"
networks:
- backend
- frontend
ports:
- "8080:8080"
- "8090:8090"
networks:
frontend:
external: true
backend:
external: true
The backend service is described here (a fork from ChripStack but it could be anything else):
version: "3"
services:
# [...]
chirpstack-application-server:
image: chirpstack/chirpstack-application-server:3
networks:
- backend
volumes:
- ./configuration/chirpstack-application-server:/etc/chirpstack-application-server
labels:
- "traefik.enable=true"
- "traefik.docker.network=backend"
- "traefik.http.routers.chirpstack.entrypoints=lora-server"
- "traefik.http.routers.chirpstack.rule=Host(`{host:}`)"
- "traefik.http.routers.chirpstack.service=chirpstack-application-server#docker"
- "traefik.http.services.chirpstack-application-server.loadbalancer.server.port=8080"
# [...]
networks:
backend:
external: true
The service also natively run on :8080 and I would like to access it on :8090 through traefik.
When I run both applications, traefik registers the new service and does not complain (no errors, no warning, the flow seems complete at least from the dashboard interface).
time="2020-07-30T11:47:47Z" level=debug msg="Creating middleware" middlewareType=Pipelining serviceName=chirpstack-application-server#docker entryPointName=lora-server routerName=chirpstack#docker middlewareName=pipelining
time="2020-07-30T11:47:47Z" level=debug msg="Creating load-balancer" entryPointName=lora-server routerName=chirpstack#docker serviceName=chirpstack-application-server#docker
time="2020-07-30T11:47:47Z" level=debug msg="Creating server 0 http://192.168.112.9:8080" entryPointName=lora-server routerName=chirpstack#docker serviceName=chirpstack-application-server#docker serverName=0
time="2020-07-30T11:47:47Z" level=debug msg="Added outgoing tracing middleware chirpstack-application-server#docker" middlewareName=tracing entryPointName=lora-server routerName=chirpstack#docker middlewareType=TracingForwarder
But I could not access the service, I am geting 404 errors when I try to connect http://host:8090.
To my understanding, it seems traefik does not know how it should complete the flow between the two networks: http://frontend:8090 -> http://backend:8080 (because I haven't referenced it anywhere).
What should I change in my configuration to make it work? How can I specify to traefik that it must route the HTTP traffic from frontend:8090 to backend:8080? Your help is much appreciated.
Traefik listens on some port, that's the only thing defined with entrypoints. You don't specify network for this incoming requests, because it's unrelated. traefik.docker.network is only used for routing after Traefik handles the incoming requests.
So the correct flow is not http://frontend:8090 -> http://backend:8080, but http://host:8090 -> http://backend:8080.
I think your configuration is correct. The only thing which seems to be odd is usage of Host rule. Maybe try to change it to something like this:
"traefik.http.routers.chirpstack.rule=hostregexp(`{host:.+}`)"

Traefik intermittent 404 on docker-compose

I'm running a bunch of services behind a traefik reverse proxy. I have tested those services to death and they work great. The problem is that when traefik is involved I get intermittent 404 errors whhenever I interact with them.
One of those services exposes a nice and simple REST api. Consuming code has to retry all requests. This is managable.
One of thse services exposes a frontend: If I want to use the frontend I have to constantly refresh the page. This is a truely aweful user experience.
Here are some samples from my compose file:
version: "2.1"
services:
reverse-proxy:
image: traefik:v2.2
command:
- "--api.insecure=true"
- "--providers.docker=true"
- "--providers.docker.exposedbydefault=false"
- "--entrypoints.web.address=:80"
ports:
- "8081:80"
- "8082:8080"
volumes:
- /var/run/docker.sock:/var/run/docker.sock
api_service:
image: its_just_a_flask_app
labels:
- "traefik.enable=true"
- "traefik.http.routers.configrouter1.rule=PathPrefix(`/config_backend/`) && (Method(`GET`) || Method(`POST`))"
- "traefik.http.routers.configrouter1.middlewares=config-backend-auth#docker"
- "traefik.http.middlewares.config-backend-auth.basicauth.usersfile=/config/usersfile"
webserver:
image: puckel/docker-airflow:with_a_few_lil_tweaks
restart: always
depends_on:
- postgres # these exist and work fine
- redis
environment:
- LOAD_EX=n
- FERNET_KEY=stuff=
- EXECUTOR=Celery
- AIRFLOW__WEBSERVER__BASE_URL=http://webserver/airflow
volumes:
- ../orchistrator/dags/:/usr/local/airflow/dags
- ./requirements.txt:/requirements.txt
command: webserver
healthcheck:
test: ["CMD-SHELL", "[ -f /usr/local/airflow/airflow-webserver.pid ]"]
interval: 30s
timeout: 30s
retries: 3
labels:
- "traefik.enable=true"
- "traefik.http.routers.aurflowrouter.rule=PathPrefix(`/airflow`)"
- "traefik.http.routers.aurflowrouter.middlewares=airflow-basic-auth#docker"
- "traefik.http.middlewares.airflow-basic-auth.basicauth.usersfile=/config/usersfile"
- traefik.http.services.my-service.loadbalancer.server.port=8080
As you can see both of these use basic auth. removing the auth has no effect
removing the webserver's healthcheck has no effect
when making api calls to the api_service, the first call often fails, the second call always succeeds
when accessing the airflow frontend: the first page load fails, after that it succeeds.
theres a button on the airflow fronend that triggers a POST. The POST returns a 302 Found, then the redirect always gives me a 404 at first
sometimes the web frontend oads, but the static resources that it relies on do not load, resulting in an ugly and unusable site. So I find myself refreshing the page a lot
I'm at a loss here. Any help would be very apprectiated.
Traefik tags I've tried:
Sinve the only advice I've recieved or found so far is about using old tags or new tags, here's what I've found
image: traefik:v2.2
image: traefik:v2.2.1
image: traefik:v2.2.5
image: traefik:latest
I got similar issues after pulling traefik:latest yesterday.
Just noticed the image was updated today and a new pull fixed my issues.
Turned out it was a bug on v2.2.2. See here for more. Use, for example, v2.2.5 to get rid of this problem

Keycloak Gatekeeper (forwarding proxy) does nothing

I have a docker-compose setup with service 1 (grafana) sending requests to service 2 (prometheus).
I've put a Keycloak Gatekeeper in front of service 2, asking for authentication.
That works perfectly fine.
Now my idea was to also place a second Keycloak Gatekeeper in front of service 1, injecting said authentication.
Unfortunately, that doesnt work.
Observing my traffic via wireshark, it seems my second Keycloak Gatekeeper is not even involved in any communication.
My docker compose file for service 1 and the forwarding proxy looks roughly like this:
keycloak-forwarder:
image: quay.io/keycloak/keycloak-gatekeeper
command:
- --enable-forwarding=true
- --forwarding-username=<my_username>
- --forwarding-password=<my_password>
- --forwarding-domains=${BASE_DOMAIN}/grafana
- --listen=:3001
- --client-id=<my_keycloak_client_id>
- --client-secret=<my_keycloak_client_secret>
- --discovery-url=${DOMAIN_PROTOCOL}://${KEYCLOAK_DOMAIN}/auth/realms/<my_keycloak_realm>
networks:
- webgateway
grafana:
image: grafana/grafana
networks:
- webgateway
labels:
traefik.enable: true
traefik.backend: grafana
traefik.frontend.rule: Host:${BASE_DOMAIN};PathPrefix:/grafana;PathPrefixStrip:/grafana
traefik.port: 3000
traefik.docker.network: webgateway
Ok, I've found the solution.
There are several things, that I did wrong.
The forwarding-domains flag describes the domains the request goes to,
not comes from. So if grafana talks to prometheus, the prometheus
domain needs to be entered here.
The Keycloak Gatekeeper doesn't automatically intercept communication. So grafana
needs to use it explicitly as proxy.
So the fixed docker-compose looks the following:
keycloak-forwarder:
image: quay.io/keycloak/keycloak-gatekeeper
command:
- --enable-forwarding=true
- --forwarding-username=<my_username>
- --forwarding-password=<my_password>
- --forwarding-domains=${BASE_DOMAIN}/prometheus
- --listen=:3001
- --client-id=<my_keycloak_client_id>
- --client-secret=<my_keycloak_client_secret>
- --discovery-url=${DOMAIN_PROTOCOL}://${KEYCLOAK_DOMAIN}/auth/realms/<my_keycloak_realm>
networks:
- webgateway
grafana:
image: grafana/grafana
networks:
- webgateway
environment:
- HTTP_PROXY=http://keycloak-forwarder:3001
- HTTPS_PROXY=http://keycloak-forwarder:3001
labels:
traefik.enable: true
traefik.backend: grafana
traefik.frontend.rule: Host:${BASE_DOMAIN};PathPrefix:/grafana;PathPrefixStrip:/grafana
traefik.port: 3000
traefik.docker.network: webgateway