Traefik rule need solution for sub domain - docker

I want to run an application behind traefik not as a sub-domain, but something like: xyz.abc.com/m1 or xyz.abc.com/m2 and so on.
Which label will work for it. I have tried with PathPrefix but it's not working. A sample application Joomla is deployed on docker swarm mode . Can I use Nginx or Haproxy for the same ?? If so, How?

When putting multiple applications behind the same name, there's a good chance the app needs to know it's URL prefix isn't at root (as most apps are expecting to be deployed at the root). So, might need to look at that too.
Traefik-wise, a stack file might look like this. This is running in Swarm mode (since you mentioned Swarm), which requires the Traefik labels to be on the service, not on the container. As such, they have to be within the deploy.labels definition, not just labels.
Example using Traefik 1
version: "3.7"
services:
proxy:
image: traefik:1.7
command: --docker --docker.swarmMode
ports:
- 80:80
volumes:
- /var/run/docker.sock:/var/run/docker.sock
app1:
image: your-image-for-app1
deploy:
labels:
traefik.backend: app1
traefik.frontend.rule: PathPrefix:/m1
traefik.port: 80
app2:
image: your-image-for-app2
deploy:
labels:
traefik.backend: app2
traefik.frontend.rule: PathPrefix:/m2
traefik.port: 80
Example using Traefik 2
version: "3.7"
services:
proxy:
image: traefik:2.0
command: --providers.docker --providers.docker.swarmMode
ports:
- 80:80
volumes:
- /var/run/docker.sock:/var/run/docker.sock
app1:
image: your-image-for-app1
deploy:
labels:
traefik.http.routers.app1.rule: PathPrefix(`/m1`)
traefik.http.services.app1.loadbalancer.server.port: 80
app2:
image: your-image-for-app2
deploy:
labels:
traefik.http.routers.app2.rule: PathPrefix(`/m2`)
traefik.http.services.app2.loadbalancer.server.port: 80

Related

Traefik routing one application to port 80, others require explicit port

I have an environment running docker containers.
This environment hosts Traefik, Nextcloud, MotionEye and Heimdall.
I also have another environment running CoreDNS in a docker container.
For some reason, I can get MotionEye to be accessible from motioneye.docker.swarm (changed the domain in here for privacy).
However, for nextcloud and Heimdall, I have to explicitly access the ports and I'm struggling to tell why.
e.g. Heimdall is gateway.docker.swarm:8091 when should be gateway.docker.swarm
When a user requests a webpage onto the local dns server X.X.X.117 it gets routed through to the traefik instance on X.X.X.106.
My traefik compose file is as follows:
version: '3'
services:
reverse-proxy:
# The official v2 Traefik docker image
image: traefik:v2.3
restart: always
# Enables the web UI and tells Traefik to listen to docker
command: --api.insecure=true --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.port=8080"
- "traefik.backend=traefik"
- "traefik.frontend.rule=Host:traefik.docker.swarm"
- "traefik.docker.network=traefik_default"
My Heimdall compose is as follows:
version: "3"
services:
heimdall:
image: ghcr.io/linuxserver/heimdall
container_name: heimdall
environment:
- PUID=1000
- PGID=1000
- TZ=Europe/London
volumes:
- /home/pi/heimdall/config:/config
ports:
- 8091:80
restart: unless-stopped
networks:
- heimdall
labels:
- "traefik.enable=true"
- "traefik.port=8091"
- "traefik.http.routers.heimdall.entrypoints=http"
- "traefik.http.routers.heimdall.rule=Host(`gateway.docker.swarm`)"
networks:
heimdall:
external:
name: heimdall
Can anyone see what I'm doing wrong here?
When you access through gateway.docker.swarm:8091 it works because you are accessing the heimdall container directly. This is possible because you defined
ports:
- 8091:80
in your docker-compose.
In order to access through traefik they must be on the same network. Also, remove the port mapping if you like this container to be only accessible through traefik. And finally correct the traefik port accordingly.
version: "3"
services:
heimdall:
image: ghcr.io/linuxserver/heimdall
container_name: heimdall
environment:
- PUID=1000
- PGID=1000
- TZ=Europe/London
volumes:
- /home/pi/heimdall/config:/config
restart: unless-stopped
labels:
- "traefik.enable=true"
- "traefik.port=80"
- "traefik.http.routers.heimdall.entrypoints=http"
- "traefik.http.routers.heimdall.rule=Host(`gateway.docker.swarm`)"

