Docker Swarm - Requests fail to reach a service on a different node - docker

I've setup a Docker Swarm with Traefik v2 as the reverse proxy, and have been able to access the dashboard with no issues.
I am having an issue where I cannot get a response from any service that runs on a different node to the node Traefik is running on. I'm been testing and researching and presuming it's a network issue of some type.
I've done some quick testing with a empty Nginx image and was able to deploy another stack and get a response if the image was on the same node. Other stacks on the swarm which deploy across multiple nodes (but not including the Traefik node) are able to communicate to each other without issues).
Here is the test stack to provide some context of what I was using.
version: '3.8'
services:
test:
image: nginx:latest
deploy:
replicas: 1
placement:
constraints:
- node.role==worker
labels:
- "traefik.enable=true"
- "traefik.docker.network=uccser-dev-public"
- "traefik.http.services.test.loadbalancer.server.port=80"
- "traefik.http.routers.test.service=test"
- "traefik.http.routers.test.rule=Host(`TEST DOMAIN`) && PathPrefix(`/test`)"
- "traefik.http.routers.test.entryPoints=web"
networks:
- uccser-dev-public
networks:
uccser-dev-public:
external: true
The uccser-dev-public network is an overlay network across all nodes, with no encryption.
If I added a constraint to specify the Traefik node, then the requests worked with no issues. However, if I switched it to a different node, I get the Traefik 404 page.
The Traefik dashboard is showing it sees the service.
However the access logs show the following:
proxy_traefik.1.6fbx58k4n3fj#SWARM_NODE | IP_ADDRESS - - [21/Jul/2021:09:03:02 +0000] "GET / HTTP/2.0" - - "-" "-" 1430 "-" "-" 0ms
It's just blank, and I don't know where to proceed from here. The normal log shows no errors that I can see.
Traefik stack file:
version: '3.8'
x-default-opts:
&default-opts
logging:
options:
max-size: '1m'
max-file: '3'
services:
# Custom proxy to secure docker socket for Traefik
docker-socket:
<<: *default-opts
image: tecnativa/docker-socket-proxy
networks:
- traefik-docker
volumes:
- /var/run/docker.sock:/var/run/docker.sock
environment:
NETWORKS: 1
SERVICES: 1
SWARM: 1
TASKS: 1
deploy:
placement:
constraints:
- node.role == manager
# Reverse proxy for handling requests
traefik:
<<: *default-opts
image: traefik:2.4.11
networks:
- uccser-dev-public
- traefik-docker
volumes:
- traefik-public-certificates:/etc/traefik/acme/
ports:
- target: 80 # HTTP
published: 80
protocol: tcp
mode: host
- target: 443 # HTTPS
published: 443
protocol: tcp
mode: host
command:
# Docker
- --providers.docker
- --providers.docker.swarmmode
- --providers.docker.endpoint=tcp://docker-socket:2375
- --providers.docker.exposedByDefault=false
- --providers.docker.network=uccser-dev-public
- --providers.docker.watch
- --api
- --api.dashboard
- --entryPoints.web.address=:80
- --entryPoints.websecure.address=:443
- --log.level=DEBUG
- --global.sendAnonymousUsage=false
deploy:
placement:
constraints:
- node.role==worker
# Dynamic Configuration
labels:
- "traefik.enable=true"
- "traefik.http.routers.dashboard.rule=Host(`SWARM_NODE`) && (PathPrefix(`/api`) || PathPrefix(`/dashboard`))"
- "traefik.http.routers.dashboard.service=api#internal"
- "traefik.http.services.dummy-svc.loadbalancer.server.port=9999" # Dummy service for Swarm port detection. The port can be any valid integer value.
volumes:
traefik-public-certificates: {}
networks:
# This network is used by other services
# to connect to the proxy.
uccser-dev-public:
external: true
# This network is used for Traefik to talk to
# the Docker socket.
traefik-docker:
driver: overlay
driver_opts:
encrypted: 'true'
Any ideas?

Further testing showed other services were working on different nodes, so figured it must be an issue with my application. Turns out my Django application still had a bunch of settings configured for it's previous hosting location regarding HTTPS. As it wasn't passing the required settings it had denied the requests before the were processed. I needed to have the logging level for gunicorn (WSGI) lower to see more information too.
In summary, Traefik and Swarm were fine.

