Użycie Traefika v2 do tworzenia proxy dla kontenerów Docker w celach developerskich na localhost

Grudzień 9, 2023 | #docker , #localhost , #traefik

000000
011011
000101
110100

Po co używać Traefika na localhost?

Użycie Traefik-a na localhost, czyli w środowisku deweloperskim na lokalnym komputerze, może przynieść kilka istotnych korzyści, szczególnie w kontekście rozwoju aplikacji bazujących na kontenerach.

Symulacja środowiska produkcyjnego

Traefik pozwala na lepsze odwzorowanie konfiguracji sieciowej, którą znajdziesz w środowisku produkcyjnym. Używanie go na localhost ułatwia testowanie i rozwój aplikacji w warunkach zbliżonych do realnych jak choćby zarządzanie certyfikatami SSL/TLS. Traefik umożliwia zarządzanie certyfikatami nawet w środowisku deweloperskim, co jest przydatne przy testowaniu bezpiecznych połączeń HTTPS.

Narzędzie to ma wsparcie HTTP/2 ale obsługuje też inne nowoczesne protokoły jak np. WebSocket , co jest przydatne przy rozwijaniu i testowaniu aplikacji korzystających z tych technologii.

Używając Traefika, możesz łatwo skonfigurować i testować aplikacje działające na wielu domenach lub subdomenach, nawet jeśli są one uruchomione lokalnie.

Praca z wieloma serwisami

Jeśli pracujesz nad aplikacją składającą się np. z wielu mikroserwisów, Traefik może automatycznie zarządzać ruchem sieciowym pomiędzy nimi, co ułatwia ich testowanie. Traefik potrafi automatycznie wykryć i skonfigurować trasy dla nowych usług i kontenerów, co jest szczególnie przydatne w dynamicznie zmieniających się środowiskach deweloperskich, w których nie tylko trzeba zadbać o współpracę pomiędzy serwisami ale czasami też zachodzi potrzeba testowania balansowania obciążenia pomiędzy różnymi instancjami aplikacji lub serwisów.

Uruchamianie Traefika w Dockerze na localhost

W katalogu ./tarefik tworzymy plik docker-compose.yml. Treść pliku kopiujemy z Quick Start z oficjalnej dokumentacji Traefik-a. Jedyne co dodamy od siebie to definicję sieci, która będzie dostępna poza kontenerem, w którym zamknięte jest nasze reverse proxy.

version: '3'

services:
  reverse-proxy:
    # Oficjalny obraz Dokera z Traefik v2
    image: traefik:v2.10
    # Włącza dashboard and mówi Traefik-owi aby nasłuchiwał zdarzeń Dockera
    command: --api.insecure=true --providers.docker
    ports:
      # Numer portu dla HTTP
      - "80:80"
      # Port, pod którym będzie dostępny dashboard Traefik-a 
      # (włączony opcją --api.insecure=true)
      - "8080:8080"
    volumes:
      # Aby Traefik mógł słuchać zdarzeń Dockera
      - /var/run/docker.sock:/var/run/docker.sock:ro
    networks:
      # Niestandardowa sieć
      - traefik_network

networks:
  traefik_network:
    # Ta opcja sprawia, że sieć jest dostępna na zewnątrz
    external: true

Tak jak jest napisane w "Szybkim Starcie" - to wszystko czego potrzebujemy by Traefik był gotowy do pracy.

# jeszcze tylko tworzymy zewnętrzną sieć
docker network create traefik_network
# i odpalamy
docker compose up -d reverse-proxy

Dashboard Traefika w przeglądarce internetowej dostępny jest pod adresem localhost:8080.

Można też odpytać api z konfiguracją Traefik-a.

curl http://localhost:8080/api/rawdata

Sprawdzanie czy Traefik sam wykryje nowy serwis i automatycznie utworzy trasę.

Aby to przetestować twórcy Traefik-a przygotowali prosty obraz Dockera, który po uruchomieniu i odpytaniu przez http zwraca nieco informacji o maszynie, na które został odpalony. W tym samym, albo innym katalogu tworzymy kolejny plik docker-compose.whoami.yml i ponownie kopiujemy jego treść z dokumentacji. Także tym razem dodajemy informację o sieci traefik_network.

version: '3'

services:
  whoami:
    image: traefik/whoami
    networks:
      - traefik_network
    labels:
      - "traefik.http.routers.whoami.rule=Host(`whoami.docker.localhost`)"

networks:
  traefik_network:
    external: true

Po uruchomieniu...

docker compose -f docker-compose.whoami.yml up -d whoami

... można ponownie sprawdzić konfigurację Traefik-a - tym razem formatując wynik w json-ie dla lepszej czytelności.