Traefik 2.0 and docker simple configuration doesnt work

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)"

New containers accessing volume on preexisting container

I have a 'master' container, that should be already running when starting all the others.
In it i have a conf/ directory, that this service is monitoring and applying the relevant changes.
How can i have each new container drop a file in this directory?
real scenario:
given my docker-compose.yml below, i want each service (portainer, whoami, apache) to drop a .yml file in the "./traefik/conf/:/etc/traefik/conf/" path mapping of the traefik service.
docker-compose.yml
version: "3.5"
services:
traefik:
image: traefik
env_file: ./traefik/env
restart: unless-stopped
ports:
- "80:80"
- "443:443"
- "8080:8080"
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- ./traefik/conf/:/etc/traefik/conf/
- ./traefik/traefik.yml:/etc/traefik/traefik.yml
portainer:
image: portainer/portainer
depends_on: [traefik]
command: --no-auth -H unix:///var/run/docker.sock
volumes:
- /var/run/docker.sock:/var/run/docker.sock
whoami:
image: containous/whoami
depends_on: [traefik]
portainer.traefik.yml
http:
routers:
portainer:
entryPoints: [http]
middlewares: [redirect-to-http]
service: portainer-preauth#docker
rule: Host(`portainer.docker.mydomain`)
whoami.traefik.yml
http:
routers:
whoami:
entryPoints: [http]
middlewares: [redirect-to-http]
service: whoami-preauth#docker
rule: Host(`whoami.docker.mydomain`)
Where are the files portainer.traefik.yml and whoami.traefik.yml
located? If they are on host machine, you can directly copy them to
./traefik/conf/. – Shashank V
the thing is i cant have all files in traefik/conf.
this would require manually dropping a file there every time i create a new image.
i believe that every service should be responsible for its own files.
also, when traefik starts and finds files of those other services that haven't started yet, it logs lots of errors.
to avoid this behavior, i would like to put the file there only when the container is started.
below is is the project file structure.
You can use a volume across all services. Just define it in your docker-compose.yml and assign it to each service:
version: "3.5"
services:
traefik:
image: traefik
env_file: ./traefik/env
restart: unless-stopped
ports:
- "80:80"
- "443:443"
- "8080:8080"
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- ./traefik/conf/:/etc/traefik/conf/
- ./traefik/traefik.yml:/etc/traefik/traefik.yml
- foo:/path/to/share/
portainer:
image: portainer/portainer
depends_on: [traefik]
command: --no-auth -H unix:///var/run/docker.sock
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- foo:/another/path/to/share/
whoami:
image: containous/whoami
depends_on: [traefik]
volumes:
- foo:/and/another/path/
volumes:
foo:
driver: local
This is the equivalent to the --volumes-from feature of "plain" Docker. Or at least, what comes closest to it.
Your master container would then have to use the same volume. If this container doesn't run within the same Docker Compose context, you have to define this volume externally before.

Exposing a Docker database service only on the internal network with Traefik

