Jak hostować strony internetowe Docker za pomocą Traefika?

Poznaj Docker w kilku prostych krokach

Jak hostować <span class='purple'>strony internetowe</span> Docker za pomocą <span class='purple'>Traefika</span>?

Co to jest Traefik?

Czym jest Traefik?

Traefik to nowoczesny reverse proxy i load balancer, który został stworzony z myślą o dynamicznym zarządzaniu ruchem sieciowym w środowiskach mikroserwisowych. W przeciwieństwie do tradycyjnych narzędzi, Traefik został zaprojektowany, aby bezproblemowo integrować się z nowoczesnymi narzędziami i platformami, takimi jak Docker czy Kubernetes.

Kluczowe cechy Traefika

  1. Automatyczna konfiguracja - Jedną z głównych cech Traefika jest jego zdolność do automatycznego wykrywania usług i konfigurowania tras (DNS). Dzięki integracji z systemami takimi jak Kubernetes czy Docker, Traefik automatycznie aktualizuje swoje ustawienia, gdy nowe usługi są dodawane, zmieniane lub usuwane.
  2. Wsparcie dla wielu protokołów - Traefik obsługuje zarówno protokoły TCP jak i UDP dzięki czemu możemy być używany w szerokim zakresie zastosowań. Dodatkowo oferuje możliwość tworzenia Middlewarów, które pozwalają na zwiększoną kontrole nad aplikacjami.
  3. Łatwa konfiguracja SSL - Traefik automatycznie zarządza certyfikatami SSL, korzystając z Let's Encrypt. Dzięki temu możliwe jest łatwe i szybkie wdrożenie bezpiecznych połączeń HTTPS bez potrzeby ręcznego zarządzania certyfikatami.
  4. Loadbalancer - Traefik oferuje zaawansowane funkcje balansowania obciążenia, które umożliwiają równomierne rozdzielanie ruchu sieciowego między różne instancje usług.
  5. Label based routing - W celu hostowania aplikacji na naszej domenie wystarczy że dodamy odpowiedni label do kontenera w pliku docker-compose.yml

Dlaczego wybrać Traefik a nie np. Docker Reverse Proxy?

Traefik pomimo iż na pierwszy rzut oka może wydawać się ciężki w osbłudze, w rzeczywistości pozwoli nam na zarządzanie naszymi aplikacjami kontenerowymi w dużo prostrzy sposób niż przy użyciu np. Docker Reverse Proxy. W przypadku wykrozystania Traefika nie musimy samodzielnie konfigurować certyfikatów SSL, martwić się o przekierowania HTTP na HTTPS, oraz dodatkowo w szybki i prosty sposób możemy korzystać z Middlewarów. Dodatkowo sama platforma oferuje wiele rozbudowanych wtyczek, które warto rozważyć przy wybranych projektach.

Podstawowa konfiguracja Traefik

Jak skonfigurować Traefik?

Poniżej znajduje się minimalistyczny plik compose.yml zawierający podstawową konfigurację Traefik do Developmentu.

Traefik Dashboard (Development Only)

W poniższym przykładzie uruchamiamy kontener Traefik z aktywnym Traefik Dashbord. Podejście takie jest wysoce niebezpieczne, z uwagi na konieczność uruchomienia interfejsu API Traefik, który niezabezpieczony może prowadzić do wielu problemów z bezpieczeństwem hostowanych aplikacji.

Potraktuj poniższy przykład ściśle edukacyjnie, w dalszej części znajdziesz również bezpieczną implementację.

Plik konfiguracyjny traefik-compose.yml (Development - Traefik Dashboard)

services: traefik:  image: traefik:latest  ports:   - "80:80"   - "443:443"  command:   - "--api.dashboard=true"Enable Traefik Dashboard   - "--providers.docker.exposedbydefault=false"Do not expose Docker containers by default   - "--entrypoints.web.address=:80"   - "--entrypoints.websecure.address=:443"   - "--certificatesresolvers.myresolver.acme.tlschallenge=true"Enable ACME TLS Challenge   - "--certificatesresolvers.myresolver.acme.email=EMAIL"Define Email for ACME   - "--certificatesresolvers.myresolver.acme.storage=/letsencrypt/acme.json"Define Storage for ACME  volumes:   - "var/run/docker.sock:/var/run/docker.sock"Expose Docker Socket (DANGEROUS!!!)   - "./letsencrypt:/letsencrypt"Volume for SSL Certs  labels:   - "traefik.enable=true"Enables Traefik Routing   - "traefik.http.routers.traefik.rule=Host(`example.domain`)"Define domain for Traefik Dashboard   - "traefik.http.routers.traefik.entrypoints=websecure"Host Traefik Dashbord Over HTTPS   - "traefik.http.routers.traefik.service=api@internal"Enable Traefik API - Need for Traefik Dashbord   - "traefik.http.routers.traefik.tls.certresolver=myresolver"Enable ACME TLS Challenge

