Mam dwie aplikacje (app1 i app2) na localhoscie. Baza danych znajduje sie w app1. Musze polaczyc dwie aplikacje to tej samej bazy danych z app1. App1 polaczylem bezproblemu, bo wszystko jest na tym samym docker composer. Problem jest z app2. Nie moge polaczyc sie z baza danych z app2.
Czyli masz w jednym dockerze aplikację app1 i bazę? Nieładnie :P Prawilnie by było jakbyś miał aplikację i bazę w osobnych dockerach.
No ale wracając do twojego problemu. Czy docker z bazą wystawia porty dla bazy? No bo co w zasadzie oznacza Nie moge polaczyc sie z baza danych z app2.
?
W tym towim opisie jest strqszny chaos. Narysuj vo gdzie masz. Możliwe że masz podefiniowane różne sieci dla tych rozwiązań.
KamilAdam napisał(a):
Czyli masz w jednym dockerze aplikację app1 i bazę? Nieładnie :P Prawilnie by było jakbyś miał aplikację i bazę w osobnych dockerach.
Jest jakiś powód ku temu? Oprócz tego że się da?
Parę razy się nad tym zastanawiałem, i nie widzę specjalnej różnicy.
Jedyny argument jaki widzę za, to jeśli nie budujesz swoich obrazów tylko używasz np domyślny h nginx-alpine
i mysql
, to wsadzasz takie dwa bezpośrednio w docker-compose
i jest. Ale jak i tak robisz swój obraz z Dockerfile
to w sumie co za różnica? Mogłoby być w jednym.
App1 to aplikacja, ktora istnieje juz bardzo dlugo. Chce napisac maly serwis (app2), ktory bedzie korzystal z bazy danych z docker-compose app1. Tylko, ze nie moge polaczyc sie z app2 z baza danych z app1 :( Nie uzywam network w zadnych z dwoch docker-compose plikow. Zaraz je poustawiam i moze wystawie porty bazy danych. Bo nie wiem w czym problem.
Troche niebardzo...
Odnoszę wrażenie, że wrzucenie zawartości plików Compose pomogłoby uzyskać obraz sytuacji.
Na bardzo uproszczonej ilustracji przedstawiam, jak ja to rozumiem:
Jeśli tak, jak wspomniałeś – wystarczy utworzyć sieć typu mostek i podłączyć istniejące kontenery:
Klasyczne rozwiązanie
# Utworzenie sieci:
docker network create --driver bridge some_network
# Podłączenie kontenerów do wspólnej sieci:
docker network connect some_network db1
docker network connect some_network app2
I to tyle. Można je skomunikować na gorąco – bez restartów i odtwarzania kontenerów.
Compose
Jeśli koniecznie w Compose – można w obu plikach zadeklarować poniższą konfigurację sieci domyślnej. Naturalnie pomijam zmienne środowiskowe – z tym powinieneś sobie poradzić: nazwa kontenera jako host i port, jeżeli nie jest domyślny.
networks:
default:
name: some_network
Po zmianie konieczne będzie utworzenie kontenerów na nowo, dlatego użycie bezpośrednio docker network
będzie wygodniejsze.
Riddle napisał(a):
KamilAdam napisał(a):
Czyli masz w jednym dockerze aplikację app1 i bazę? Nieładnie :P Prawilnie by było jakbyś miał aplikację i bazę w osobnych dockerach.
Jest jakiś powód ku temu? Oprócz tego że się da?
Parę razy się nad tym zastanawiałem, i nie widzę specjalnej różnicy.
Jedyny argument jaki widzę za, to jeśli nie budujesz swoich obrazów tylko używasz np domyślny h
nginx-alpine
imysql
, to wsadzasz takie dwa bezpośrednio wdocker-compose
i jest. Ale jak i tak robisz swój obraz zDockerfile
to w sumie co za różnica? Mogłoby być w jednym.
Oczywiscie, ze sa ku temu powody, a nawet cala masa. W najlepszym wypadku powinno sie miec 1 proces na kontener, bo:
- W innym wypadku entrypoint musi byc skryptem
- Masz jeden duzy kontener przez co w base image musisz trzymac duzo wiecej zaleznosci/libek, ktorych normalnie bys nie potrzebowal. Co gorsza czasami mozna sie przez to nabawic problemow w momencie kiedy appka i baza beda potrzebowac tego samego depa w innej wersji.
- Nie mozesz skalowac samej apki (przykladowo chce miec 10 apek i 1 db, a nie 10 apek i 10 db)
- Utrudnione debugowanie. Jezeli kontener failuje to znaczy, ze jakis proces sfailowal. W tej sytuacji nie wiadomo od razu czy jest to wina apki, czy bazy.
- Ograniczenie uzywalnosci/elastycznosci, niektore kontenery mozna wykorzystywac wielokrotnie lub tez w lekko zmodyfikowanym stylu (np sidecar pattern)
Mysle, ze znalazloby sie drugie tyle powodow, te po prostu od razu przyszly mi do glowy.
Wyglada, ze z network dziala.
Drugi sposób, to jak wystawiasz port bazy na localhost to w drugiej apce możesz po prostu podłączyć się do bazy przez host.docker.internal
zamiast adresu IP typu localhost
czy nazwy kontenera typu myapppDB
Wtedy masz stałe ustawienia, nic nie trzeba klikać i pamiętać poleceń przy uruchamianiu.
Riddle napisał(a):
KamilAdam napisał(a):
Czyli masz w jednym dockerze aplikację app1 i bazę? Nieładnie :P Prawilnie by było jakbyś miał aplikację i bazę w osobnych dockerach.
Jest jakiś powód ku temu? Oprócz tego że się da?
Parę razy się nad tym zastanawiałem, i nie widzę specjalnej różnicy.
Jedyny argument jaki widzę za, to jeśli nie budujesz swoich obrazów tylko używasz np domyślny h
nginx-alpine
imysql
, to wsadzasz takie dwa bezpośrednio wdocker-compose
i jest. Ale jak i tak robisz swój obraz zDockerfile
to w sumie co za różnica? Mogłoby być w jednym.
@Riddle: , @KamilAdam : Jak rozumiecie "osobne dockery"? Obrazy (Dockerfile) czy deployment (docker-compose) ?
@Riddle @yarel Sorry, dużo pracy w pracy i po pracy. Tak, mam na myśli osobne kontenery. Czy mam jakis papier czemu baza powinna być w osobnym kontenerze? Nie, nie mam. Tak było w tutorialach sprzed 5 lat na które trafiłem. Uzasadnienie było takie że lepiej widzać w docker ps
co działa a co nie i nie trzeba logować się do dockera żeby diagnozować. Pozostałe uzasadnienia na które trafiłem później to łatwiejsze logowanie i zbieranie logów przez systemo do tego dedykowane. Po prostu każde "źródło logów" (jak np aplikacja) pisze na standardowe wyjście i zewnętrzny system do zbierania logów już to sobie ogarnia. Z innych zalet to że jesteśmy już w "pół drogi" do skalowanej aplikacji. No bo jak mamy osobno aplikację w dockerze to jak nam ruch wzrośnie to wystarczy postawić ją sobie w X instancjach (oczywiście o ile jest bezstanowa a my mamy load balacer czy proxy z przodu). Nie możemy tak zrobić jak mamy aplikację i bazę w tym samym dockerze raczej z oczywistych względów :P
No, ale jak piszę tutoriale o dockerze czytałem 5 lat temu, może coś się zmieniło w idei dzielenia na dockery przez ostatnie 5 lat
@KamilAdam: osobne kontenery wydają się dobrą praktyką. Myślałem, że chodzi o zbudowanie jednego obrazu, z którego tworzone jest wiele kontenerów, ale jeśli w ramach jednego kontenera chcemy uruchomić wiele komponentów, to siłą rzeczy będzie jeden obraz.
Przy osobnych kontenerach:
- przydzielone zasoby można kontrolować per kontener (a jak w kontenerze masz kilka komponentów, to staje się to bardziej złożone i może generować pewne ograniczenia, tj. wewnątrz kontenera trzeba by mieć możliwość wpływania na ustawienia cgroups, co wydaje się trochę ryzykowne, z konteneraA zmieniam cgroups dla hosta i konteneraB :D )
- wszystko w jednym kontenerze -> zależności systemowe są współdzielone (podbicie wersji zależności może być dobre dla jednego komponentu, ale niekoniecznie dla drugiego)
- mniej zależności -> prostsze podbicie, wersji, potencjalnie mniej luk bezpieczeństwa (app i baza mogą używać osobny base imageów)
- budowanie obrazów dla osobnych kontenerów może być robione w parallelu (szybszy build niż sekwencyjnie dorzucanie np. bazy + aplikacji; obrazy można skanować pod kątem bezpieczeństwa w parallelu)
- zasada "single responsibility" spełniona, a wiadomo, że jak
proszekcoś jest do wszystkiego...
Na plus używania tego samego kontenera:
- komunikacja międzyprocesowa może być szybsza (np. via SHM, czy kolejki systemowe)
- ścieżka sieciowa skrócona (pomijamy stos dockerowy)
- możemy komponenty zapakować jako usługi systemowe (np. systemd i zwalić na ten podsystem zarządzanie kolejnością uruchamiania czy restartów)
KamilAdam napisał(a):
@Riddle @yarel Sorry, dużo pracy w pracy i po pracy. Tak, mam na myśli osobne kontenery. Czy mam jakis papier czemu baza powinna być w osobnym kontenerze? Nie, nie mam. Tak było w tutorialach sprzed 5 lat na które trafiłem. Uzasadnienie było takie że lepiej widzać w
docker ps
co działa a co nie i nie trzeba logować się do dockera żeby diagnozować. Pozostałe uzasadnienia na które trafiłem później to łatwiejsze logowanie i zbieranie logów przez systemo do tego dedykowane. Po prostu każde "źródło logów" (jak np aplikacja) pisze na standardowe wyjście i zewnętrzny system do zbierania logów już to sobie ogarnia. Z innych zalet to że jesteśmy już w "pół drogi" do skalowanej aplikacji. No bo jak mamy osobno aplikację w dockerze to jak nam ruch wzrośnie to wystarczy postawić ją sobie w X instancjach (oczywiście o ile jest bezstanowa a my mamy load balacer czy proxy z przodu). Nie możemy tak zrobić jak mamy aplikację i bazę w tym samym dockerze raczej z oczywistych względów :P
No okej, coś w tym jest.
Należałoby rozważyć za i przeciw i jakąś rozsądną konkluzję z tego wyciągnąć.
Bo ja np nie lubię odpalić docker-compose
a jakiejś prostej aplikacji, i zobaczyć 15 kontenerów. Potem uczysz się aplikacji miesiąc, i się dowiadujesz że połowa kontenerów jest dodane właściwie po nic.