curl http://localhost:8080/api/rawdata | python3 -m json.tool

Zmiany widać też w dashboardzie /dashboard/#/http/routers.

Jak się sam przekonałem, to że Traefik wykrył nowy serwis nie oznacza jeszcze, że aplikacja jest poprawnie serwowana więc koniecznym jest także odwiedzenie nowego serwisu w przeglądarce whoami.docker.localhost lub odpytanie w konsoli:

curl http://whoami.docker.localhost

Konfigurowanie Django z Traefik-iem na komputerze lokalnym

Konfiguracja, którą przedstawię poniżej została uproszczona do maksimum aby nie zaciemniać istoty sprawy. Nie mniej jeśli chcesz szybko zainicjować nowy projekt Django w kontenerze Docker to możesz skorzystać z prostego przepisu.

Utwórzmy nowy katalog na potrzeby projektu Django ./django_with_traefik i wejdźmy do niego. W katalogu projektu utworzymy trzy pliki

cd ./django_with_traefik
touch Dockerfile requirements.txt docker-compose.yml

Plik Dockerfile

FROM python:3
ENV PYTHONDONTWRITEBYTECODE=1
ENV PYTHONUNBUFFERED=1
WORKDIR /code
COPY requirements.txt /code/
RUN pip install -r requirements.txt
COPY . /code/

Plik requirements.txt

Django>=3.0,<4.0

Plik docker-compose.yml

services:
  web:
    build: .
    command: python manage.py runserver 0.0.0.0:8000
    volumes:
      - .:/code
    ports:
      - "8000:8000"

Zainicjujmy projekt.

docker compose run --rm web django-admin startproject project_name .

Powyższa instrukcja zbudowała obraz na podstawie pliku Dockerfile i stworzyła na jego podstawie kontener, w którym została odpalona komenda Django tworząca nowy projekt. W katalogu projektu zostały utworzone pliki projektu tj. plik manage.py i katalog project_name wraz z zawartością. Ponieważ domyślnie w kontenerach procesy uruchamiane są na prawach root-a, właścicielem dopiero co utworzonych plików i folderów jest root. Dlatego przypisujemy je do naszego użytkownika.

sudo chown -R $USER:$USER project_name manage.py

Teraz tylko uruchamiamy serwis...

docker compose up

...i sprawdzamy.

Jeśli projekt działa pod adresem localhost:8000 dodajmy sieć traefik_network i kilka etykiet, które sprawią, że to samo zobaczymy też pod adresem web.docker.localhost

Plik docker-compose.yml

services:
  web:
    build: .
    command: python manage.py runserver 0.0.0.0:8000
    volumes:
      - .:/code
    ports:
      - "8000:8000"
    networks:
      - traefik_network
    labels:
      - "traefik.enable=true"
      - "traefik.docker.network=traefik_network"
      - "traefik.http.routers.web.rule=Host(`web.docker.localhost`)"
      - "traefik.http.services.web.loadbalancer.server.port=8000"
      
networks:
  traefik_network:
    external: true

Jak widać powyżej podpiąłem kontener web do sieci Traefik-a i jeszcze dodatkowo w etykiecie traefik.docker.network=traefik_network poinformowałem proxy jakiej sieci ma używać do komunikacji. W naszym przypadku podpięcie do jednej sieci jest całkowicie wystarczające, ale gdybyśmy chcieli dodać do pliku docker-compose.yml np. kontener z bazą danych PostgreSQL warto byłoby utworzyć kolejną - tym razem wewnętrzną sieć - która służyłaby do komunikacji kontenerów między sobą.

Pozostaje nam sprawdzić czy projekt dostępny jest pod adresem web.docker.localhost. Jeśli wszystko działa, możemy spróbować skonfigurować bezpieczne połączenie HTTPS.

Posprzątajmy po naszym eksperymencie z Traefikiem, Django i Dockerem na localhost

Jak już uznamy, że kontener whoami nie jest już nam dłużej potrzebny możemy usunąć go, jaki i jego obraz.

cd ./traefik
docker compose -f docker-compose.whoami.yml down && docker rmi traefik/whoami

Analogicznie możemy zrobić z serwisem Django - jeśli to był tylko eksperyment i kontenery nie są nam już dłużej potrzebne.

Akceptuję Ta strona zapisuje niewielkie pliki tekstowe, nazywane ciasteczkami (ang. cookies) na Twoim urządzeniu w celu lepszego dostosowania treści oraz dla celów statystycznych. Możesz wyłączyć możliwość ich zapisu, zmieniając ustawienia Twojej przeglądarki. Korzystanie z tej strony bez zmiany ustawień oznacza zgodę na przechowywanie cookies w Twoim urządzeniu.