Another reason for this can be that Docker Swarm ports haven't been opened on all of the nodes. If you're using UFW that means running the following on every machine participating in the swarm:
ufw allow 2377/tcp
ufw allow 7946/tcp
ufw allow 7946/udp
ufw allow 4789/udp

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.

Docker container communication and security

Lets say I have 2 nodes(1 Manager and 1 Worker) and the following compose
services:
nginx:
image: nginx
ports:
- 443:443
deploy:
placement:
constraints:
- node.role==manager
networks:
- somenet
app:
image: someapp
deploy:
mode: global
networks:
- somenet
networks:
default:
driver: overlay
driver_opts:
encrypted: "true"
Where NGINX exposes the App to the outside world through HTTPS and forwards the request to one of the app replicas as a reverse proxy.
Should the communication between NGINX and App through HTTPS/SSL?
Is there any way to sniff the packets inside this overlay network?
Is it possible to gain access to any of the containers beside compromising the machine itself?

Bad gateway as Traefik fails to point to a new service instance after a failed health check

I have a Docker Swarm web application that can deploy fine and can be reached from outside by a browser.
But it was not showing the client IP address to the HTTP service.
So I decided to add a Traefik service to the Docker Compose file to expose the client IP to the HTTP service.
I use a mode: host and a driver: overlay for this reason.
The complete configuration is described in two Docker Compose files that I run in sequence.
First I run the docker stack deploy --compose-file docker-compose-dev.yml common command on the file:
version: "3.9"
services:
traefik:
image: traefik:v2.5
networks:
common:
ports:
- target: 80
published: 80
mode: host
- target: 443
published: 443
mode: host
command:
- "--providers.docker.endpoint=unix:///var/run/docker.sock"
- "--providers.docker.swarmMode=true"
- "--providers.docker.exposedbydefault=false"
- "--providers.docker.network=common"
- "--entrypoints.web.address=:80"
# Set a debug level custom log file
- "--log.level=DEBUG"
- "--log.filePath=/var/log/traefik.log"
- "--accessLog.filePath=/var/log/access.log"
# Enable the Traefik dashboard
- "--api.dashboard=true"
deploy:
placement:
constraints:
- node.role == manager
labels:
# Expose the Traefik dashboard
- "traefik.enable=true"
- "traefik.http.routers.dashboard.service=api#internal"
- "traefik.http.services.traefik.loadbalancer.server.port=888" # A port number required by Docker Swarm but not being used in fact
- "traefik.http.routers.dashboard.rule=Host(`traefik.learnintouch.com`)"
- "traefik.http.routers.traefik.entrypoints=web"
# Basic HTTP authentication to secure the dashboard access
- "traefik.http.routers.traefik.middlewares=traefik-auth"
- "traefik.http.middlewares.traefik-auth.basicauth.users=stephane:$$apr1$$m72sBfSg$$7.NRvy75AZXAMtH3C2YTz/"
volumes:
# So that Traefik can listen to the Docker events
- "/var/run/docker.sock:/var/run/docker.sock:ro"
- "~/dev/docker/projects/common/volumes/logs/traefik.service.log:/var/log/traefik.log"
- "~/dev/docker/projects/common/volumes/logs/traefik.access.log:/var/log/access.log"
networks:
common:
name: common
driver: overlay
Then I run the docker stack deploy --compose-file docker-compose.yml www_learnintouch command on the file:
version: "3.9"
services:
www:
image: localhost:5000/www.learnintouch
networks:
common:
volumes:
- "~/dev/docker/projects/learnintouch/volumes/www.learnintouch/account/data:/usr/local/learnintouch/www/learnintouch.com/account/data"
- "~/dev/docker/projects/learnintouch/volumes/www.learnintouch/account/backup:/usr/local/learnintouch/www/learnintouch.com/account/backup"
- "~/dev/docker/projects/learnintouch/volumes/engine:/usr/local/learnintouch/engine"
- "~/dev/docker/projects/common/volumes/letsencrypt/certbot/conf/live/thalasoft.com:/usr/local/learnintouch/letsencrypt"
- "~/dev/docker/projects/common/volumes/logs:/usr/local/apache/logs"
- "~/dev/docker/projects/common/volumes/logs:/usr/local/learnintouch/logs"
user: "${CURRENT_UID}:${CURRENT_GID}"
deploy:
replicas: 1
restart_policy:
condition: any
delay: 5s
max_attempts: 3
window: 10s
labels:
- "traefik.enable=true"
- "traefik.http.routers.www.rule=Host(`dev.learnintouch.com`)"
- "traefik.http.routers.www.entrypoints=web"
- "traefik.http.services.www.loadbalancer.server.port=80"
healthcheck:
test: curl --fail http://127.0.0.1:80/engine/ping.php || exit 1
interval: 10s
timeout: 3s
retries: 3
networks:
common:
external: true
name: common
Here are the networks:
stephane#stephane-pc:~$ docker network ls
NETWORK ID NAME DRIVER SCOPE
6beaf0c3a518 bridge bridge local
ouffqdmdesuy common overlay swarm
17et43c5tuf0 docker-registry_default overlay swarm
1ae825c8c821 docker_gwbridge bridge local
7e6b4b7733ca host host local
2ui8s1yomngt ingress overlay swarm
460aad21ada9 none null local
tc846a14ftz5 verdaccio overlay swarm
The docker ps command shows that all containers are healthy.
But a request to http://dev.learnintouch.com/ responds with a Bad Gateway error MOST of the times except when rarely it does not and the web application displays fine.
As a side note, I would like any unhealthy service to be restarted and seen by Traefik. Just like Docker Swarm restarts unhealthy services I would like Traefik to restart unhealthy services too.
The service log:
{"level":"debug","msg":"Configuration received from provider docker: {\"http\":{\"routers\":{\"dashboard\":{\"service\":\"api#internal\",\"rule\":\"Host(`traefik.learnintouch.com`)\"},\"nodejs\":{\"entryPoints\":[\"web\"],\"service\":\"nodejs\",\"rule\":\"Host(`dev.learnintouch.com`)\"},\"traefik\":{\"entryPoints\":[\"web\"],\"middlewares\":[\"traefik-auth\"],\"service\":\"traefik\",\"rule\":\"Host(`common-reverse-proxy`)\"},\"www\":{\"entryPoints\":[\"web\"],\"service\":\"www\",\"rule\":\"Host(`dev.learnintouch.com`)\"}},\"services\":{\"nodejs\":{\"loadBalancer\":{\"servers\":[{\"url\":\"http://10.0.14.17:9001\"}],\"passHostHeader\":true}},\"traefik\":{\"loadBalancer\":{\"servers\":[{\"url\":\"http://10.0.14.8:888\"}],\"passHostHeader\":true}},\"www\":{\"loadBalancer\":{\"servers\":[{\"url\":\"http://10.0.14.18:80\"}],\"passHostHeader\":true}}},\"middlewares\":{\"traefik-auth\":{\"basicAuth\":{\"users\":[\"stephane:$apr1$m72sBfSg$7.NRvy75AZXAMtH3C2YTz/\"]}}}},\"tcp\":{},\"udp\":{}}","providerName":"docker","time":"2021-07-04T10:25:01Z"}
{"level":"info","msg":"Skipping same configuration","providerName":"docker","time":"2021-07-04T10:25:01Z"}
I also tried to have Docker Swarm doing the load balancing with adding the - "traefik.docker.lbswarm=true" property to my service but the Bad Gateway error remained.
I also restarted the Swarm manager:
docker swarm leave --force
docker swarm init
but the Bad Gateway error remained.
I also added the two labels:
- "traefik.backend.loadbalancer.sticky=true"
- "traefik.backend.loadbalancer.stickiness=true"
but the Bad Gateway error remained.
It feels like Traefik hits the web service before that one has a chance to be ready. Would there be any way to tell Traefik to wait a given amount of seconds before hitting the web service ?
UPDATE: I could find, not a solution, but a workaround the issue, by splitting the first above common stack file into two files, with one dedicated to the traefik stack. I could then start the 3 stacks in the following order: common, www_learnintouch and traefik
The important thing was to start the traefik stack after the others. If I then had to remove and start again the www_learnintouch stack for example, then I had to follow this by removing and starting again the traefik stack.
Also, if I removed the container of www_learnintouch with a docker rm -f CONTAINER_ID command then I also needed to remove and start again the traefik stack.

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 2.0 behind docker swarm not working