W powyższym przykładzie zdefiniowaliśmy serwis Traefik z nastepującymi parametrami:

  • Udostępniliśmy porty 80 i 443 dla naszego Traefik Reverse Proxy
  • Utworzyliśmy volumen dla certyfikatów SSL
  • Daliśmy dostęp do naszego Docker Socet dla serwisu Traefik (NIEBEZPIECZNE)
  • W sekcji commands skonfigurowaliśmy porty oraz certyfikaty SSL, oraz dodatkowo uruchomiliśmy Traefik Dashboard
  • W sekcji labels przypisaliśmy dostęp do naszego Traefik Dashbord pod adresem URL example.domain oraz

W celu przetestowania powyższej konfiguracji musisz posiadać wykupioną domenę. Jeśli takową posiadasz to skieruj ją na swój serwer VPS. Poniżej przykładowa konfiguracja moich domen.

Przykładowa konfiguracja DNS

Uruchom Traefik Dashboard

docker compose uplubdocker compose -f compose-file-name.yml up

Przejdź na wybraną przez siebie domenę, jeśli wszystko działa poprawnie to znajdziesz tutaj panel Traefik Dashboard.

Bezpieczna konfiguracja Traefik

Dlaczego powyższa konfiguracja nie jest bezpieczna?

Kiedy poznaliśmy już podstawową konfigurację serwisu Traefik, warto byłoby dowiedzieć się jak powinna wyglądać ona w bezpieczny sposób. Powyższe rozwiązanie niesie ze sobą kilka problemów:

  • Dajemy bezpośredni dostęp do socketu Docker, czego nie powinnismy NIGDY robić, póki się na tym nie znamy
  • Udostępniamy interfejs API Traefik, który dodatkowo nie jest w ząden sposób chroniony, w ten sposób atakujący może podejrzeć wszysktie nasze informacje
  • Sam Traefik Dashboard również dostępny jest publicznie i nie jest chroniony hasłem.

Bezpieczny przykład konfiguracji Traefik

Poniżej skonfigurujemy serwis Traefik, tak aby korzystał z Docer Socet za pomocą proxy, oraz całkowicie wyłączymy dostęp do Traefik Dashboard.

Plik konfiguracyjny traefik-compose.yml (Development - Traefik Dashboard)

services: socket-proxy: --New Service - Socket Proxy  image: "tecnativa/docker-socket-proxy"  container_name: "socket-proxy"  environment:   - CONTAINERS=1  networks:   - "traefik-socket-proxy"  volumes:   - "/var/run/docker.sock:/var/run/docker.sock:ro" traefik: --Modified Traefik Service  image: "traefik:latest"  depends_on:   - "socket-proxy"  ports:   - "80:80"   - "443:443"  networks:   - "traefik-socket-proxy"--Connect to Socket Proxy   - "traefik-external"--Traefick Network  command:   - "--providers.docker.endpoint=tcp://socket-proxy:2375"--Use Socket Proxy   - "--providers.docker.exposedbydefault=false"   - "--entrypoints.web.address=:80"   - "--entrypoints.websecure.address=:443"   - "--certificatesresolvers.myresolver.acme.tlschallenge=true"   - "--certificatesresolvers.myresolver.acme.email=EMAIL"   - "--certificatesresolvers.myresolver.acme.storage=/letsencrypt/acme.json"  volumes:   - "./letsencrypt:/letsencrypt"  labels:   - "traefik.enable=true"networks: traefik-socket-proxy: --Internal Network for Socket Proxy  name: "traefik-socket-proxy" traefik-external: -- Network that host External Websites  name: "traefik-external"

Porównaj powyższy bezpieczny przykład z poprzednim. Aktualne rozwiązanie nie udostępnia Traefick Dashbord oraz wykorzystuje dodatkowy serwis jakim jest Socket-Proxy, które pozwala na ograniczoną komunikację naszego Traeficka z Socetem Dockera. W razie potrzeb za pomocą zmiennych środowiskowych można dodatkowo dokonać bardziej restrykcyjnej konfiguracji proxy.

