Docker Swarm + Traefik: Expose Traefik GUI through frontend rule; Service / Container port redirection - docker

I am trying to use Traefik with Docker Swarm backend, and I am using the stack file below:
version: "3"
services:
traefik:
image: traefik:1.5
command: --web --docker --docker.swarmmode --docker.watch --docker.domain=sample.com --logLevel=DEBUG
deploy:
placement:
constraints: [node.role==manager]
restart_policy:
condition: on-failure
labels:
- "traefik.port=8080"
- "traefik.docker.network=sample-network"
- "traefik.frontend.rule=Host:traefik.sample.com"
ports:
- "80:80"
- "8080:8080"
- "443:443"
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- /dev/null:/traefik.toml
networks:
- sample-network
portainer:
image: portainer/portainer:latest
command: --no-auth -H unix:///var/run/docker.sock
deploy:
placement:
constraints: [node.role == manager]
labels:
- "traefik.portainer.port=7777"
- "traefik.docker.network=sample-network"
- "traefik.frontend.rule=Host:portainer.sample.com"
ports:
- "7777:9000"
volumes:
- /var/run/docker.sock:/var/run/docker.sock
networks:
- sample-network
networks:
sample-network:
I have 2 questions that I am trying to wrap my head around:
1) (Exposing Traefik dashboard through frontend rule) I can access Traefik's web dashboard on sample.com:8080, yet I cannot access it through traefik.sample.com.
2) (Port Redirection on containers/services) I can access Portainer GUI through sample.com:7777, yet I cannot access it through portainer.sample.com. I am more curious of port redirection, because how will I setup 2 services in a single stack file if I encounter 2 images publishing to the same port? My service label declarations will clash at traefik.port=XXXX

You don´t need the traefik labels on the traefik service itself. It´s accessed from the outside over the specified ports:
ports:
- "80:80"
- "8080:8080"
- "443:443"
On the portainer service you don´t need the port mappings because you probably want to route the request with traefik.
Because traefik and portainer are in the same docker network traefik can access portainer on every port.
Therefore the port for traefik have to match the real portainer port:
labels:
- "traefik.port=9000"
- "traefik.docker.network=sample-network"
- "traefik.frontend.rule=Host:portainer.sample.com"
In the current setup you have to request traefik with Host:portainer.sample.com.
You can test it with
curl --verbose --header 'Host: portainer.sample.com' 'http://<DockerhostIp>:80'
Edit: Updated curl
Edit 2: Reaction to the edit of PO
The portainer.sample.com DNS entry will have to point to your docker host. Then traefik will route it to the correct container.
An alternative is to specifiy a traefik prefix:
"traefik.frontend.rule=Host:site1.org;PathPrefixStrip: /sub/"
With the rule all requests on site1.org/sub will routed to this specific service/container.
Have a look at
Traefik-Docker-Sample
Edit 3:
The self route for the dashboard/webui should work with:
labels:
- "traefik.port=8080"
- "traefik.docker.network=sample-network"
- "traefik.frontend.rule=Host:traefik.sample.com"
Just be sure that you have a DNS entry for traefik.sample.com.
To check if the traefik setup works you can also run
curl --verbose -H Host:traefik.sample.com <DockerHostIp>

Related

traefik discovers consul service but can not reach from outside

