Docker od wersji 1.1 umożliwia na wykrywanie usług za pomocą aliasu. Jest to osiągalne poprzez demon Dockera, który posiada zaimplementowany wbudowany serwer DNS.
W praktyce oznacza to, że tworząc plik konfiguracyjny dla Docker Compose możemy posługiwać się nazwami usług (aliasami) bez konieczności wskazywania ich adresu. W tym artykule przedstawię Ci najbardziej przydatne polecenia i przykłady, które ułatwią Ci konfiguracje sieci kontenerów.
Opcje konfiguracji ustawień DNS kontenera
- –name=CONTAINER-NAME – przypisanie nazwy dla kontenera, za pomocą którego będzie można wyszukać go w sieci Dockerowej. Wbudowany serwer DNS przechowuje mapowanie między nazwą kontenera a jego adresem IP (w sieci, do której nastąpiło przyłączenie kontenera).
- –network-alias=ALIAS – możliwość przypisania aliasu dla kontenera, który działa na podobnej zasadzie jak nazwa. Różnicą jest to, że kontener może mieć różne aliasy w różnych sieciach.
- –link=CONTAINER_NAME:ALIAS – użycie tej opcji podczas uruchamiania kontenera tworzy wpis w DNS o nazwie ALIAS, który wskazuje adres IP kontenera zidentyfikowany przez CONTAINER_NAME.
- –dns=[IP_ADDRESS…] – adresy IP podawane za pomocą opcji –dns są używane przez wbudowany serwer DNS do przekazywania zapytań DNS gdy wbudowany serwer DNS nie jest w stanie przetworzyć żądania rozpoznania nazw poszczególnych kontenerów (te adresy IP zarządzane są przez wbudowany serwer DNS i nie będą aktualizowane w pliku /etc/resolv.conf kontenera.)
- –dns-search=DOMAIN… – ta opcja jest zarządzana przez serwer DNS i nie dokona ona aktualizacji pliku /etc/resolv.conf kontenera (przykład – gdy proces kontenerowy próbuje uzyskać dostęp do hosta i gdy domena wyszukiwania example.com jest ustawiona. W danej instancji logika DNS nie tylko szuka hosta, ale także „host.example.com”).
- –dns-opt=OPTION… – ustawia opcje używane przez resolvery DNS. Opcjami tymi zarządza wbudowany serwer DNS i nie zostaną zaktualizowane w pliku /etc/resolv.conf kontenera.
Zasada działania DNS dla Docker
W przypadku opcji:
- –dns=[IP_ADDRESS…]
- –dns-search=DOMAIN…
- –dns-opt=OPTION…
Docker używa pliku /etc/resolv.conf, należącego do maszyny-hosta (maszyny, w której zostaje wywołany demon Dokera). W ten sposób demon odfiltrowuje wszystkie wpisy serwera nazw IP hosta lokalnego z oryginalnego pliku hosta.
Filtrowanie jest konieczne, ponieważ wszystkie adresy localhost są nieosiągalne z sieci kontenera. Po odfiltrowaniu, gdy w pliku /etc/resolv.conf kontenera nie ma już wpisów serwera nazw, to demon dodaje publiczne serwery nazw Google DNS (8.8.8.8 i 8.8.4.4) do konfiguracji DNS kontenera. Jeśli w demonie włączono IPv6, to zostaną również dodane publiczne serwery nazw Google DNS IPv6. W przypadku dostępu do resolvera localhosta, konieczna jest modyfikacja usługi DNS na hoście żeby nasłuchiwał adresu hosta nielokalnego, który jest dostępny z poziomu kontenera.
Docker Compose – przykład wykorzystania DNS
W przypadku Docker Compose konfigurowana jest jedna sieć dla aplikacji. Każdy kontener dla usługi dołącza do domyślnej sieci i jest dostępny zarówno dla innych kontenerów w tej sieci oraz inne kontenery mogą go odnaleźć pod nazwą hosta identyczną do nazwy kontenera. Sieć aplikacji otrzymuje nazwę opartą na nazwie projektu (która wzoruje się na nazwie katalogu w którym projekt jest zawarty). Nazwę projektu można podmienić przy użyciu flagi:
-project-name
lub używając zmienną środowiskową COMPOSE_PROJECT_NAME.
Przy założeniu, że aplikacja znajduje się w katalogu SpringApp plik docker-compose.yml zawiera treść:
version: "3" services: web: build: . ports: - "8000:8000" db: image: postgres ports: - "8001:5432"
Można wywnioskować, że po wykonaniu polecenia docker-compose up wykonają się następujące czynności:
- Zostanie utworzona sieć o nazwie SpringApp_default
- Kontener zostanie utworzony przy użyciu konfiguracji paramentu „web”. Dołącza on do sieci SpringApp_default pod nazwą „web”.
- Kontener zostanie utworzony przy użyciu konfiguracji paramentu „db”. Dołącza on do sieci SpringApp_default pod nazwą „db”.
Każdy kontener może teraz wyszukać „web” bądź „db” i otrzymać adres IP odpowiedniego kontenera. Na przykład kod aplikacji „web” może połączyć się z adresem URL postgres://db:5432 i rozpocząć korzystanie z bazy danych Postgres.
Różnice pomiędzy HOST A CONTAINER PORT
Należy zauważyć różnicę między HOST_PORT a CONTAINER_PORT. W naszym przykładzie dla „db” HOST_PORT ma wartość 8001, a port kontenera – 5432 (jest to port domyślny dla Postgresa). Sieciowa komunikacja między usługami korzysta z CONTAINER_PORT. Po zdefiniowaniu HOST_PORT usługa jest dostępna również poza rojem (swarm’em).
Można też skorzystać z linków (łącz) – pozwalają one zdefiniować dodatkowe aliasy, za pomocą których usługa jest osiągalna z innej usługi. Nie są wymagane do umożliwienia komunikacji między serwisami (w przykładzie services) – domyślnie każda usługa może dotrzeć do dowolnego innego serwisu o nazwie tej usługi.
Można również zmienić ustawienia domyślnej sieci dla całej aplikacji zamiast (bądź też) określania własnych sieci, definiując wpis w networks o nazwie default:
version: "3" services: web: build: . ports: - "8000:8000" db: image: postgres networks: default: # Use a custom driver driver: custom-driver-1