Traefik with Docker Swarm? - docker-swarm

I am not sure if this is possible because I do not have control over the DNS (I can edit /etc/hosts though).
I have a few Azure Ubuntu servers running with 1 manager and 2 workers (3 total). These nodes are only accessible on our corporate network. I typically access web portals from my desktop at the office by typing:
IP-Address:Port
Host:Port
Host.corp.companyname.com:Port
My goal is to instead type something like host/pgadmin or host/portainer to be routed to a web portal which is running on the worker nodes. Is it possible? I don't mind editing my desktop's /etc/hosts file but I don't want to specify an IP address (otherwise there is no point in having the portal run on multiple nodes).
services:
web:
image: traefik:1.7-alpine
networks:
- frontend
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- /dev/null:/traefik.toml
ports:
- "80:80"
- "8080:8080"
command:
- --docker
- --docker.swarmMode
- --docker.domain=corp.companyname.com
- --docker.watch
- --api
- --defaultentrypoints=http
deploy:
placement:
constraints:
- node.role == manager
pgadmin4:
image: dpage/pgadmin4:4.0
ports:
- "5050:80"
deploy:
placement:
constraints:
- node.role == worker
labels:
- traefik.enable=true
- traefik.docker.network=frontend
- traefik.backend=pgadmin4
- traefik.port=5050
- traefik.frontend.rule=???????
networks:
- frontend
networks:
frontend:
external: true
name: frontend

You can totally do it with
- traefik.frontend.rule=PathPrefixStrip:/pgadmin/
Here is a list of matchers that traefik can work with.

I got this to work finally.
I had to rename my traefik.docker.network from frontend to traefik_frontend (traefik was the name I used when I ran the stack deploy command)
I had to use Firefox (Chrome would not work - I have no idea why)
I changed the traefik.port=5050 to traefik.port=80
I added traefik-pgadmin.docker.localhost to my /etc/hosts file on windows (and noticed before I was saving it as .txt file which was wrong)

Related

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

How can I secure the traefik dashboard using SSL & basic auth?

A have traefik set up and working for a 3 node docker swarm on DigitalOcean, and my web apps are being served just fine. I want to secure the traefik dashboard, and have gleaned some info from GitHub issues, but my attempts result in a gateway timeout when trying to access the dashboard.
My compose file is below (auth & url edited for security):
version: "3.5"
services:
traefik:
image: traefik:1.6
command:
- --api
- --docker
- --docker.watch
- --docker.swarmmode
- --entryPoints=Name:http Address::80
- --entryPoints=Name:https Address::443 TLS:/run/secrets/el_cert,/run/secrets/el_key,/run/secrets/as_cert,/run/secrets/as_key
ports:
- 80:80
- 443:443
networks:
- proxy
volumes:
- /var/run/docker.sock:/var/run/docker.sock
secrets:
- as_cert
- as_key
- el_cert
- el_key
deploy:
mode: global
labels:
- "traefik.frontend.entryPoints=http,https"
- "traefik.frontend.headers.SSLRedirect=true"
- "traefik.frontend.rule=Host:<hostname>"
- "traefik.port=8080"
- "traefik.frontend.auth.basic=<user>:<password>"
placement:
constraints: [node.role==manager]
networks:
proxy:
external:
name: proxy
secrets:
as_cert:
external: true
as_key:
external: true
el_cert:
external: true
el_key:
external: true
BTW If I move the labels out from under deploy it works locally using docker-compose.
Adding the following label seems to fix things:
traefik.backend.loadbalancer.swarm=true
I presume the traefik load balancer was getting into some kind of infinite loop. I would be grateful if someone could offer a full explanation!

Traefik segment in Docker Swarm

I had (as all of us who used Docker Cloud) to migrate my app to new environment, so i chose Docker Swarm CE. I am using Traefik as reverse proxy, and before migration it workked with segments just as per documentation, but for some reason it can not deal with those anymore in Swarm.
My service expose ports 3000 and 3001 for given path prefixes. Here is the part of docker-compose.yml for problematic service:
my-service:
image: my-service-image
deploy:
restart_policy:
condition: on-failure
labels:
traefik.port: 80
traefik.serviceapi.backend: api
traefik.serviceapi.frontend.entryPoints: "http,https"
traefik.serviceapi.frontend.rule: "PathPrefixStrip:/service/api"
traefik.serviceapi.port: 3000
traefik.servicesocket.backend: socket
traefik.servicesocket.frontend.entryPoints: "http,https,ws,wss"
traefik.servicesocket.frontend.rule: "PathPrefixStrip:/service/socket"
traefik.servicesocket.port: 3001
but for some reason swarm does not recognise these traefik segments, or I am missing something.
Did anyone have same issue?
Thanks!
UPDATE:
traefik:
image: traefik
command:
- "--web"
- "--docker"
- "--docker.swarmMode"
- "--docker.watch"
- "--docker.domain=my-domain"
- "--defaultentrypoints=http,https"
- "--entrypoints=Name:http Address::80 Redirect.EntryPoint:https"
- "--entrypoints=Name:https Address::443 TLS"
- "--acme"
- "--acme.storage=/etc/traefik/acme/acme.json"
- "--acme.entryPoint=https"
- "--acme.domains=my-domain"
- "--acme.httpChallenge.entryPoint=http"
- "--acme.email=email"
- "--logLevel=DEBUG"
deploy:
restart_policy:
condition: on-failure
ports:
- 80:80
- 443:443
- 8080:8080
volumes:
- ./var/run/docker.sock:/var/run/docker.sock
- ./traefik/acme/acme.json:/etc/traefik/acme/acme.json
I have more than 10 services working properly, only issue is that I cannot reach my-service endpoints, seems that swarm do not recognize traefik segments.
I found solution, so it might be helpful to someone:
for Docker Swarm you must set traefik.port, EXCEPT you are using segments - in this case you remove traefik.port and just set up ports of your service. In my case i just had to remove traefik.port: 80, and also both .backend's, traefik will create it's own.

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

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>

Resources