I am trying to make combination of docker + consul + traefik from last several days and it doesn't seem to be working. I am at a point where I just don't know what I am missing in my configuration.
My docker host IP address is: 192.168.30.12
I created a bridge network called consulwhich has a subnet of 172.28.0.5/16
Here is my docker compose for consul (for simplicity, I am running just one consul server so that I can debug an issue)
services:
consul-server:
container_name: consul-server-bootstrap
image: consul:latest
networks:
- consul
ports:
- 8400:8400
- 8500:8500
- 53:8600
- 53:8600/udp
command: agent -server -bootstrap -ui -node=consul-server -client=0.0.0.0 -advertise=192.168.30.12 -recursor=8.8.8.8
restart: unless-stopped
I am using registrator to register service to the consul. Here is docker compose for that service:
registrator:
image: gliderlabs/registrator:latest
volumes:
- /var/run/docker.sock:/tmp/docker.sock
container_name: consul-registrator
restart: unless-stopped
command: consul://consul-server-bootstrap:8500
networks:
- consul
Here is my traefik docker compose section
reverse-proxy:
container_name: traefik
image: traefik:v2.9
networks:
- consul
command: --api.insecure=true --providers.consulcatalog=true --providers.consulcatalog.prefix=traefik --providers.consulcatalog.endpoint.address=http://192.168.30.12:8500
ports:
- "80:80"
- "8080:8080"
Here is whoami container that I am registering with consul
whoami:
# A container that exposes an API to show its IP address
image: traefik/whoami
networks:
- consul
restart: unless-stopped
environment:
- SERVICE_TAGS=whoami
- SERVICE_NAME=whoami
- SERVICE_80_ID=whoami
ports:
- "80"
labels:
- traefik.enable=true
- traefik.backend=whoami
- traefik.port=80
- traefik.default.protocol=http
- traefik.http.routers.whoami.rule=Host(`whoami`)
When I visit http://192.168.30.12:8500, I see that whoami is registered with consul as seen below:
I see whoami on traefik dashboard as well when I visit http://192.168.30.12:8080
I also run dig command dig #127.0.0.1 whoami.service.consul on my docker host and that also can discover the service just fine as seen below:
I made a host entry on my other computer as seen below
192.168.30.12 whoami
When I try to visit http://whoami in browser, I get "Bad Gateway" error.
I want to register new containers to consul using registrator and than add it to the traefik load balancer using service tags and then consume those service from outside of my docker host.
Can someone please point me where I am making mistake. I have spent several days on it to make it work.

Traefik + cloudflared with full strict tunnel on docker

I have a VM which run multiple containers all linked to one docker network.
Traefik (as reverse proxy & load balancer)
cloudflared as tunnel
whoami (for testing purposes)
and some containers like photoprism, nextcloud, node-red,...
I generated an origin cert via Cloudflare which has been added to Traefik.
In Cloudflare, I have a subdomain which points via the tunnel to https://172.16.10.11 (ip from the VM). This causes an unsecure connection (IP SAN applied -> I don't think this is possible on a private ip?). When I disable TLS verification on Cloudflare, it works. However, I am trying to set this up properly. Next,I tried pointing my domain towards https://localhost. the cloudflared service running in a container cannot reach any other services as these are located other containers.
I was thinking, what if I run the cloudflared service within the Traefik container, I believe I can reach Traefik via localhost?
Do you have any advice on how to achieve a secure tunnel with cert verification? Or is this not realistic when self-hosting?
Current docker compose:
version: '3'
services:
traefik:
image: traefik:latest
command:
- --log.level=debug
- --api.insecure=true
- --providers.docker=true
- --providers.docker.exposedbydefault=false
- --entrypoints.web.address=:80
- --entrypoints.websecure.address=:443
- --serverstransport.insecureskipverify
- --providers.file.filename=/etc/traefik/dynamic_conf.yml
- --providers.file.watch=true
ports:
- "8080:8080"
- "443:443"
- "80:80"
networks:
- proxy_network
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- traefik-data:/etc/traefik
labels:
- traefik.enable=true
- traefik.docker.network=proxy_network
- traefik.http.routers.traefik.rule=Host(`${DOMAINNAME_TRAEFIK}`)
- traefik.http.routers.traefik.entrypoints=web
- traefik.http.routers.traefik.service=traefik
- traefik.http.services.traefik.loadbalancer.server.port=8080
tunnel:
container_name: cloudflared-tunnel
image: cloudflare/cloudflared
#restart: unless-stopped
networks:
- proxy_network
command: tunnel --no-autoupdate run --token ${CLOUDFLARED_TOKEN}
whoami:
image: traefik/whoami
container_name: whoami1
command:
# It tells whoami to start listening on 2001 instead of 80
- --port=2000
- --name=iamfoo
networks:
- proxy_network
labels:
- traefik.enable=true
- traefik.http.routers.whoami.rule=Host(`${DOMAINNAME}`)
- traefik.http.routers.whoami.entrypoints=websecure
- traefik.http.routers.whoami.tls=true
- traefik.http.routers.whoami.service=whoami
- traefik.http.services.whoami.loadbalancer.server.port=2000
volumes:
traefik-data:
driver: local
networks:
proxy_network:
name: proxy_network
external: true
I expect a secure tunnel solution and to make sure that this architecture is setup in a good way.

