Traefik with multiple docker-compose.yml files - docker-compose

Hello traefik friends.
I just started to look into traefik. All tutorials show how to run one docker-compose.yml file with traefik togather with other containers. I most often have many separate docker-compose.yml files and very much would like to use them with traefik.
so here is my code for traefik container:
version: "3.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.websecure.address=:443"
- "--certificatesresolvers.myresolver.acme.tlschallenge=true"
#- "--certificatesresolvers.myresolver.acme.caserver=https://acme-staging-v02.api.letsencrypt.org/directory"
- "--certificatesresolvers.myresolver.acme.email=xxxxxxxxx#gmail.com"
- "--certificatesresolvers.myresolver.acme.storage=/letsencrypt/acme.json"
ports:
- "443:443"
- "8080:8080"
networks:
- "traefik"
- "external"
volumes:
- "./letsencrypt:/letsencrypt"
- "/var/run/docker.sock:/var/run/docker.sock:ro"
and the other exemplary docker-compose I would like to use with traefik:
version: '3.1'
services:
php:
image: php:7.4-apache
ports:
- 8081:80
volumes:
- ./php/www:/var/www/html/
labels:
- "traefik.enable=true"
- "traefik.http.routers.php.rule=host(`php.xxxxxx.com`)"
- "traefik.http.routers.php.entrypoints=websecure"
- "traefik.http.routers.php.tls.certresolver=myresolver"
unfortunately that doesnt seem to work (when I concat theese to files into one big docker-compose.yml file - it works fine. Could you point me in the right direction?

Traefik needs to be part of the networks for all the services it connects to. For me it works when I set network: host for Traefik. (And then you have to remove ports part.)
I do wonder how safe that is, I can't seem to access the admin interface from another machine, so that's good.

Each docker-compose.yml by default create its own network. So traefik from the traefik network can't access PHP server from some other "php-default" network.
see Compose Networking docs
We have to add the PHP server to the traefik network:
php/docker-compose.yml:
services:
php:
image: php:7.4-apache
# we need to tell the traefik what port is the container listening to
expose:
- 80
volumes:
- ./php/www:/var/www/html/
labels:
- "traefik.enable=true"
- "traefik.http.routers.php.rule=host(`php.xxxxxx.com`)"
- "traefik.http.routers.php.entrypoints=websecure"
- "traefik.http.routers.php.tls.certresolver=myresolver"
networks:
default:
name: traefik
external: true
OR if you want to have other networks
services:
php:
...
networks:
- traefik
...
networks:
traefik:
external: true
Note there is not defined port property, instead there is expose. The port exposes ports on the host, the expose act as mere documentation (see this Q) but the traefik read it.
And because of that, I think that in your traefik/docker-compose.yml the external network is unnecessary.

Related

Minio Buckets not working behind Traefik reverse-proxy

I have a minio docker service running, which is connectable on storage/console.
My traefik also works for this.
But I suspect the connections to use the pattern BUCKET.backup.lo.domain.com which leads to a 404 from traefik.
I clearly see this pattern, for example, when using Cyberduck to connect (in the traefik logs and Cyberduck itself). The connection itself is possible (backup.lo.domain.com). I also get the buckets listed. But as soon as I click on the bucket it shows a modal with the bucket.lo.domain.com pattern and the traefik default certificate.
version: "3.8"
volumes:
minio-data:
services:
minio:
container_name: minio-backup
image: quay.io/minio/minio:RELEASE.2022-01-08T03-11-54Z
networks:
- traefik
volumes:
- minio-data:/data
command:
- server
- /data
- --console-address
- ":9001"
environment:
- TZ=${TIME_ZONE}
- MINIO_ROOT_USER=root
- MINIO_ROOT_PASSWORD=password
- MINIO_BROWSER_REDIRECT_URL=https://backup-console.lo.domain.com
- MINIO_DOMAIN=https://backup.lo.domain.com
labels:
- traefik.enable=true
- traefik.docker.network=traefik
- traefik.http.routers.minio.service=minio
- traefik.http.routers.minio.rule=Host(`backup.lo.domain.com`)
- traefik.http.routers.minio.tls.certresolver=letsenc
- traefik.http.routers.minio.entrypoints=websecure
- traefik.http.services.minio.loadbalancer.server.port=9000
- "traefik.http.routers.minio-console.service=minio-console"
- "traefik.http.routers.minio-console.rule=Host(`backup-console.lo.domain.com`)"
- "traefik.http.routers.minio-console.entrypoints=websecure"
- "traefik.http.routers.minio-console.tls.certresolver=letsenc"
- "traefik.http.services.minio-console.loadbalancer.server.port=9001"
restart: unless-stopped
traefik:
image: traefik
container_name: traefik
command:
- --providers.docker=true
- --entryPoints.web.address=:80
- --entryPoints.websecure.address=:443
labels:
- "traefik.http.routers.traefik.tls=true"
- "traefik.http.routers.traefik.entrypoints=websecure"
- "traefik.http.routers.traefik.tls.certresolver=letsenc"
- "traefik.http.routers.traefik.service=api#internal"
- "traefik.http.routers.traefik.tls.domains[0].main=lo.domain.com"
- "traefik.http.routers.traefik.tls.domains[0].sans=*.lo.domain.com"
volumes:
- "/var/run/docker.sock:/var/run/docker.sock:ro"
restart: unless-stopped
networks:
traefik:
networks:
traefik_public:
Any ideas? Could I use something like wildcards for subdomains?
The problem here is that buckets do not have sub-domain DNS entries in your setup. If you disable this and use path-style requests things should work fine: https://docs.cyberduck.io/protocols/s3/#disable-use-of-virtual-host-style-requests
Specifically, you need to set s3.bucket.virtualhost.disable to true in Cyberbuck.

Traefik 2 Gateway Timeout

So I have the following docker-compose.yml
version: "3.7"
services:
roundclinic-mysql:
image: mysql:5.7
networks:
- spring-boot-mysql-network
environment:
- MYSQL_DATABASE=
- MYSQL_USER=
- MYSQL_PASSWORD=
- MYSQL_ROOT_PASSWORD=
volumes:
- ./mysqldata:/var/lib/mysql:rw,delegated
ports:
- "3306:3306"
web-service:
image: roundclinic/roundclinic:latest
networks:
- spring-boot-mysql-network
- traefik-network
depends_on:
- roundclinic-mysql
ports:
- 8080:8080
environment:
- "SPRING_PROFILES_ACTIVE=dev"
links:
- roundclinic-mysql
labels:
- "--providers.docker.network=traefik_default"
- "traefik.enable=true"
- "traefik.http.routers.roundclinic.rule=Host(`api-dev.roundclinic.app`)"
- "traefik.http.routers.roundclinic.entrypoints=web"
- "traefik.http.services.cal.loadbalancer.server.port=8080"
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"
- "traefik.docker.network=traefik-network"
ports:
- "80:80"
volumes:
- "/var/run/docker.sock:/var/run/docker.sock:ro"
networks:
traefik-network:
driver: bridge
external: true
spring-boot-mysql-network:
driver: bridge
volumes:
my-db:
Spring boot starts up fine and can connect to mysql.
When I connect to http://api-dev.roundclinic.app:8080/../ I can hit my application just fine
When I connect to http://api-dev.roundclinic.app/../ I get a gateway timeout. I can see in the traefik logs that it's forwarding the request to what seems to be the correct IP and port, but nothing hits the actual application. I'm not sure what's going on here. Any help?
When accessing port 8080 you are bypassing Traefik and directly access your application, correct?
Generally speaking the Traefik labels look good. Entrypoint, Port and Host are defined, router and service port are present. These are usually all the requirements for Docker-based setups.
One thing that I noticed is that the traefik container uses "traefik.docker.network=traefik-network", but your web app uses:
"--providers.docker.network=traefik_default".
I am not sure if traefik_default is something that traefik provides but that mismatch in network names might be the issue.
I can't test if that is the problem but that would be the first thing to check.
One way would be to simplify your config but just always using the networks key from docker compose instead of mixing it with labels and arguments.

traefik v2.2 help using only docker-compose router service entrypoint

Started learning about docker, traefik for playing in home.
Aim: Put everything all together in docker-compose.yml and .env files, understand basics, comment accordingly.
Want to get dashboard from traefik.test.local/dashboard rather test.local:8080, similarly api should be accessed from traefik.test.local/api. So that don't have to think about port numbers.
added lines to /etc/hosts
127.0.0.1 test.local
127.0.0.1 traefik.test.local
docker-compose.yml
version: "3.7"
services:
traefik:
# The official v2 Traefik docker image
image: traefik:v2.2
# Lets name the container
container_name: traefik
command:
# Enables the web UI
- "--api.insecure=true"
# Tells Traefik to listen to docker
- "--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.http.routers.router.rule=Host(`traefik.test.local/dashboard`)"
#- "traefik.http.routers.router.rule=Host(`traefik.test.local/api`)"
restart:
always
Not able to understand how to connect from router to services. Also correct me if I am wrong anywhere. Thank you.
PS: OS: kde-neon
you can achieve this using the following definition, you need to add labels for the routers and service and not only the router
proxy:
image: traefik:v2.1
command:
- '--providers.docker=true'
- '--entryPoints.web.address=:80'
- '--entryPoints.metrics.address=:8082'
- '--providers.providersThrottleDuration=2s'
- '--providers.docker.watch=true'
- '--providers.docker.swarmMode=true'
- '--providers.docker.swarmModeRefreshSeconds=15s'
- '--providers.docker.exposedbydefault=false'
- '--providers.docker.defaultRule=Host("traefik.lvh.me")'
- '--accessLog.bufferingSize=0'
- '--api=true'
- '--api.dashboard=true'
- '--api.insecure=true'
- '--ping.entryPoint=web'
volumes:
- '/var/run/docker.sock:/var/run/docker.sock:ro'
ports:
- '80:80'
- '8080:8080'
restart:
always
deploy:
labels:
- traefik.enable=true
- traefik.docker.network=monitoring
- traefik.http.services.traefik-dashboard.loadbalancer.server.port=8080
- traefik.http.routers.traefik-dashboard.rule=Host(`dashboard.traefik.lvh.me`)
- traefik.http.routers.traefik-dashboard.service=traefik-dashboard
- traefik.http.routers.traefik-dashboard.entrypoints=web
- traefik.http.services.traefik-api.loadbalancer.server.port=80
- traefik.http.routers.traefik-api.rule=Host(`api.traefik.lvh.me`)
- traefik.http.routers.traefik-api.service=traefik-api
- traefik.http.routers.traefik-api.entrypoints=web
logging:
driver: json-file
options:
'max-size': '10m'
'max-file': '5'
also if you use lvh.me domain you not need to edit /etc/hosts

Traefik,multiple frontend rules to one docker container

I did search the manual but really couldn't make it very clear, even using the keywords to google that.
I need to proxy the /_ to the API container, some rule like that www.mydomain.com/_ => API container
There is already a specified domain point to this API container
api.mydomain.com => API container
This is my docker-compose.yml, all I want is to add a rule that proxy the /_ to this container too.
version: '3.3'
services:
testapi:
image: git.xxxx.com/api/core/test:latest
restart: always
networks:
- web
- default
expose:
- "80"
labels:
- "traefik.enable=true"
- "traefik.port=80"
- "traefik.docker.network=web"
- "traefik.backend=testapi"
#this domain is used for app
- "traefik.frontend.rule=Host:api.test.mydomain.com"
#this is used for website.All I want is prxy "https://www.test.mydomain.com/_/" to this container
- "traefik.frontend.rule1=Host:www.test.mydomain.com;PathPrefixStrp:/_"
You can use segment labels:
version: '3.3'
services:
testapi:
image: git.xxxx.com/api/core/test:latest
restart: always
networks:
- web
- default
expose:
- "80"
labels:
- "traefik.enable=true"
- "traefik.port=80"
- "traefik.docker.network=web"
#this domain is used for app
- "traefik.foo.frontend.rule=Host:api.test.mydomain.com"
- "traefik.bar.frontend.rule=Host:www.test.mydomain.com,m.test.mydomain.com;PathPrefixStrp:/_"
https://docs.traefik.io/v1.6/configuration/backends/docker/#on-containers-with-multiple-ports-segment-labels

Traefik docker-compose only creating one frontend route instead of 3

I want traefik to routh specific paths to my nginx service.
The setup below works on my development environment, but not on a live
environment.
The issue is, for the nginx service it only ever creates one of the frontend
routes, usually just static, or just media. It's as if it finds one, creates it
and then just doesn't bother with the rest.
If I restart my containers, then traefik will randomly do only one of the routes
again, but never all 3 as it does on my dev machine.
docker-compose.yml
version: '3'
services:
db:
image: postgres:latest
webapp:
build:
context: ./src/webapp/
env_file:
- .env
volumes:
- "./resources:/mnt/resources/"
depends_on:
- db
links:
- "db:dbhost"
labels:
- "traefik.backend=webapp"
- "traefik.port=8000"
- "traefik.webapp.entryPoints=https"
- "traefik.webapp.frontend.rule=Host:my.domain.example"
nginx:
build:
context: ./src/nginx/
volumes:
- ./resources:/mnt/resources
labels:
- "traefik.backend=nginx"
- "traefik.port=443"
- "traefik.frontend.entryPoints=https"
- "traefik.static.frontend.rule=Host:my.domain.example;PathPrefix:/static"
- "traefik.media.frontend.rule=Host:my.domain.example;PathPrefix:/media"
- "traefik.sw.frontend.rule=Host:my.domain.example;Path:/service-worker.js"
traefik:
image: traefik:1.6.3
restart: always
ports:
- "80:80"
- "443:443"
- "8080:8080"
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- ./src/traefik/traefik.toml:/traefik.toml
- ./src/traefik/acme.json:/acme.json
A separate question but still traefik related:
Traefik is supposed to fetch letsencrypt certs for the main.domain, and does so
perfectly well for that domain.
But it's also trying to fetch certs for the db and traefik service.
How do I tell traefik not to fetch certs for these services?
Finally figured it out.
For the frontends that weren't generated, I basically had to specify a backend for each frontend, and then they worked as expected.
so this:
- "traefik.static.frontend.rule=Host:my.domain.example;PathPrefix:/static"
- "traefik.media.frontend.rule=Host:my.domain.example;PathPrefix:/media"
- "traefik.sw.frontend.rule=Host:my.domain.example;Path:/service-worker.js"
... became this:
- "traefik.static.backend=nginx-static"
- "traefik.static.frontend.rule=Host:my.domain.example;PathPrefix:/static"
- "traefik.media.backend=nginx-media"
- "traefik.media.frontend.rule=Host:my.domain.example;PathPrefix:/media"
- "traefik.sw.backend=nginx-sw"
- "traefik.sw.frontend.rule=Host:my.domain.example;Path:/service-worker.js"
After that everything worked correctly.