Hosting strony internetowej Traefik

Struktura Pliku Konfiguracyjnego Traefik

Jak zauważyliśmy na powyrzszych przykładach konfiguracja Traefika nie jest niczym skoplikowanym, jednakże kiedy zaczynamy definiować nasze serwisy musimy spełnić jeden ważny wymóg. Przeanalizuj dokładnie poniższy przykład...

Przykładowa konfiguracja Traefika

Service - Labels

Zwróć uwagę na zaznaczone na zółto fragmenty kodu. Zdefinjowaliśmy serwis o nazwie "testing", a następnie w sekcji "labels" użyliśmy jego nazwy tuż po frazie "routers".

Jest to sposób w jaki nalezy przypisywać nazwy serwisów do labeli za pomocą Traefika. Jeśli popełnisz w tym miejscu błąd Traefik nie bedzie w stanie zlokalizować Twojego kontenera.

Pamiętaj aby zawsze dokonywać przypisania tak jak w powyższym przykładzie, adekwatnie do nazw swoich serwisów.

  • image: traefik/whoami - Nasz Obraz Aplikacji
  • container_name: "testing" - Nazwa Naszego Kontenera
  • traefik.enable=true" - Uruchamia Routing dla danego kontenera
  • traefik.http.routers.SERVICE_NAME.rule=Host(`example.com`)" - Określa adres URL pod jakim znajdować ma się aplikacja
  • traefik.http.routers.SERVICE_NAME.entrypoints=websecure" - Informuje Traefik aby hostować aplikację za pośrednictwem portu 443 (HTTPS)
  • traefik.http.routers.SERVICE_NAME.certesolver=myresolver" - Informuje Traefik o aby korzystać z naszego agenta SSL (Let's Encrypt)
  • traefik.http.routers.SERVICE_NAME.middlewares=waf@docker" - Informuje Traefik o aby dana aplikacja korzystała z podanego middleware'a
  • networks: - W tej sekcji standradowo podpianmy aplikację do stworzonej przez nasz sieci Traefik-External (Sieć publiczna)

Cały plik konfiguracyjny Traefik z podpiętą stroną HTTP

Poniżej cały plik konfiguracyjny, zawierający uruchomioną stronę internetową.

Przykładowa bezpieczna konfiguracja Traefik z jedną stroną internetową

services: socket-proxy: --Socket Proxy  image: "tecnativa/docker-socket-proxy"  container_name: "socket-proxy"  environment:   - CONTAINERS=1  networks:   - "traefik-socket-proxy"  volumes:   - "/var/run/docker.sock:/var/run/docker.sock:ro" traefik: --Traefik Service  image: "traefik:latest"  depends_on:   - "socket-proxy"  ports:   - "80:80"   - "443:443"  networks:   - "traefik-socket-proxy"   - "traefik-external"  command:   - "--providers.docker.endpoint=tcp://socket-proxy:2375"   - "--providers.docker.exposedbydefault=false"   - "--entrypoints.web.address=:80"   - "--entrypoints.websecure.address=:443"   - "--certificatesresolvers.myresolver.acme.tlschallenge=true"   - "--certificatesresolvers.myresolver.acme.email=EMAIL"   - "--certificatesresolvers.myresolver.acme.storage=/letsencrypt/acme.json"  volumes:   - "./letsencrypt:/letsencrypt"  labels:   - "traefik.enable=true" your-app: -- Our Website  image: "traefik/whoami"  container_name: "your-app"  labels:   - "traefik.enable=true" -- Enable Traefik on your app   - "traefik.http.routers.your-app.rule=Host(`whoami.jakubwojtysiak.online`)" -- Replace with your domain   - "traefik.http.routers.your-app.entrypoints=websecure" -- Host webiste on 443 (HTTPS)   - "traefik.http.routers.your-app.tls.certresolver=myresolver" -- Use Lets Encrypt Cert Resolver  networks:   - "traefik-external" -- Attach website to external network, so Traefik can discover it (We have to use it as we decided to use Traefik Socket Proxy)networks: traefik-socket-proxy:  name: "traefik-socket-proxy" traefik-external:  name: "traefik-external"

Uruchom plik compose.yml

docker compose up -d

Po przejściu na wybraną przez siebie domenę powinieneś zobaczyć prostą aplikację która wyświetli informacje o Twoim zapytaniu wysłanym na serwer. Dokładnie tym samym sposobem będziesz w stanie uruchomić dowolne aplikacje webowe.