Mam kilka kontenerów Docker działających jak:
- Nginx
- Aplikacja internetowa 1
- Aplikacja internetowa 2
- PostgreSQL
Ponieważ Nginx musi łączyć się z serwerami aplikacji internetowych w aplikacji internetowej 1 i 2, a aplikacje internetowe muszą komunikować się z PostgreSQL, mam takie linki:
- Nginx --- link ---> Aplikacja internetowa 1
- Nginx --- link ---> Aplikacja internetowa 2
- Aplikacja internetowa 1 --- link ---> PostgreSQL
- Aplikacja internetowa 2 --- link ---> PostgreSQL
Na początku działa to całkiem dobrze. Jednak kiedy tworzę nową wersję aplikacji internetowej 1 i aplikacji internetowej 2, muszę je wymienić. Ja tylko usuwam kontenery aplikacji internetowej, konfiguruję nowe kontenery i uruchamiam je.
W przypadku kontenerów aplikacji internetowych ich adresy IP na początku wyglądałyby następująco:
- 172.17.0.2
- 172.17.0.3
A po ich wymianie będą miały nowe adresy IP:
- 172.17.0.5
- 172.17.0.6
Teraz te ujawnione zmienne środowiskowe w kontenerze Nginx nadal wskazują na stare adresy IP. Tu pojawia się problem. Jak wymienić kontener bez zrywania połączenia między kontenerami? Ten sam problem będzie dotyczył również PostgreSQL. Jeśli chcę zaktualizować wersję obrazu PostgreSQL, z pewnością muszę ją usunąć i uruchomić nową, ale potem muszę przebudować cały wykres kontenera, więc nie jest to idealne rozwiązanie do rzeczywistej pracy serwera.
źródło
Możesz użyć kontenera ambasadora . Ale nie łącz kontenera ambasadora ze swoim klientem, ponieważ stwarza to ten sam problem, co powyżej. Zamiast tego użyj udostępnionego portu kontenera ambasadora na hoście platformy docker (zwykle 172.17.42.1). Przykład:
objętość postgresów:
postgres-kontener:
ambasador-kontener na postgres:
Teraz możesz uruchomić kontener klienta postgresql bez łączenia kontenera ambasadora i uzyskać dostęp do postgresql na hoście bramy (zazwyczaj 172.17.42.1):
Teraz możesz zrestartować kontener ambasadora bez konieczności restartowania klienta.
źródło
Jeśli ktoś nadal jest ciekawy, musisz użyć wpisów hosta w pliku / etc / hosts dla każdego kontenera dockera i nie powinien polegać na zmiennych ENV, ponieważ nie są one aktualizowane automatycznie.
Dla każdego połączonego kontenera będzie wpis pliku hosta w formacie LINKEDCONTAINERNAME_PORT_PORTNUMBER_TCP itd.
Poniższy fragment pochodzi z dokumentów docker
źródło
Jest to zawarte w eksperymentalnej kompilacji dockera 3 tygodnie temu wraz z wprowadzeniem usług: https://github.com/docker/docker/blob/master/experimental/networking.md
Powinieneś być w stanie uzyskać dynamiczne łącze w miejscu, uruchamiając kontener Dockera z
--publish-service <name>
argumentami. Ta nazwa będzie dostępna przez DNS. Jest to trwałe przy ponownym uruchomieniu kontenera (o ile oczywiście ponownie uruchomisz kontener z tą samą nazwą usługi)źródło
wget -qO- https://experimental.docker.com/ | sh
aby zainstalować wersję eksperymentalnąpublish-service
opcję eksperymentalną . Teraz zamiast tego mają aliasy o zasięgu sieci. Zasadniczo to samo.Aby rozwiązać ten problem, możesz użyć linków dokowanych z nazwami.
Najbardziej podstawowa konfiguracja polega na utworzeniu najpierw nazwanego kontenera bazy danych:
następnie utwórz kontener WWW łączący się z bazą danych:
Dzięki temu nie musisz ręcznie łączyć kontenerów z ich adresami IP.
źródło
db
w tym przypadku) otrzyma nowy adres IP. Twój drugi kontener (zrestartowany lub nie) zachowa wartości ENV od momentu jego uruchomienia i jest bezużyteczny.net-alias
lub nazwy kontenera).dzięki podejściu OpenSVC można obejść ten problem:
za każdym razem, gdy wymieniasz kontener, masz pewność, że połączy się on z właściwym adresem IP.
Samouczek tutaj => Docker Multi Containers z OpenSVC
nie przegap części „złożonej orkiestracji” na końcu tuto, która może pomóc w uruchamianiu / zatrzymywaniu kontenerów we właściwej kolejności (1 podzbiór postgresql + 1 podzbiór webapp + 1 podzbiór nginx)
główną wadą jest to, że wystawiasz aplikacje webowe i porty PostgreSQL na adres publiczny, aw rzeczywistości tylko port tcp nginx musi być ujawniony publicznie.
źródło
Możesz także wypróbować metodę ambasadora polegającą na posiadaniu kontenera pośredniczącego tylko po to, aby zachować łącze w stanie nienaruszonym ... (zobacz https://docs.docker.com/articles/ambassador_pattern_linking/ ), aby uzyskać więcej informacji
źródło
Możesz powiązać porty połączeń obrazów ze stałymi portami na hoście i skonfigurować usługi, aby ich używać.
Ma to również swoje wady, ale może zadziałać w twoim przypadku.
źródło
Inną alternatywą jest skorzystanie z
--net container:$CONTAINER_ID
opcji.Krok 1: utwórz kontenery „sieciowe”
Krok 2: Wstrzyknij usługi do kontenerów „sieciowych”
Dopóki nie dotkniesz kontenerów „sieciowych”, adresy IP Twoich linków nie powinny ulec zmianie.
źródło
Alias o zasięgu sieci jest tym, czego potrzebujesz w tym przypadku. Jest to dość nowa funkcja, za pomocą której można „opublikować” kontener udostępniający usługę dla całej sieci, w przeciwieństwie do aliasów odsyłaczy dostępnych tylko z jednego kontenera.
Nie dodaje żadnego rodzaju zależności między kontenerami - mogą się komunikować, dopóki oba są uruchomione, niezależnie od ponownych uruchomień, zamiany i kolejności uruchamiania. Uważam, że używa wewnętrznie DNS zamiast / etc / hosts
Użyj go w ten sposób:
docker run --net=some_user_definied_nw --net-alias postgres ...
i możesz połączyć się z nim za pomocą tego aliasu z dowolnego kontenera w tej samej sieci.Nie działa w domyślnej sieci, niestety musisz ją utworzyć,
docker network create <network>
a następnie używać z--net=<network>
każdym kontenerem ( kompozycja też ją obsługuje ).Oprócz tego, że kontener jest wyłączony, a tym samym nieosiągalny przez alias, wiele kontenerów może również współdzielić alias, w którym to przypadku nie ma gwarancji, że zostanie on rozwiązany na właściwy. Ale w niektórych przypadkach może to pomóc w bezproblemowej aktualizacji.
Na razie nie jest to dobrze udokumentowane, trudno to rozgryźć, czytając tylko stronę podręcznika.
źródło