Если у вас есть сервисы, которые запущены в контейнерах и слушают одинаковые порты (к примеру 443 для AdGuard Home и Vaultwarden), то надо дать понять traefik'у, как разделять трафик до них.
Для этого у routers есть сущность rule.
Будем исходить из того, что у нас есть контейнер с traefik, запущенный вот тут.
Единственное, что мы в него добавим, так это строчку:
- "--entrypoints.https.address=:443"
в раздел command:
. Это позволит траефику слушать не только порт 80, но и 443.
Сейчас мы не будем останавливаться на особенностях протокола https, а именно сертификатах и вернемся к ним чуть позднее.
Маршрутиpация с помощью Host(`SITE`):
Итак, если у вас есть домен example.com (с адресом 1.2.3.4), то обращение к сервису AdGuard Home можно описать так:
Обращаю внимание, что это описание блока labels в docker-compose.yml для контейнера, в котором запущен adguardhome.
labels:
- "traefik.http.routers.adguardhome.entrypoints=https"
- "traefik.http.routers.adguardhome.rule=Host(`adguard.example.com`)"
- "traefik.http.services.adguardhome.loadbalancer.server.port=443"
Где https это entrypoints, описанный в docker-compose.yml для запуска самого traefik (см. выше), а adguard.example.com имеет тот же ip адрес (1.2.3.4), что и example.com (или просто ссылается на основной домен с помощью cname), но он создается именно для доступа к сервису adguard home (прописать можно как на dns, который обслуживает вашу зону, добавив A запись, так и на любом dns, который недоступен снаружи - главное, чтобы тот, кто обращается к adguardhome мог отрезолвить адрес adguard.example.com в тот же адрес, на котором крутится traefik).
Таким образом, если в браузере ввести адрес https://adguard.example.com, то вы попадаете на машину, где запущен traefik, который слушает порты 80 и 443 (смотрим эту статью ). Запрос приходит на 443 порт машины, traefik с помощью rule=Host(adguard.example.com
) определяет, что этот запрос надо адресовать в service adguardhome на порт 443.
Соответственно, чтобы можно было обратиться к сервису Vaultwarden, надо сделать адрес vaultwarden.example.com с тем же ip - 1.2.3.4 (название условно, то есть можно и vaultwarden111test.example.com, это неважно; главное - указать его потом в правиле) и для контейнера Vaultwarden указать labels:
labels:
- "traefik.http.routers.vaultwarden.entrypoints=https"
- "traefik.http.routers.vaultwarden.rule=Host(`vaultwarden.example.com`)"
- "traefik.http.services.vaultwarden.loadbalancer.server.port=443"
Маршрутиpация с помощью Path(`/PATH`):
Если будет несколько приложений, которые работают на порту 8080 (например), то для каждого надо сделать свой домен, а в loadbalancer указать нужный порт:
Обращаю внимание, что этот пример показан только для понимания принципов работы traefik, а именно, что 443 порт внутри контейнеров adguardhome и vaultwarden никак не связаны с тем, что traefik слушает этот порт снаружи. Внутри контейнеров приложение может слушать любой порт, так же как и снаружи можно получить доступ к контейнеру через 80 порт, указать другой entrypoint.
- "traefik.http.services.<service-name>.loadbalancer.server.port=8080"
Если же есть какое-то приложение, у которого корневой префикс отличен от /, то можно использовать конструкцию:
- "traefik.http.routers.vaultwarden.rule=Host(`example.com`) && Path(`/app_path`)"
Например, есть простое приложение на go, которое слушает порт 8080 и ждет префикс /app:
package main
import (
"fmt"
"log"
"net/http"
)
func handler(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Hello, world!")
}
func main() {
http.HandleFunc("/app_path", handler)
log.Fatal(http.ListenAndServe(":8080", nil))
}
Тогда после того как вы упакуете его в контейнер и запустите из такого docker-compose.yml файла:
labels:
- "traefik.enable=true"
- "traefik.http.routers.go1.entrypoints=web"
- "traefik.http.routers.go1.rule=Host(`example.com`) && Path(`/app_path`)"
- "traefik.http.services.go1.loadbalancer.server.port=8080"
Приложение будет возвращать Hello, world!
только при запросе на http://example.com/app_path.