Traefik not updating when services are deployed to docker swarm

I have a traefik environment running in docker. Originally I was running services in standard containers. I am not deploying containers to docker swarm and I have done this for traefik too, where the container is only deployed to my swarm manager.
For some reason, traefik successfully registers the host name I have given it, and can access that fine.
However, when I deploy any other service to the swarm, traefik doesn't pick it up.
There is one other service that has partially worked. I have deployed heimdall to docker swarm which can be access from gateway.docker.swarm:8091 but I don't want the port either.
My traefik compose file is as follows:
version: '3.3'
networks:
swarm-network:
driver: overlay
services:
traefik:
# The official v2 Traefik docker image
image: traefik
deploy:
placement:
constraints:
- node.role == manager
labels:
- "traefik.enable=true"
- "traefik.docker.network=pi_swarm-network"
- "traefik.http.routers.traefik.entrypoints=http"
- "traefik.http.services.traefik.loadbalancer.server.port=8080"
- "traefik.http.routers.traefik.rule=Host(`traefik.docker.swarm`)"
# Enables the web UI and tells Traefik to listen to docker
command:
- '--api.insecure=true'
- '--providers.docker=true'
- '--providers.docker.swarmmode=true'
- '--providers.docker.defaultRule=Host("docker.swarm")'
- '--providers.docker.watch=true'
- '--providers.docker.swarmModeRefreshSeconds=15s'
# Metrics configuration for influx db.
- '--metrics=true'
- '--metrics.influxdb=true'
- '--metrics.influxdb.address=192.168.8.122:8086'
- '--metrics.influxdb.protocol=http'
- '--metrics.influxdb.database=traefik'
- '--metrics.influxdb.addEntryPointsLabels=true'
- '--metrics.influxdb.addServicesLabels=true'
- '--metrics.influxdb.pushInterval=10s'
# Tracing
- '--tracing=true'
- '--tracing.zipkin=true'
- '--tracing.zipkin.httpEndpoint=http://192.168.8.117:9411/api/v2/spans'
- '--log'
- '--accesslog'
ports:
# The HTTP port
- "80:80"
# The Web UI (enabled by --api.insecure=true)
- "8080:8080"
networks:
- swarm-network
volumes:
# So that Traefik can listen to the Docker events
- /var/run/docker.sock:/var/run/docker.sock
An example of another service I am running is heimdall which has the compose file of the following:
version: "3"
networks:
swarm-network:
external:
name: pi_swarm-network
services:
heimdall:
image: ghcr.io/linuxserver/heimdall
environment:
- PUID=1000
- PGID=1000
- TZ=Europe/London
deploy:
placement:
constraints:
- node.labels.tier == web
labels:
- "traefik.enable=true"
- "traefik.docker.network=pi_swarm-network"
- "traefik.http.routers.heimdall.entrypoints=http"
- "traefik.http.services.heimdall.loadbalancer.server.port=8091"
- "traefik.http.routers.heimdall.rule=Host(`gateway.docker.swarm`)"
ports:
- 8091:80
restart: unless-stopped
networks:
- swarm-network
Can anyone see what I'm doing wrong?
I have figured out the problem.
In my compose file, I was using "traefik.http.services.heimdall.loadbalancer.entrypoints=http"
as well as
"traefik.http.routers.heimdall.entrypoints=http"
this was incorrect and needed to just be
"traefik.http.routers.heimdall.entrypoints=http"
For heimdall, I was also targetting the external port of 8091, whereas I actually needed to target the internal port of 80

Traefik routing one application to port 80, others require explicit port