So, I'm trying to use Traefik to load-balance my web apps via docker swarm.
However, I already tried many configurations but somehow not works. I already read the documentation and read some articles in the internet. Unfortunately, many articles references traefik 1.x instead traefik 2.0.
Here is my docker-stack.yml for traefik
version: '3.7'
services:
traefik:
image: traefik:2.0
deploy:
mode: global
placement:
constraints:
- node.role == manager
restart_policy:
condition: on-failure
labels:
- traefik.docker.network=load_balancer
configs:
- source: traefik
target: /etc/traefik/traefik.yml
ports:
- 80:80
volumes:
- /var/run/docker.sock:/var/run/docker.sock
networks:
- load_balancer
configs:
traefik:
file: ./traefik.yml
networks:
load_balancer:
external: true
name: load_balancer
whoami.yml (for testing purpose)
version: '3.7'
services:
whoami:
image: containous/whoami
deploy:
labels:
- traefik.enable=true
- traefik.docker.network=load_balancer
- traefik.http.routers.whoami.rule=Host(`whoami.docker.localhost`)
networks:
- load_balancer
networks:
load_balancer:
external: true
name: load_balancer
My traefik.yml
log:
level: DEBUG
api:
insecure: true
providers:
docker:
exposedByDefault: false
swarmMode: true
watch: true
docker network ls
hxjw9rytw3od load_balancer overlay swarm
curl -H Host:whoami.docker.localhost http://127.0.0.1
404 page not found
Maybe you have to add entrypoints declaration in your config: https://docs.traefik.io/routing/entrypoints/
I hope is not too late to answer this. I've found the solution.
First, you can either use traefik.yml for configuration or use traefik cli flags in docker-compose command field.
Here is the working approach if you use traefik.yml as your main configuration.
It is recommended to use directory over file.
traefik.yml
log:
level: DEBUG
api:
insecure: true
# This is required
entryPoints:
web:
address: ':80'
websecure:
address: ':443'
providers:
file: # Required, if you use traefik.yml as your main configuration
directory: /etc/traefik
watch: true
docker:
exposedByDefault: false
swarmMode: true
watch: true
Working approach if you use traefik cli flags
docker-compose.stack.yml
version: '3.7'
services:
traefik:
image: traefik:2.0
deploy:
mode: global
placement:
constraints:
- node.role == manager
restart_policy:
condition: on-failure
command:
- --log.level=DEBUG
- --api.insecure=true
- --ping=true
- --entrypoints.web.address=:80
- --entrypoints.websecure.address=:443
- --providers.docker.swarmmode=true
- --providers.docker.exposedbydefault=false
- --providers.docker.network=load_balancer
- --providers.docker.watch=true
ports:
- 80:80
volumes:
- /var/run/docker.sock:/var/run/docker.sock
networks:
- load_balancer
networks:
load_balancer:
external: true
name: load_balancer
whoami.yml (for testing purpose)
version: '3.7'
services:
whoami:
image: containous/whoami
deploy:
labels:
- traefik.enable=true
- traefik.docker.network=load_balancer
- traefik.http.routers.whoami.entrypoints=web
- traefik.http.routers.whoami.rule=Host(`whoami.docker.localhost`)
- traefik.http.services.whoami.loadbalancer.server.port=80
networks:
- load_balancer
networks:
load_balancer:
external: true
name: load_balancer
Test via curl
curl -H Host:whoami.docker.localhost 127.0.0.1
I can suggest you to Not use traefik.yml but to use the cli args to configure your instance.
You can make it like this :
version: "3.7"
services:
ingress:
image: traefik:v2.0
networks:
- ingress-net
ports:
- "80:80"
- "443:443"
# TCP Port if needed for any service you have
- "60000:60000"
command:
### ###
# Traefik Global Configuration #
### ###
# Enable DEBUG logs
- "--log.level=DEBUG" # DEBUG, INFO, etc...
- "--ping=true"
# Enable api access without authentification (only GET route so it only possible to get IPs)
- "--api.insecure=true" # You can insecure here, because It accessible only in the container if you didn't open the port.
# Set the provider to Docker
- "--providers.docker=true"
# Set the docker network
- "--providers.docker.network=ingress-net"
# Set to docker swarm cluster
- "--providers.docker.swarmMode=true"
# If False : Do not expose containers to the web by default
- "--providers.docker.exposedByDefault=false"
# Default rule to service-name.example.com
- "--providers.docker.defaultRule=Host(`{{ trimPrefix `/` .Name }}.example.com`)"
# Default http port
- "--entrypoints.http.address=:80"
# Default https port
- "--entrypoints.https.address=:443"
# Enable let's encrypt
- "--certificatesResolvers.certbot=true"
- "--certificatesResolvers.certbot.acme.httpChallenge=true"
- "--certificatesResolvers.certbot.acme.httpChallenge.entrypoint=http"
- "--certificatesResolvers.certbot.acme.email=admin#example.com"
- "--certificatesResolvers.certbot.acme.storage=/letsencrypt/acme.json"
# TCP Entrypoint if needed
- "--entrypoints.tcpendpointname.address=:60000"
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- ./acme.json:/letsencrypt/acme.json
deploy:
replicas: 1
labels:
### ###
# Traefik Dashboard #
### ###
# Enable this endpoint
- traefik.enable=true
##
# Http
#
# Set the service route
- traefik.http.routers.ingress_http.rule=Host(`ingress.example.com`)
# Set the entrypoint (http or https)
- traefik.http.routers.ingress_http.entrypoints=http
# Rule to redirect to http to https
- traefik.http.middlewares.ingress-https-redirect.redirectscheme.scheme=https
# Enable Https redirection
- traefik.http.routers.ingress_http.middlewares=ingress-https-redirect#docker
#
##
##
# Https
#
- traefik.http.routers.ingress_https.rule=Host(`ingress.example.com`)
# Set the entrypoint (http or https)
- traefik.http.routers.ingress_https.entrypoints=https
# Enable Let's encrypt auto certificat creation
- traefik.http.routers.ingress_https.tls.certresolver=certbot
# Enable authentification
- traefik.http.routers.ingress_https.middlewares=ingress-auth#
# Uncommant this to enable basic authentification
# - traefik.http.middlewares.ingress-auth.basicauth.users=admin:$$this$$is$$encrypted$$password
#
##
##
# TCP Endpoint
#
# Set the service route
- "traefik.tcp.routers.tcpendpointname.rule=HostSNI(`*`)"
# Here you can set the host uri if you use tls only.
# - "traefik.tcp.routers.tcpendpointname.rule=HostSNI(`tcp.example.com`)"
# - "traefik.tcp.routers.tcpendpointname.tls=true"
# Set the entrypoin
- "traefik.tcp.routers.tcpendpointname.entrypoints=tcpendpointname"
#
##
##
# Service
#
# Set the service port
- traefik.http.services.ingress.loadbalancer.server.port=8080
#
##
placement:
constraints:
- node.role == manager
networks:
ingress-net:
external: true
I hope this will Help you.
You can use the same labels for any other containers, that work with the same logic.
Since you've got a 404 page not found Traefik seems to be available.
However, when using curl to fetch http://127.0.0.1 this IP address is going to be content of request's Host header field. This in turn is used by Traefik for routing the request. Since your whoami service is meant to match requests for Host whoami.docker.localhost this given response of Traefik is just fine.
Have you tried fetching http://whoami.docker.localhost instead? You might need to inject this hostname into hosts /etc/hosts files prior to testing with curl.
127.0.0.1 whoami.docker.localhost
Optionally, you can try manual HTTP request with a tool like netcat (sometimes available as nc):
# netcat 127.0.0.1 80
GET / HTTP/1.0
Host: whoami.docker.localhost
You need to press Enter twice after entering second line of request as required by HTTP.
Port Detection
Docker Swarm does not provide any port detection information to Traefik.
Therefore you must specify the port to use for communication by using the label traefik.http.services.<service_name>.loadbalancer.server.port (Check the reference for this label in the routing section for Docker).
Traefik's service discovery with Docker requires container labels instead of image labels (check traefik's quickstart).
The following minimal working example works on docker swarm:
version: '3.7'
services:
traefik:
image: traefik:2.0
command: --providers.docker
ports:
- 80:80
volumes:
- /var/run/docker.sock:/var/run/docker.sock
whoami:
image: containous/whoami
labels: # defining a container label instead of an image label
- "traefik.http.routers.whoami.rule=Host(`whoami.docker.localhost`)"

Resources