Docker jest niesamowity. Kocham to. Prawdę mówiąc, naprawdę to kocham. Jeśli jednak każdego dnia pracujesz z ponad 10 mikrousługami, zarządzanie relacjami między tymi usługami podczas lokalnego rozwoju może być trudne.

W fazie produkcyjnej dysponujemy niezawodnymi domenami, za pomocą których możemy wyszukiwać inne usługi. Kiedy pracujemy lokalnie, jesteśmy zdani na zmienne środowiskowe Docker Compose i złożone połączenia w celu osiągnięcia lokalnych potoków. Prowadzi to do mylących i skomplikowanych konfiguracji, których nauczenie się 1) i 2) zajmuje dużo czasu nowym programistom.

O ile mi wiadomo, jest to nadal najpopularniejsza metoda wyszukiwania informacji o innych kontenerach Dockera podczas lokalnej pracy z Dockerem.

Wiem dobrze, wydaje się to zbyt piękne, aby mogło być prawdziwe… Cóż, tak nie jest. DNSDock to narzędzie, które umożliwia tę właśnie funkcję. DNSDock jest cytowany jako „wykrywanie usług DNS dla kontenerów Docker”, ja wolę to nazywać „siłą napędową lokalnego rozwoju Dockera”.

„Wykrywanie usług DNS dla kontenerów Docker”

Fajnie mówisz. Co to dokładnie oznacza? Oznacza to, że możesz przypisywać domeny do swoich kontenerów w pliku tworzenia dokera, a domeny te będą dostępne nie tylko dla innych kontenerów działających na Twojej maszynie wirtualnej, ale także dostępne dla Twojego komputera hosta.

Zastanawiasz się, jakie dane znajdują się w Twoim kontenerze Redis? Podłącz go bezpośrednio do RDM. Uruchamiasz PostgresSQL lub MySQL? Po prostu odpal Sequel Pro i spójrz. Chociaż wszystko to jest całkiem możliwe bez DNSDock, jest to także ogromna PITA!

Sweet, skoro już wiemy co i dlaczego, przyjrzyjmy się jak.

Cel końcowy

Najpierw przyjrzyjmy się oczekiwanemu wynikowi. Zasadniczo chcemy pliku Docker Compose, który wygląda tak…

# myapp/docker-compose.yml
redis:
  image: redis
  environment:
    DNSDOCK_NAME: cache
    DNSDOCK_IMAGE: myapp
  ports:
    - "6379":"6379"
mysql:
 image: mysql:5.6
  environment:
    DNSDOCK_NAME: db
    DNSDOCK_IMAGE: myapp
    MYSQL_ALLOW_EMPTY_PASSWORD: yes
  ports:
    — “3306:3306”
myapp:
  build: .
  environment:
    REDIS_HOST: cache.myapp.docker
    DB_HOST: db.myapp.docker
    HOST: api.myapp.docker
    DNSDOCK_NAME: api
    DNSDOCK_IMAGE: myapp
  ports:
    - "8001":"8001"

W tej konfiguracji nasz klient Redis jest dostępny pod adresem cache.myapp.docker, nasza baza danych mysql jest dostępna pod adresem db.myapp.docker, a nasze API jest dostępne pod adresem api.myapp.docker.

Teraz z naszego komputera hosta możemy łatwo przeglądać nasze dane Redis lub MySQL, a także uzyskiwać dostęp do interfejsu API za pośrednictwem naszej znormalizowanej nazwy domeny. Jeśli chcesz uruchomić inne usługi nadrzędne lub podrzędne, możesz po prostu ustawić zmienną środowiska API_HOST i nie będzie potrzeby dodawania skomplikowanych łączy Dockera i linków zewnętrznych.

Dzięki temu możemy mieć czyste zmienne środowiskowe inne niż Docker, których możemy używać we wszystkich środowiskach, zarówno wewnątrz, jak i na zewnątrz maszyny wirtualnej Docker. Możesz łatwo zastąpić REDIS_HOST i MYSQL_HOST w swoich środowiskach testowych i produkcyjnych, bez konieczności informowania aplikacji o tym, gdzie jest uruchamiana.

Jak można sobie wyobrazić, znacznie zmniejsza to wysiłek wymagany do uruchomienia złożonych systemów i uzyskania parytetu środowiskowego.

Jak się tam dostać

Co więc dokładnie jest potrzebne, aby zadziałała ta magia? Konfiguracja DNSDock jest nieco skomplikowana, ale gdy już ją poprawnie skonfigurujesz, Twoi przyjaciele i współpracownicy będą Cię chwalić jako bohatera, który uprościł proces lokalnego programowania.

