Docker Compose i sieci - dlaczego API nie łączy się z bazą?

Tymoteusz Maciejewski • 27 października 2026
Ośmiornica z klockami symbolizuje Docker Compose, narzędzie do zarządzania sieciami kontenerów.

Spis treści

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.

Diagram ilustrujący docker compose network z dwoma usługami web i bazami danych, połączonymi różnymi sieciami.

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-shared

W 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.

FAQ - Najczęstsze pytania

W kontenerze wartość `localhost` oznacza ten sam kontener, a nie bazę danych. Jeśli usługa bazy nazywa się `db`, aplikacja powinna używać hosta `db` i portu kontenera, na przykład `db:5432`. Mapowanie `15432:5432` służy do połączeń z hosta i nie zmienia adresu używanego przez inne kontenery w tej samej sieci.

Zdefiniuj sieci, na przykład `frontend` i `backend`, a następnie przypisz je konkretnym usługom. `proxy` może należeć tylko do `frontend`, `api` do obu sieci, a `db` tylko do `backend`. Usługi komunikują się wtedy, gdy mają przynajmniej jedną wspólną sieć, więc proxy nie połączy się bezpośrednio z bazą.

Utwórz wcześniej wspólną sieć poleceniem `docker network create app-shared`. W obu plikach Compose zadeklaruj ją jako `external: true` z tą samą nazwą i dołącz tylko usługi, które muszą się komunikować. Połączenie kieruj do nazwy usługi widocznej w tej sieci, a nie do nazwy katalogu projektu.

Jeśli nazwa usługi się nie rozwiązuje, sprawdź, czy usługi mają wspólną sieć i czy host został wpisany poprawnie. Komunikat `connection refused` zwykle oznacza, że proces nie nasłuchuje na wskazanym porcie albo działa tylko na loopbacku. Przy diagnostyce użyj `docker compose config`, `docker network inspect` oraz testu uruchomionego przez `docker compose exec`.

Oceń artykuł

Ocena: 4.70 Liczba głosów: 10

Tagi

docker compose
kontenery
dns
sieci
Autor Tymoteusz Maciejewski
Tymoteusz Maciejewski
Moje dni wypełnia zgłębianie kodu i analiza nowych technologii, zawsze z myślą o tym, jak najlepiej przekazać tę wiedzę dalej. Nazywam się Tymoteusz Maciejewski i od 12 lat aktywnie działam w świecie programowania, technologii i kariery w IT. Interesuje mnie nie tylko samo tworzenie oprogramowania, ale także proces, który prowadzi do zrozumienia złożonych zagadnień i uporządkowania ich w przystępny sposób. Na lukasz-zielinski.pl staram się dzielić się tym, co sam odkrywam, sprawdzając informacje u podstaw i dbając o to, by treści były aktualne i zrozumiałe dla każdego, kto chce rozwijać się w tej dynamicznej branży.

Udostępnij artykuł

Napisz komentarz