API w kontenerze nie łączy się z bazą, choć oba serwisy działają? W Docker Compose najczęściej wystarczy użyć nazwy usługi zamiast `localhost`, ale to zadziała tylko wtedy, gdy kontenery mają wspólną sieć. Sam wpis `networks` w pliku nie podłącza jeszcze usługi - trzeba przypisać sieć zarówno do definicji, jak i do konkretnych serwisów.
Najkrótsza droga do działającej sieci
- Domyślna sieć wystarcza, gdy wszystkie usługi są w jednym projekcie Compose.
- Nazwa usługi, na przykład `db`, jest adresem hosta dla innych kontenerów w tej samej sieci.
- Własne sieci pozwalają rozdzielić dostęp między warstwą aplikacji, proxy i bazą.
- Sieć zewnętrzna łączy osobne projekty, ale musi istnieć przed uruchomieniem Compose.
- Port kontenera służy do komunikacji między kontenerami; port hosta jest potrzebny do połączeń spoza Dockera.

Domyślna sieć załatwia większość aplikacji
W typowym projekcie Compose nie musisz deklarować sieci ręcznie. Po uruchomieniu konfiguracji narzędzie tworzy sieć domyślną projektu, a usługi w niej mogą odnajdywać się po nazwach z sekcji `services`. Dla małej aplikacji webowej i bazy to zwykle najlepszy początek: mniej YAML-a, mniej miejsc na literówkę.
Jeśli usługa aplikacji nazywa się `api`, a baza `db`, połączenie z aplikacji powinno wskazywać host `db`, nie `localhost`. Wewnątrz kontenera `localhost` oznacza właśnie ten kontener. Z kolei `ports: ["15432:5432"]` mapuje port bazy na maszynę hosta: inny kontener w tej samej sieci nadal łączy się przez `db:5432`.
Docker może przydzielić kontenerowi inny adres IP po jego odtworzeniu, więc nie wpisuj adresów IP na stałe do konfiguracji aplikacji. Nazwa usługi pozostaje stabilnym punktem odniesienia, choć po przerwaniu istniejącego połączenia klient musi ponownie połączyć się z usługą. Tak opisuje to dokumentacja sieci Docker Compose.
Podział na sieci ogranicza, kto widzi bazę
Gdy jeden kontener ma obsługiwać ruch z proxy i rozmawiać z bazą, a proxy nie powinno widzieć bazy bezpośrednio, rozdziel usługi na dwie sieci. Usługi komunikują się, gdy mają przynajmniej jedną wspólną sieć; sama obecność w tym samym pliku Compose nie daje im dostępu do każdej sieci.
services:
proxy:
image: nginx
networks:
- frontend
api:
image: example/api
networks:
- frontend
- backend
db:
image: postgres
networks:
- backend
networks:
frontend:
backend:W tym układzie `proxy` może dotrzeć do `api`, a `api` do `db`; `proxy` i `db` nie mają wspólnej sieci. Uważam, że taki prosty podział jest czytelniejszy niż próba zabezpieczenia wszystkiego samymi nazwami usług. Sieć porządkuje dostęp, ale nie zastępuje uwierzytelniania ani zabezpieczeń samej bazy.
Możesz też ustawić `internal: true` dla sieci, która ma być odizolowana od zewnętrznej łączności. Uważaj jednak na usługę dołączoną równocześnie do takiej sieci i do zwykłej sieci: nadal może korzystać z połączenia zewnętrznego przez tę drugą. Opis opcji `internal`, `external` i domyślnej sieci znajdziesz w specyfikacji sieci Docker Compose.
Osobne projekty połączysz przez sieć external
Dwa niezależne pliki Compose tworzą zwykle osobne sieci domyślne. Dlatego frontend z jednego projektu nie zobaczy automatycznie API z drugiego, nawet jeśli oba stoją na tym samym hoście. Wspólna sieć zewnętrzna daje im wspólny kanał komunikacji, bez przenoszenia wszystkich usług do jednego pliku.
services:
api:
image: example/api
networks:
- shared
networks:
shared:
external: true
name: app-sharedW drugim projekcie deklarujesz tę samą sieć zewnętrzną i dołączasz do niej usługę, która ma się komunikować z API. Sieć trzeba utworzyć wcześniej, na przykład poleceniem `docker network create app-shared`; jeśli jej brakuje, Compose zgłosi błąd zamiast utworzyć ją za Ciebie. W adresie połączenia użyj nazwy usługi widocznej w tej sieci, a nie nazwy katalogu projektu.
Sieć wspólna zwiększa zasięg widoczności usług, więc nie podłączaj do niej całego stosu bez potrzeby. Rozsądny układ to udostępnić w niej tylko API lub proxy, a bazę pozostawić w prywatnej sieci projektu.
Błąd połączenia rozpoznasz po tym, co dokładnie nie działa
Komunikat „connection refused” i błąd rozwiązywania nazwy wskazują na różne problemy. Zamiast zmieniać losowo porty, sprawdź, czy usługi dzielą sieć, czy host jest poprawny i czy proces rzeczywiście nasłuchuje na porcie kontenera.
| Objaw | Prawdopodobna przyczyna | Co sprawdzić |
|---|---|---|
| Host `localhost` działa tylko z hosta | Kontener próbuje połączyć się z samym sobą | Użyj nazwy usługi, np. `db`, i portu kontenera |
| Nazwa usługi nie rozwiązuje się | Usługi nie mają wspólnej sieci albo nazwa hosta jest błędna | Sprawdź przypisanie `networks` oraz nazwę w konfiguracji klienta |
| Nazwa działa, ale połączenie jest odrzucane | Proces nie nasłuchuje na tym porcie albo działa tylko na loopbacku | Sprawdź port i adres nasłuchiwania procesu w kontenerze docelowym |
| Compose zgłasza brak sieci | Sieć oznaczona jako `external` nie została wcześniej utworzona | Utwórz ją poleceniem `docker network create` albo popraw nazwę |
Przy diagnostyce zacznij od konfiguracji po scaleniu: `docker compose config` pokazuje model, który Compose zastosuje po uwzględnieniu plików i zmiennych. Potem sprawdź członków sieci przez `docker network inspect app-shared` albo uruchom test z wnętrza kontenera poleceniem `docker compose exec api ...`. Najpierw ustal, czy problem dotyczy DNS, wspólnej sieci czy portu; dopiero potem zmieniaj YAML.
Wybierz najmniejszą sieć, która rozwiązuje problem
Jeśli wszystkie usługi należą do jednego projektu i nie potrzebujesz izolować warstw, pozostaw sieć domyślną. Gdy chcesz ograniczyć bezpośredni dostęp do bazy, dodaj osobne sieci; gdy komunikują się osobne projekty, zastosuj sieć zewnętrzną i dołącz do niej tylko potrzebne usługi.
Nie publikuj portu bazy na hoście tylko po to, by API w kontenerze mogło do niej dotrzeć. Wystarczy wspólna sieć i port kontenera. W rezultacie konfiguracja pozostaje prostsza, a przypadkowy dostęp z zewnątrz nie wynika z samej potrzeby komunikacji między usługami.