Najpierw przyjrzyjmy się, jak działa DNSDock. (Uwaga dodatkowa: dokumentacja w repozytorium DNSDock jest znacznie lepsza niż cokolwiek, co mogłem udostępnić. Celem tego artykułu jest bardziej świadomość niż instrukcje.)

Dnsdock łączy się z Docker Remote API i utrzymuje aktualną listę uruchomionych kontenerów. Jeśli żądanie DNS pasuje do niektórych kontenerów, zwracane są ich lokalne adresy IP.

To wszystko, prosto z dokumentów. Jednak aby to działało na maszynie wirtualnej i komputerze hosta (ten artykuł skupia się na Mac OSX), musimy włożyć trochę pracy.

Konfigurowanie maszyny

Pierwszą rzeczą, którą musimy zrobić, to skonfigurować pewne informacje o routingu dla naszego komputera-hosta. Uruchomienie poniższych poleceń skonfiguruje komputer hosta tak, aby kierował wszelkie żądania do *.docker na adres IP komputera Docker.

# make resolver dir if it does not exist
sudo mkdir -p /etc/resolver >/dev/null 2>&1
# add nameserver entry for *.docker URLs
echo "nameserver 172.17.42.1" | sudo tee /etc/resolver/docker > /dev/null
# remove previous entry for DNSDocker in case docker machine has different IP
sudo route -n delete -net 172.17.0.0
# add entries to route table for docker machine
sudo route -n add 172.17.0.0/16 $(docker-machine ip <your_docker_machine_name>)
sudo route -n add 172.17.42.1/32 $(docker-machine ip <your_docker_machine_name>)

Konfigurowanie kontenera DNSDock

Teraz, gdy maszyna hosta jest skonfigurowana do obsługi przekazywania domen *.docker na maszynę Docker, możemy uruchomić kontener DNSDock i wypróbować naszą nową funkcjonalność.

Najpierw uruchommy kontener…

docker run -d -v /var/run/docker.sock:/var/run/docker.sock --name dnsdock -p 172.17.42.1:53:53/udp tonistiigi/dnsdock

Przyjrzyjmy się teraz, co to właściwie robi…

# share the docker socket to the container so that DNSDock can connect to the Docker API
-v /var/run/docker.sock:/var/run/docker.sock
# expose the default DNS port to the docker0 bridge interface
-p 172.17.42.1:53:53/udp

I to wszystko! Uruchom niektóre usługi za pomocą docker-compose, a powinieneś być w stanie uzyskać do nich dostęp z komputera hosta i z poziomu maszyny wirtualnej, niezależnie od przypisanej im nazwy domeny!

Mam nadzieję, że przyniesie Ci to tyle samo radości i wydajności, co mnie!

WSKAZÓWKI!

Możesz także ustawić zmienną DNSDOCK_ALIAS env env w pliku tworzenia okna dokowanego, co umożliwi Ci także skonfigurowanie aliasów dla kontenerów…

myapp:
  build: .
  environment:
    REDIS_HOST: cache.myapp.docker
    DB_HOST: db.myapp.docker
    HOST: api.myapp.docker
    DNSDOCK_NAME: api
    DNSDOCK_IMAGE: myapp
    DNSDOCK_ALIAS: api.v2.myapp.docker, m.api.myapp.docker, etc...
  ports:
    - "8001":"8001"

Możesz także ustawić żądany sufiks domeny, jeśli nie wolisz domyślnego ustawienia .docker

docker run -d -v /var/run/docker.sock:/var/run/docker.sock --name dnsdock -domain container -p 172.17.42.1:53:53/udp tonistiigi/dnsdock

Jeśli użyjemy naszego przykładu myapp, otrzymamy teraz adresy URL takie jak api.myapp.container. (Jeśli zmienisz domenę, będziesz musiał utworzyć serwer nazw dla tego sufiksu domeny, zobacz informacje o routingu powyżej.)

Podziękowanie

Chciałbym gorąco pozdrowić @steven.merrill z https://www.phase2technology.com/. Dziękuję za zapoznanie się z moim postem i pomoc w kwestiach technicznych!

Kolejna uwaga

Technologia Phase 2 umożliwiła mi dostęp w wersji beta do fantastycznych narzędzi dokowanych, które robią to wszystko za Ciebie! Zaglądaj tutaj, aby uzyskać aktualizację, gdy zostanie oficjalnie udostępniona jako oprogramowanie typu open source!