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.
Related
I am using Traefik in my VPS to route the traffic to my websites, after hours of messing around with it I finally managed to get it working with https using Le's Encrypt.
Now, one thing that I need to do is be able to also access my website via plain http as this is a hobby project for older browsers and the only reason I added tls is because Firefox doesn't like my website without it.
The problem is that, with my current configuration, I can access my website via https normally but when I try it with plain http I get a 404 error.
Here's what my config on docker-compose looks like:
version: "3"
services:
traefik:
image: "traefik:v2.5"
container_name: "traefik"
command:
#- "--log.level=DEBUG"
- "--api.insecure=true"
- "--providers.docker=true"
- "--providers.docker.exposedbydefault=false"
- "--entrypoints.web.address=:80"
- "--entrypoints.websecure.address=:443"
- "--certificatesresolvers.teeresolver.acme.tlschallenge=true"
- "--certificatesresolvers.teeresolver.acme.email=me#gmail.com"
- "--certificatesresolvers.teeresolver.acme.storage=/letsencrypt/acme.json"
ports:
- "443:443"
- "80:80"
- "8080:8080"
volumes:
- "./letsencrypt:/letsencrypt"
- "/var/run/docker.sock:/var/run/docker.sock:ro"
networks:
- mywebsite
# [...]
mywebsite:
image: my-web-site/site
build:
context: ~/mywebsite-runner/_work/my-web-site-php/my-web-site-php
dockerfile: Dockerfile
volumes:
- ./tee-downloads:/var/www/build/downloads
- ./tee-contents:/var/www/build/contents
ports:
- "0.0.0.0:8001:80"
labels:
- "traefik.enable=true"
- "traefik.http.routers.themywebsite.rule=Host(`mywebsite.com`, `www.mywebsite.com`)"
- "traefik.http.routers.themywebsite.entrypoints=websecure,web"
- "traefik.http.routers.themywebsite.tls.certresolver=teeresolver"
networks:
- mywebsite
networks:
mywebsite:
I have been searching for a solution for hours but the only things I can find on google are configs to redirect http to https, which I can't do.
Does anyone know how to do that?
Thanks in advance for the help.
In traefik , each router defines a set of policies to apply depending of rules and entrypoints.
If you want 2 policies, one for http and one for https, you need to define 2 traefik routers :
mywebsite:
...
labels:
- "traefik.enable=true"
- "traefik.http.routers.themywebsite.entrypoints=websecure"
- "traefik.http.routers.themywebsite.tls.certresolver=teeresolver"
- "traefik.http.routers.themywebsite.rule=Host(`mywebsite.com`, `www.mywebsite.com`)"
- "traefik.http.routers.httpwebsite.entrypoints=web"
- "traefik.http.routers.httpwebsite.rule=Host(`mywebsite.com`, `www.mywebsite.com`)"
One called themywebsite
Another one called httpwebsite
As a result, you do not use a certresolver for httpwebsite router.
I'm starting to use treafix but I facing a wall. I'm trying to start with the basic docker example provided here : https://doc.traefik.io/traefik/user-guides/docker-compose/basic-example/
version: "3.8"
services:
traefik:
image: "traefik:v2.3"
container_name: "traefik"
command:
- "--log.level=DEBUG"
- "--accessLog"
- "--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: "traefik/whoami"
container_name: "simple-service"
labels:
- "traefik.enable=true"
- "traefik.http.routers.whoami.entrypoints=web"
- "traefik.http.routers.whoami.rule=Host('server.local')"
As I'm local, I've set up "server.local" in my hostfile to point to 127.0.0.1
However, when I run it with compose and try to access my server.local I only got a 404, not the whoami expected response. I don't see anything that jump to me as wrong within the logs but again, I'm starting in, the traefik area.
I'm using docker desktop on windows wityh WSL2 and running the compose inside an ubuntu WSL2 vm
I found my issue :
In the traefik rule, you should only use backtick (`) and not a single quote (') to define string litteral
so my :
- "traefik.http.routers.whoami.rule=Host('server.local')"
should be
- "traefik.http.routers.whoami.rule=Host(`server.local`)"
I wished the traefik documentation made this much more clear, especially in the default exemples ...
I'm following some tutorial link_to_tutorial about traefik 2.0 and docker, and I have docker-compose file which starts up two containers: traefik and my-app. The problem is when containers up and running, I am not able to browse to localhost:8082, as suggested by configuration, I always get "unable to connect" in browser.
docker-compose.yml :
version: "3.3"
services:
traefik:
image: "traefik:v2.0.1"
command:
- --entrypoints.web.address=:80
- --providers.docker
- --api.insecure
ports:
- "80:80"
- "8080:8080"
volumes:
- "/var/run/docker.sock:/var/run/docker.sock:ro"
my-app:
image: containous/whoami:v1.3.0
command:
# It tells whoami to start listening on 8082 instead of 80
- --port=8082
labels:
- "traefik.http.routers.my-app.rule=Host(`whoami.docker.localhost`)"
- "traefik.http.services.my-app.loadbalancer.server.port=8082"
However I am able to get localhost:8080 and traefik UI works well. As I understand all requests to "traefik" container normally should be redirected to "my-app":8082 container but it somehow fails. Help heeded.Thanks.
"traefik.http.routers.my-app.rule=Host(localhost,127.0.0.1)"
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}”
Is it possible to have a wildcard subdomain that does not include a specific subdomain?
*.mydomain.com OK
login.mydomain.com SKIP
I cannot access my login container when using a wildcard on my app container. Below is an image of what I am trying to accomplish. (the traffic logo should technically be between the list of routes and the containers)
The following configuration does not work if the rule HostRegexp:{subdomain:[a-z]+}.${HOST_DOMAIN} is included.
This configuration successfully works after removing the host regex for everything EXCEPT the wildcard subdomains.
services:
traefik:
image: traefik
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- .traefik.toml:/etc/traefik/traefik.toml:ro
ports:
- "80:80"
- "443:443"
api:
image: my-api-image
labels:
- "traefik.enable=true"
- "traefik.port=80"
- "traefik.frontend.rule=Host:app.${HOST_DOMAIN}; PathPrefix: /api"
app:
image: my-app-image
labels:
- "traefik.enable=true"
- "traefik.port=80"
- "traefik.frontend.rule=Host:app.${HOST_DOMAIN}"
- "traefik.frontend.rule=HostRegexp:{subdomain:[a-z]+}.${HOST_DOMAIN}" # this second rule overwrites the first rule and I am aware of that, I am just showing what rules i've tried :)
login:
image: my-login-image
labels:
- "traefik.enable=true"
- "traefik.port=80"
- "traefik.frontend.rule=Host:login.${HOST_DOMAIN}"
My problem is currently with the app container. I am getting a bad gateway if I have the following included as a frontend rule:
"traefik.frontend.rule=HostRegexp:{subdomain:[a-z]+}.${HOST_DOMAIN}"
I also tried leaving the above under app, and removing the following without any luck:
"traefik.frontend.rule=Host:app.${HOST_DOMAIN}"
Any suggestions or ideas would be appreciated. Thanks.
Edit:
Rewording this a bit.
So this is what worked for me:
version: '2'
services:
traefik:
image: traefik
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
# I removed your traefik.toml as you did not specify what is in it, so it's irrelevant
ports:
- "80:80"
- "443:443"
# Very helpful for debugging dashboard can be seen at http://localhost:8080 if the port is exposed
- "8080:8080"
labels:
# You don't want traefik trying to create proxy for itself
- "traefik.enable=false"
# Since we have no traefik.toml any longer, let's put the essentials on the command line
command: ["--api","--docker"]
app:
# this is my test image of a web server that dumps request back to the caller
image: andrewsav/talkback
# the hostname is a part of the dump, so let's specify something that we can relate to
hostname: "app"
labels:
# note that you want this frontened to match the last. otherwise it will match login.${HOST_DOMAIN}"
- "traefik.frontend.priority=1"
- "traefik.enable=true"
- "traefik.port=80"
- "traefik.frontend.rule=HostRegexp:{subdomain:[a-z]+}.${HOST_DOMAIN}"
api:
image: andrewsav/talkback
hostname: "api"
labels:
# this frontend needs to match before the one above
- "traefik.frontend.priority=2"
- "traefik.enable=true"
- "traefik.port=80"
- "traefik.frontend.rule=Host:app.${HOST_DOMAIN}; PathPrefix: /api"
login:
image: andrewsav/talkback
hostname: "login"
labels:
- "traefik.frontend.priority=3"
- "traefik.enable=true"
- "traefik.port=80"
- "traefik.frontend.rule=Host:login.${HOST_DOMAIN}"
A few notes:
Bad Gateway indicates that the endpoint you told traefik to talk to is not listening. Look at at the dashboard and find out which backend is used and double check that ip/port is correct.
You have to use priorities for matching order. Please refer to the documentation on how it works.