I have an environment running docker containers.
This environment hosts Traefik, Nextcloud, MotionEye and Heimdall.
I also have another environment running CoreDNS in a docker container.
For some reason, I can get MotionEye to be accessible from motioneye.docker.swarm (changed the domain in here for privacy).
However, for nextcloud and Heimdall, I have to explicitly access the ports and I'm struggling to tell why.
e.g. Heimdall is gateway.docker.swarm:8091 when should be gateway.docker.swarm
When a user requests a webpage onto the local dns server X.X.X.117 it gets routed through to the traefik instance on X.X.X.106.
My traefik compose file is as follows:
version: '3'
services:
reverse-proxy:
# The official v2 Traefik docker image
image: traefik:v2.3
restart: always
# Enables the web UI and tells Traefik to listen to docker
command: --api.insecure=true --providers.docker
ports:
# The HTTP port
- "80:80"
# The Web UI (enabled by --api.insecure=true)
- "8080:8080"
volumes:
# So that Traefik can listen to the Docker events
- /var/run/docker.sock:/var/run/docker.sock
labels:
- "traefik.port=8080"
- "traefik.backend=traefik"
- "traefik.frontend.rule=Host:traefik.docker.swarm"
- "traefik.docker.network=traefik_default"
My Heimdall compose is as follows:
version: "3"
services:
heimdall:
image: ghcr.io/linuxserver/heimdall
container_name: heimdall
environment:
- PUID=1000
- PGID=1000
- TZ=Europe/London
volumes:
- /home/pi/heimdall/config:/config
ports:
- 8091:80
restart: unless-stopped
networks:
- heimdall
labels:
- "traefik.enable=true"
- "traefik.port=8091"
- "traefik.http.routers.heimdall.entrypoints=http"
- "traefik.http.routers.heimdall.rule=Host(`gateway.docker.swarm`)"
networks:
heimdall:
external:
name: heimdall
Can anyone see what I'm doing wrong here?
When you access through gateway.docker.swarm:8091 it works because you are accessing the heimdall container directly. This is possible because you defined
ports:
- 8091:80
in your docker-compose.
In order to access through traefik they must be on the same network. Also, remove the port mapping if you like this container to be only accessible through traefik. And finally correct the traefik port accordingly.
version: "3"
services:
heimdall:
image: ghcr.io/linuxserver/heimdall
container_name: heimdall
environment:
- PUID=1000
- PGID=1000
- TZ=Europe/London
volumes:
- /home/pi/heimdall/config:/config
restart: unless-stopped
labels:
- "traefik.enable=true"
- "traefik.port=80"
- "traefik.http.routers.heimdall.entrypoints=http"
- "traefik.http.routers.heimdall.rule=Host(`gateway.docker.swarm`)"

How do I configure traefik properly for docker services on subdomains?

The example from the traefik quickstart guide for using the whoami image on the whoami subdomain works, but I can't get jellyfin working in a similar setup, and I can't figure out what's different:
kevin#pihost:~/personal$ curl -H Host:jellyfin.kevinm416.com http://127.0.0.1
Bad Gateway
kevin#pihost:~/personal$ curl -H Host:whoami.kevinm416.com http://127.0.0.1
Hostname: f7820e1787fe
IP: 127.0.0.1
...
This is my docker-compose file, which has all the traefik config:
version: "3"
volumes:
jellyfin-config:
jellyfin-cache:
services:
reverse-proxy:
image: traefik:v2.2
# Enables the web UI and tells Traefik to listen to docker
command:
- "--api.insecure=true"
- "--providers.docker"
- "--entrypoints.web.address=:80"
- "--entrypoints.websecure.address=:443"
ports:
- "80:80"
- "443:443"
# The Web UI (enabled by --api.insecure=true)
- "8080:8080"
volumes:
- /var/run/docker.sock:/var/run/docker.sock
whoami:
image: containous/whoami
labels:
- "traefik.http.routers.whoami.rule=Host(`whoami.kevinm416.com`)"
jellyfin:
image: jellyfin/jellyfin
network_mode: "host"
environment:
TZ: 'America/Los_Angeles'
ports:
- "8096:8096"
volumes:
- jellyfin-config:/config
- jellyfin-cache:/cache
- /home/kevin/microcenter:/microcenter:ro
labels:
- "traefik.http.routers.jellyfin.rule=Host(`jellyfin.kevinm416.com`)"
- "traefik.http.services.jellyfin.loadbalancer.server.port=8096"
restart: always
I guess there could be two problems:
you haven't specified entrypoints for your containers, e.g. for whoami it could be (maybe you want new one for jellyfin with port 8096?):
- "traefik.http.routers.whoami.entrypoints=web"
network_mode: "host" in jellyfin -- traefik should be in the same network as container (or try to use traefik.docker.network setting), so I would suggest just remove that line.

Resources