I'm running minio using its official docker-compose file which creates 4 services (containers): minio1,minio2,minio3,minio4. Traefik treats them as 4 unique services, but in reality, they should be treated as a single backend, that is, I want Traefik to generate 1 frontend an 1 backend (with 4 servers) for minio.
I tried putting them into a single group(servicefabric.groupname) but to no avail.
I have the following labels set for each minio service:
labels:
- "traefik.servicefabric.groupname=minio"
- "traefik.basic.frontend.rule=Host:foo.bar.com"
- "traefik.weight=10" # 10,20,30,40 incremented per service
- "traefik.frontend.rule=Host:traefik"
- "traefik.port=9000"
container_name: minio*
Is there any way to achieve this?
#Riverman
I had the same issue as you and I solved it by playing around as it's not fully documented in Traefik documentation. What you need to do is specify the traefik.backend value for all the services to be the same name and set traefik.frontend.backend to that traefik.backend value. You can't use the service piece for this. Below is an example.
services:
minio01:
image: minio/minio
hostname: minio01
restart: always
volumes:
- minio01-data:/export
networks:
- minio
- traefik
command: server http://minio01/export http://minio02/export
labels:
- 'traefik.enable=true'
- 'traefik.docker.network=traefik'
- 'traefik.frontend.rule=Host:minio.local'
- 'traefik.frontend.backend=minio'
- 'traefik.port=9000'
- 'traefik.protocol=http'
- 'traefik.backend=minio'
minio02:
image: minio/minio
hostname: minio02
restart: always
volumes:
- minio02-data:/export
networks:
- minio
- traefik
command: server http://minio01/export http://minio02/export
labels:
- 'traefik.enable=true'
- 'traefik.docker.network=traefik'
- 'traefik.frontend.rule=Host:minio.local'
- 'traefik.frontend.backend=minio'
- 'traefik.port=9000'
- 'traefik.protocol=http'
- 'traefik.backend=minio'
All minio services have to have the same frontend rule and the same backend name.
labels:
- "traefik.frontend.rule=Host:minio.${DOMAIN}"
- "traefik.backend=minio"
- "traefik.port=9000"
Also I think you misunderstood the meaning of "backend". A backend is a server to which Traefik route traffic based on the frontend rules. Same as "upstream"/"location" in nginx.
Edit
As stated in the comment, this configuration creates multiple frontends all pointing to the same backend, although functional this looks ugly. A quick solution is to just have one service with ‘frontend’ but if that service goes down, the frontend will be gone too.
A better way to do this is to set it in the config file, traefik.toml:
[frontends]
[frontends.frontend1]
backend = "minio"
[frontends.frontend1.minio]
rule = "Host: minio.${DOMAIN}”
Related
I am trying to follow the community documentation on mailcow dockerized and I am using Traefik as my load balancer.
I have successfully obtained a SSL certificate and the certdump is working as expected when I check the logs.
The issue I have having is that the nginx-mailcow container is not receiving the requests when I visit mail.example.com. My Traefik logs show this:
level=error msg="entryPoint \"secure\" doesn't exist" routerName=moo#docker entryPointName=secure
level=error msg="no valid entryPoint for this router" routerName=moo#docker
My docker-compose.override.yml looks like this (not much different to the community documentation):
version: '2.1'
services:
nginx-mailcow:
networks:
traefik:
web:
labels:
- traefik.enable=true
- traefik.http.routers.moo.rule=Host(`${MAILCOW_HOSTNAME}`)
- traefik.http.routers.moo.tls=true
- traefik.http.routers.moo.tls.certresolver=godaddy
- traefik.http.routers.moo.middlewares=redirect#file
- traefik.http.routers.moo.service=nginx-mailcow
- traefik.http.services.moo.loadBalancer.passHostHeader=true
- traefik.http.middlewares.https-redirect.redirectscheme.scheme=https
- traefik.http.middlewares.https-redirect.headers.customrequestheaders.X-Forwarded-Proto=https
- traefik.http.routers.moo.middlewares=https-redirect
- traefik.http.services.moo.loadbalancer.server.port=80
- traefik.http.routers.moo.entrypoints=secure
- traefik.docker.network=web
certdumper:
image: humenius/traefik-certs-dumper
container_name: traefik_certdumper
network_mode: none
volumes:
- acme:/traefik:ro
- ./data/assets/ssl/:/output:rw
environment:
- DOMAIN=${MAILCOW_HOSTNAME}
networks:
traefik:
external: true
web:
external: true
volumes:
acme:
name: "traefik_acme"
Can anyone see what I am doing wrong?
I have also tried with only:
labels:
- traefik.enable=true
- traefik.http.routers.moo.rule=Host(`${MAILCOW_HOSTNAME}`)
- traefik.http.routers.moo.tls=true
- traefik.http.routers.moo.tls.certresolver=godaddy
- traefik.http.services.moo.loadbalancer.server.port=80
- traefik.http.routers.moo.entrypoints=secure
- traefik.docker.network=web
This still did not work.
When you define a name for a service, you must use the same name in your service configuration, like this:
traefik.http.routers.moo.service=nginx-mailcow
traefik.http.services.moonginx-mailcow.loadBalancer.passHostHeader=true
The loadBalancer.servers (notice the s in servers) doesn't have a port key, only url:
traefik.http.services.moo.loadbalancer.server.port=80
traefik.http.services.nginx-mailcow.loadbalancer.servers.url=['http://nginx-mailcow:80']
But as you are using defaults, you can omit all of the above =)
One more thing, I don't know how your Traefik container is configured but if your Traefik is running with a defined traefik network (internal) and a web network (public), you should use the traefik network in your Mailcow container as you want to route all external traffic through Traefik.
traefik.docker.network=web
labels:
- traefik.enable=true
- traefik.http.routers.moo.rule=Host(`${MAILCOW_HOSTNAME}`)
- traefik.http.routers.moo.tls=true
- traefik.http.routers.moo.tls.certresolver=godaddy
- traefik.http.routers.moo.middlewares=redirect#file
- traefik.http.middlewares.https-redirect.redirectscheme.scheme=https
- traefik.http.middlewares.https-redirect.headers.customrequestheaders.X-Forwarded-Proto=https
- traefik.http.routers.moo.middlewares=https-redirect
- traefik.http.routers.moo.entrypoints=secure
- traefik.docker.network=traefik
#30daysofstackoverflow
Is there any way to set traefik.http.services name in docker-compose labels?
Lets say i have simple docker-compose.yml:
version: '3.4'
services:
traefik:
image: "traefik:v2.4.2"
command:
- --log.level=warning
- --api.insecure=true
- --api.dashboard=true
- --providers.docker=true
- --providers.docker.exposedbydefault=false
- --entrypoints.web.address=:80
ports:
- "80:80"
volumes:
- "/var/run/docker.sock:/var/run/docker.sock:ro"
labels:
- traefik.enable=true
# Dashboard
- traefik.http.routers.traefik.rule=Host(`traefik.localhost`)
# this is interesting - traefik is naming his api service somehow
- traefik.http.routers.traefik.service=api#internal
- traefik.http.services.traefik.loadbalancer.server.port=8080
whoami:
image: "traefik/whoami"
labels:
- traefik.enable=true
- traefik.http.routers.webwho.rule=Host(`who.localhost`)
This works great, after docker-compose up i can see the dashboard at http://traefik.localhost and "whoami" at http://who.localhost
The problem is the name of 'whoami' traefik service - it is something like whoami-{name_of_project} which is problem when i want to reference it in other label.
For example, i want to use new 'foo' docker service as 404.html provider (in this example i will use traefik/whoami image, which is silly, but hey, this is only example ;) )
I do that by using low priority "catch all" router:
version: '3.4'
services:
traefik:
image: "traefik:v2.4.2"
command:
- --log.level=warning
- --api.insecure=true
- --api.dashboard=true
- --api.debug=true
- --providers.docker=true
- --providers.docker.exposedbydefault=false
- --entrypoints.web.address=:80
ports:
- "80:80"
volumes:
- "/var/run/docker.sock:/var/run/docker.sock:ro"
labels:
- traefik.enable=true
# Dashboard
- traefik.http.routers.traefik.rule=Host(`traefik.localhost`)
# this is interesting - traefik is naming his api service somehow
- traefik.http.routers.traefik.service=api#internal
- traefik.http.services.traefik.loadbalancer.server.port=8080
whoami:
image: "traefik/whoami"
labels:
- traefik.enable=true
- traefik.http.routers.webwho.rule=Host(`who.localhost`)
foo:
image: "traefik/whoami"
labels:
- traefik.enable=true
- traefik.http.routers.error-router.rule=HostRegexp(`{host:.+}`)
- traefik.http.routers.error-router.priority=1
- traefik.http.routers.error-router.middlewares=error-pages-middleware
- traefik.http.middlewares.error-pages-middleware.errors.status=400-599
# nope!
# actual name of this service (as seen in traefik dashboard) is something like 'foo-test'
# and this will not work.
# (btw, there is very clear Error Message in traefik console about service foo does not exists,
# making debugging pleasant experience :) Thank you Traefik!)
- traefik.http.middlewares.error-pages-middleware.errors.service=foo
- traefik.http.middlewares.error-pages-middleware.errors.query=/{status}.html
but i have no idea how to set name of traefik service so i can reference it as value of the traefik.http.middlewares.error-pages-middleware.errors.service=??? label - service name foo-test isnt static (that 'test' is name of my directory which contains docker-compose.yml) and it keep changing from time to time (especially when used with visual studio .dcproj)
So - is there any way to set name of service?
What did i try:
Google & doc. Nope, but maybe because i dont know what to ask.
Setting container_name: foo does not help at all.
Interestlingly, if i add label - traefik.http.services.foo.loadbalancer.server.port=80 it automagically name the traefik service as foo which is exactly what i want and everything works. But this feels like "Plan B" because i dont want to set port, i want to set the name of the service.
using traefic dynamic configuration
[http.services]
[http.services.foo.loadBalancer]
[[http.services.foo.loadBalancer.servers]]
url = "http://foo:80/"
should work (i didnt tested it) -- but again, i dont want to set whole url, i want to set the name of service...
Looks like (at least in v2.4) there isnt any other way than
labels:
- traefik.http.services.<<name_of_service>>.loadbalancer.server.port=80
AFAIK even in the documentation, there is only one mention:
labels:
- "traefik.http.routers.myproxy.rule=Host(`example.net`)"
# service myservice gets automatically assigned to router myproxy
- "traefik.http.services.myservice.loadbalancer.server.port=80"
(source: https://doc.traefik.io/traefik/routing/providers/docker/ )
I am trying to host a few different websites on a single Raspberry Pi using Docker. I was told that I would need to use something like Traefik to route everything properly.
I tried using the Docker Basic Example under User Guides in their documentation as a test. I followed along with the example and created the docker-compose.yml file and copied in the example from the docs:
version: "3.3"
services:
traefik:
image: "traefik:v2.2"
container_name: "traefik"
command:
# - "--log.level=DEBUG"
- "--api.insecure=true"
- "--providers.docker=true"
- "--providers.docker.exposedbydefault=false"
- "--entrypoints.web.address=:80"
ports:
- "80:80"
- "8080:8080"
volumes:
- "/var/run/docker.sock:/var/run/docker.sock:ro"
whoami:
image: "containous/whoami"
container_name: "simple-service"
labels:
- "traefik.enable=true"
- "traefik.http.routers.whoami.rule=Host(`whoami.localhost`)"
- "traefik.http.routers.whoami.entrypoints=web"
Using this example going to the devices local IP I recieve a page that simply says:
404 Page not found
I've tried changing the Traefik container image version, and editing the example with my relevant information as well as recreating the example on another host and still I receive the above 404.
Am I doing something incorrect with Traefik to receive this 404?
In the user guide you have mentioned, there is this note:
Replace whoami.localhost by your own domain within the traefik.http.routers.whoami.rule label of the whoami service.
So, after you replace whoami.localhost with you local IP, you should be able to see whoami service responding correctly.
Suppose I have two web service say they are w1 and w2 which are deployed by docker-compose.
Now I want to create multiple container for each of them, and create a load balancer in front of them which can make the services accessed by this:
http://localhost:8880 //for service w1
http://localhost:8888 //for service w2
I have searched, and I got dockercloud-haproxy and nginx-proxy.
However, the former is deprecated, and the later have to be used with hostname to distinguish different service.
It is kind of complicated for set different hosts especially in development environment.
Then I found traefik. Seems like more configurable. This is the config file I used:
version: "3"
services:
w1:
image: jwilder/whoami
labels:
- "traefik.backend=whoami"
- "traefik.protocol=http"
- "traefik.port=8080"
- "traefik.frontend.entryPoints=http_8080"
w2:
build: . # a simple node server which use port 80
labels:
- "traefik.backend=node"
- "traefik.protocol=http"
- "traefik.port=80"
- "traefik.frontend.entryPoints=http_80"
lb:
image: traefik
command: "--docker \
--logLevel=DEBUG \
--entryPoints='Name:http_80 Address::80' \
--entryPoints='Name:http_8080 Address::8080'"
ports:
- 8880:80
- 8888:8080
volumes:
- /var/run/docker.sock:/var/run/docker.sock
While it still can not meet my requirement.
Is this possible or any other alternative solution?
You need to add the matcher -"traefik.frontend.rule=PathPrefixStrip:/" under w1 and w2. Otherwise it defaults to Host:w1.project_name.
Also, I believe jwilder/whoami uses the port 8000 instead of 8080, so change - "traefik.port=8080" to - "traefik.port=8000"
Objective
I have a server running Rancher (Docker). In that server, I have several un-related stacks.
I want to make Traefik the main interaction point of that stack. And make it load balance / proxy the requests to different containers based on the path.
I want to make it send the traffic for /api to the backend server service. And send the traffic for / to the frontendservice.
Current state
Here's a slimmed down version of my docker-compose.yml showing only the relevant services:
version: '2'
services:
server:
image: server
labels:
- "traefik.frontend.rule=PathPrefix:/api"
- "traefik.enable=true"
- "traefik.port=80"
frontend:
image: frontend
labels:
- "traefik.frontend.rule=PathPrefix:/"
- "traefik.enable=true"
- "traefik.port=80"
proxy:
image: traefik:v1.4
command: --web --accessLog --rancher --rancher.exposedbydefault=false --rancher.metadata=true
volumes:
- /dev/null:/traefik.toml
Then using a Rancher load balancer that listens to the public ports, I redirect requests to app1.example.com to my proxy service. Then it takes the requests and re-directs traffic to each of the two containers based on the path.
I also redirect traffic to traefik.app1.example.com to the same proxy service, to the port 8080 to access the web UI.
If I have only one stack, it works.
The problem
If I add another stack (or if I duplicate that stack) and have more services with Traefik labels, the proxy from app1 will read the labels from the services in app2 and any other stack that declares Traefik labels.
Then, in the web UI for the proxy in app1, I can see all the backends from all the different stacks. But the frontend rules get overwritten.
Question
Up to now, I've seen examples mostly of how to use Traefik as a unique global load balancer / proxy. I just realized that I assumed that I could also create isolated Traefik instances per stack, or a hierarchy of Traefik load balancers.
It seems to me like I'm missing some configuration or misunderstanding something.
But still, I have to ask, is it possible to have different isolated Traefik instances per stack and make them only listen and use the services in their own stack?
Is it possible with Rancher? Is it possible with any other Docker stack orchestrator (e.g. Swarm)?
If that's possible, what am I missing?
I think I found how to solve it.
It seems I can't make Traefik only use services in his own stack directly. But it seems I can use Traefik constraints and tags to achieve almost the same.
Here's my updated docker-compose.yml using constraints and tags:
version: '2'
services:
server:
image: server
labels:
- "traefik.frontend.rule=PathPrefix:/api"
- "traefik.enable=true"
- "traefik.port=80"
- "traefik.tags=app1.example.com"
frontend:
image: frontend
labels:
- "traefik.frontend.rule=PathPrefix:/"
- "traefik.enable=true"
- "traefik.port=80"
- "traefik.tags=app1.example.com"
proxy:
image: traefik:v1.4
command: --web --accessLog --constraints=tag==app1.example.com --rancher --rancher.exposedbydefault=false --rancher.metadata=true
volumes:
- /dev/null:/traefik.toml
It will only match services that have the Traefik tag app1.example.com. Those tags can be any string, but as I'm wanting to filter by a specific domain, I just used the domain I wanted to filter as the tag to use.
Also, notice that the tag is set in the services with a label traefik.tag.
If you are interested in Traefik v2 solution for this, you can use --providers.docker.constraints option to achieve the same result.
So, the basic example could be:
services:
traefik:
image: traefik:v2.3
command:
- "--providers.docker=true"
- "--providers.docker.exposedbydefault=false"
- "--providers.docker.constraints=Label(`custom.label`,`custom-value`)"
volumes:
- "/var/run/docker.sock:/var/run/docker.sock:ro"
custom_service:
image: ...
labels:
- "traefik.enable=true"
- "custom.label=custom-value"
Docs