Docker: Routing HTTPS

Jak zarządzać routingiem HTTP i szyfrowaniem TLS (HTTPS) w kontenerach Docker

👋 Witamy w dokumentacji Stackhero!

Stackhero oferuje gotowe do użycia rozwiązanie Docker cloud CaaS (Containers as a Service), które zapewnia wiele korzyści, w tym:

  • Łatwe wdrażanie kontenerów do produkcji za pomocą prostego docker-compose up.
  • Dostosowywana nazwa domeny zabezpieczona HTTPS (na przykład, https://api.twoja-firma.com, https://www.twoja-firma.com, https://backoffice.twoja-firma.com).
  • Optymalna wydajność i solidne zabezpieczenia dzięki prywatnej i dedykowanej VM.
  • Bezproblemowe aktualizacje za pomocą jednego kliknięcia.

Oszczędzaj czas i upraszczaj swoje życie: wystarczy 5 minut, aby wypróbować rozwiązanie Docker CaaS cloud hosting Stackhero i wdrożyć swoje kontenery do produkcji!

Każda instancja Stackhero for Docker zawiera dedykowany, wstępnie skonfigurowany serwer Traefik, który zarządza ruchem HTTP i automatycznie go szyfruje za pomocą certyfikatów TLS. To uproszczone ustawienie sprawia, że routing jest prosty i efektywny. Na przykład:

  • Przekieruj ruch z https://www.my-company.com (z prefiksem www lub bez) do kontenera frontend.
  • Przekieruj https://www.my-company.com/documentations do kontenera documentations.
  • Przekieruj https://api.my-project.io do kontenera api.

Możesz zarządzać nieograniczoną liczbą domen z automatycznym tworzeniem i odnawianiem certyfikatów TLS. Co najlepsze, możesz skonfigurować to wszystko w zaledwie trzech liniach!

We wszystkich poniższych przykładach konfiguracji musisz zastąpić <XXXXXX>.stackhero-network.com nazwą domeny swojej instancji Stackhero for Docker.

Poniżej znajduje się podstawowy przykład pliku docker-compose.yml:

services:
  test:
    image: nginx
    labels:
      - "traefik.enable=true" # Włącz Traefik, aby kierować ruch do tego kontenera
      - "traefik.http.routers.test.rule=Host(`<XXXXXX>.stackhero-network.com`)" # Zdefiniuj hosta
      - "traefik.http.routers.test.tls.certresolver=letsencrypt" # Użyj 'letsencrypt' jako resolvera certyfikatu TLS

W tym przykładzie kontener o nazwie test działa z obrazem Nginx. Kluczowa konfiguracja jest podana w sekcji etykiet. Wystarczy skopiować te linie do pliku docker-compose.yml i zastąpić <XXXXXX>.stackhero-network.com swoją domeną usługi.

Możesz wdrożyć kontener używając:

docker context use <XXXXXX>.stackhero-network.com
docker-compose up

Po uruchomieniu kontenera odwiedź https://<XXXXXX>.stackhero-network.com/, aby zobaczyć stronę "Welcome to nginx!".

Strona powitalna NginxStrona powitalna Nginx

Jeśli nie widzisz strony powitalnej Nginx, sprawdź pulpit nawigacyjny Traefik pod kątem możliwych błędów!

Dzięki tej konfiguracji żądania HTTP wysyłane do <XXXXXX>.stackhero-network.com są kierowane do kontenera test, a Traefik automatycznie tworzy i zarządza certyfikatami TLS dla HTTPS.

W poprzednim przykładzie użyliśmy domyślnej domeny <XXXXXX>.stackhero-network.com. W praktyce prawdopodobnie użyjesz własnych domen firmowych lub projektowych, takich jak www.my-company.com lub api.my-project.io. Poniższa sekcja wyjaśnia, jak skonfigurować niestandardowe domeny.

W tym przykładzie skonfigurujesz domenę api.my-project.io. Zastąp my-project.io domeną, którą posiadasz, a api pożądanym subdomeną.

Najpierw zaktualizuj ustawienia DNS swojej domeny, aby api.my-project.io wskazywało na domenę <XXXXXX>.stackhero-network.com.

  1. Zaloguj się do swojego dostawcy domen i uzyskaj dostęp do konfiguracji DNS.
  2. Utwórz nowy wpis o nazwie api (lub innej wybranej subdomenie), ustaw jego typ na CNAME i ustaw jego cel na <XXXXXX>.stackhero-network.com.

Przykład konfiguracji DNS w interfejsie DNS CloudflarePrzykład konfiguracji DNS w interfejsie DNS Cloudflare

Po skonfigurowaniu DNS możesz go zweryfikować, uruchamiając:

host api.my-project.io

Powinieneś zobaczyć odpowiedź podobną do:

api.my-project.io is an alias for <XXXXXX>.stackhero-network.com

Propagacja DNS może zająć do 24 godzin w zależności od dostawcy. Jeśli polecenie host nie zwraca oczekiwanej odpowiedzi, poczekaj i spróbuj ponownie później.

Następnie zaktualizuj swój plik docker-compose.yml z następującą konfiguracją:

services:
  api:
    image: traefik/whoami
    hostname: api
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.api.rule=Host(`api.my-project.io`)" # Dodaj tutaj swoją domenę
      - "traefik.http.services.api.loadbalancer.server.port=<PORT>" # Zastąp "<PORT>" portem, na którym nasłuchuje Twoje API
      - "traefik.http.routers.api.tls.certresolver=letsencrypt"

Nie zapomnij zastąpić api.my-project.io swoją rzeczywistą domeną w etykiecie Traefik Host.

Wdróż swój kontener za pomocą:

docker-compose up -d

Następnie odwiedź https://api.my-project.io. Powinieneś zobaczyć stronę tekstową wyświetlającą nazwę hosta Twojego kontenera api.

Dowód, że Traefik obsługuje nasz ruch HTTP z szyfrowaniem TLS dla naszej nowej domenyDowód, że Traefik obsługuje nasz ruch HTTP z szyfrowaniem TLS dla naszej nowej domeny

Przy pierwszym tworzeniu kontenera certyfikaty TLS mogą zająć kilka sekund do wygenerowania. Jeśli napotkasz błąd TLS, poczekaj kilka sekund i odśwież stronę, aby dać czas na wygenerowanie certyfikatów.

Gratulacje, skonfigurowałeś swoją pierwszą niestandardową domenę!

Podczas definiowania adresu URL strony internetowej, takiego jak my-company.com, warto również skonfigurować subdomenę "www". Zapewnia to, że użytkownicy łączący się przez www.my-company.com są przekierowywani do Twojej głównej strony i pomaga unikać problemów z duplikatami treści.

W poniższym przykładzie obsługiwane są zarówno my-company.com, jak i www.my-company.com. Użytkownicy uzyskujący dostęp do www.my-company.com są przekierowywani do my-company.com:

services:
  frontend:
    image: traefik/whoami
    hostname: frontend
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.frontend.rule=Host(`my-company.com`) || Host(`www.my-company.com`)" # Dodaj tutaj obie domeny
      - "traefik.http.services.frontend.loadbalancer.server.port=<PORT>" # Zastąp "<PORT>" portem, na którym nasłuchuje Twój frontend
      - "traefik.http.routers.frontend.tls.certresolver=letsencrypt"

      # Przekieruj 'www.my-company.com' do 'my-company.com':
      - 'traefik.http.routers.frontend.middlewares=redirect-www'
      - "traefik.http.middlewares.redirect-www.redirectregex.regex=^https://www.my-company.com/(.*)"
      - "traefik.http.middlewares.redirect-www.redirectregex.replacement=https://my-company.com/$${1}"
      - "traefik.http.middlewares.redirect-www.redirectregex.permanent=true"

Załóżmy, że masz kontener dedykowany swojej stronie dokumentacji. Możesz chcieć przekierować https://my-company.com/docs do tego kontenera, jednocześnie wysyłając inne żądania, takie jak https://my-company.com/, do swojego kontenera frontend. Poniższy przykład pokazuje, jak to osiągnąć:

services:
  documentations:
    image: traefik/whoami
    hostname: documentations
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.documentations.rule=Host(`my-company.com`) && PathPrefix(`/docs`)" # Zdefiniuj tutaj prefiks ścieżki
      - "traefik.http.services.documentations.loadbalancer.server.port=<PORT>" # Zastąp "<PORT>" portem, na którym nasłuchuje Twój kontener dokumentacji
      - "traefik.http.routers.documentations.tls.certresolver=letsencrypt"

  frontend:
    image: traefik/whoami
    hostname: frontend
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.frontend.rule=Host(`my-company.com`) || Host(`www.my-company.com`)"
      - "traefik.http.services.frontend.loadbalancer.server.port=<PORT>" # Zastąp "<PORT>" portem, na którym nasłuchuje Twój frontend
      - "traefik.http.routers.frontend.tls.certresolver=letsencrypt"

      # Przekieruj 'www.my-company.com' do 'my-company.com':
      - 'traefik.http.routers.frontend.middlewares=redirect-www'
      - "traefik.http.middlewares.redirect-www.redirectregex.regex=^https://www.my-company.com/(.*)"
      - "traefik.http.middlewares.redirect-www.redirectregex.replacement=https://my-company.com/$${1}"
      - "traefik.http.middlewares.redirect-www.redirectregex.permanent=true"

Teraz, odwiedzając https://my-company.com/docs (lub dowolną podścieżkę, taką jak https://my-company.com/docs/something), zobaczysz zawartość z kontenera documentations. Inne ścieżki, na przykład https://my-company.com/help, będą obsługiwane przez kontener frontend.

Domyślnie Traefik łączy się z pierwszym wystawionym portem kontenera. W niektórych przypadkach możesz potrzebować określić konkretny port. Poniższy przykład pokazuje, jak zdefiniować niestandardowy port:

services:
  frontend:
    image: traefik/whoami
    hostname: frontend
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.frontend.rule=Host(`my-company.com`)"
      - "traefik.http.routers.frontend.tls.certresolver=letsencrypt"

      # Przekieruj ruch z 'https://my-company.com' do kontenera 'frontend' na porcie 80
      - "traefik.http.services.frontend.loadbalancer.server.port=80"

Podczas definiowania kontenera w pliku docker-compose.yml, kilka pól jest ważnych dla lepszej spójności i łatwości zarządzania. Rozważ użycie następującej zalecanej konfiguracji:

services:
  <CONTAINER_NAME>:
    image: traefik/whoami
    hostname: <CONTAINER_NAME>
    container_name: <CONTAINER_NAME>
    restart: unless-stopped
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.<CONTAINER_NAME>.rule=Host(`my-company.com`)"
      - "traefik.http.routers.<CONTAINER_NAME>.tls.certresolver=letsencrypt"

Po prostu zastąp <CONTAINER_NAME> pożądaną nazwą dla swojego kontenera, na przykład frontend.

Podczas tworzenia subdomeny Let's Encrypt przestrzega RFC 952 i 1123, które pozwalają tylko na znaki z zestawu [a-zA-Z0-9-].

Chociaż podkreślenia ('_') są dozwolone w nazwach rekordów DNS, nie są akceptowane w nazwach hostów. W rezultacie Let's Encrypt odrzuca subdomeny takie jak "my_subdomain.example.com" i wyświetla błąd "Domain name contains an invalid character".

Aby rozwiązać ten problem, po prostu usuń wszelkie podkreślenia ze swoich subdomen.