Let's say I defined two services "frontend" and "db" in my docker-compose.yml which are deployed to a Docker swarm, i.e. they may also run in different stacks. With this setup Traefik automatically generates the frontend and backend for each stack which is fine.
Now I have another Docker container running temporarily in a Jenkins pipeline which shall be able to access the db service in a specific stack. My first idea was to expose the db service by adding it to the cluster-global-net network so that Traefik can generate a frontend route to the bakend. This basically works.
But I'd like to hide the database service from "the public" while still being able to connect another Docker container to it via its stack or service name using the internal "default" network.
Can this be done somehow?
version: '3.6'
networks:
default: {}
cluster-global-net:
external: true
services:
frontend:
image: frontend_image
ports:
- 8080
networks:
- cluster-global-net
- default
deploy:
labels:
traefik.port: 8080
traefik.docker.network: cluster-global-net
traefik.backend.loadbalancer.swarm: 'true'
traefik.backend.loadbalancer.stickiness: 'true'
replicas: 1
restart_policy:
condition: any
db:
image: db_image
environment:
- MYSQL_ALLOW_EMPTY_PASSWORD=false
- MYSQL_DATABASE=db_schema
- MYSQL_USER=db_user
- MYSQL_PASSWORD=db_pass
ports:
- 3306
volumes:
- db_volume:/var/lib/mysql
networks:
- default
restart: on-failure
deploy:
labels:
traefik.port: 3306
traefik.docker.network: default
What you need is a network on which both of them are deployed, but that it's not visible from anyone else.
To do such, create a network , add it to your db service and frontend, and also to your temporary service. And indeed, remove traefik label on db because they are not needed anymore here.
EG :
...
networks:
default: {}
cluster-global-net:
external: true
db-net:
external: true
services:
frontend:
image: frontend_image
networks:
- cluster-global-net
- default
- db-net
deploy:
...
db:
image: db_image
...
networks:
- default
- db-net
restart: on-failure
#no labels
docker network create db-net
docker stack deploy -c <mycompose.yml> <myfront>
docker service create --network db-net <myTemporaryImage> <temporaryService>
Then, the temporaryService as well as the frontend can reach the db through db:3306
BTW : you don't need to open the port for the frontend, since traefik will access it internally (trafik.port).
EDIT : new exemple with network created from compose file.
...
networks:
default: {}
cluster-global-net:
external: true
db-net: {}
services:
frontend:
image: frontend_image
networks:
- cluster-global-net
- default
- db-net
deploy:
...
db:
image: db_image
...
networks:
- default
- db-net
restart: on-failure
#no labels
docker stack deploy -c <mycompose.yml> someStackName
docker service create --network someStackName_db-net <myTemporaryImage> <temporaryService>

Rancher, public subdomains and nginx

I was running a complete CI stack on some local servers that I try to migrate to Rancher.
First, I have created the following configuration on one node with
docker-compose that seems to runs perfectly (i.e., I can access to
each elements separately via external public subdomains).
jwilder/nginx-proxy
jrcs/letsencrypt-nginx-proxy-companion:latest
registry:2.6.2
rancher/server:latest
Now, I want to access to some elements from brand new rancher stacks via
their respective external public subdomains. For instance,
https://gitlab.example.com, https://jenkins.example.com. Unfortunately, it doesn't work.
Actually, when I upload the following docker-compose.yml file when creating a stack, it looks like not being able to make the connection with the existing stack, the one which supports rancher itself and basically, I cannot access to the services which are running fine:
version: '2'
services:
gitlab:
image: gitlab/gitlab-ce:latest
labels:
io.rancher.container.pull_image: always
ports:
- "27100:80"
- "27143:443"
- "27122:22"
restart: always
volumes:
- /var/gitlab_volume/config:/etc/gitlab
- /var/gitlab_volume/logs:/var/log/gitlab
- /var/gitlab_volume/data:/var/opt/gitlab
environment:
VIRTUAL_HOST: "gitlab.example.com"
VIRTUAL_PORT: 80
LETSENCRYPT_HOST: "gitlab.example.com"
LETSENCRYPT_EMAIL: "admin#example.com"
What is the appropriate approach?
For info, I have already checked Rancher external subdomains but at this stage, I want to use my nginx server as load balancer.
Here the final docker-compose.yml file definition:
version: '2'
services:
gitlab:
image: gitlab/gitlab-ce:latest
network_mode: bridge
labels:
io.rancher.container.pull_image: always
ports:
- "27100:80"
- "27143:443"
- "27122:22"
restart: always
volumes:
- /var/gitlab_volume/config:/etc/gitlab
- /var/gitlab_volume/logs:/var/log/gitlab
- /var/gitlab_volume/data:/var/opt/gitlab
environment:
VIRTUAL_HOST: "gitlab.example.com"
VIRTUAL_PORT: 80
LETSENCRYPT_HOST: "gitlab.example.com"
LETSENCRYPT_EMAIL: "admin#example.com"
We just need to force the network_mode on each container definition.

Resources