Sieci w Dockerze

You are currently viewing Sieci w Dockerze

Wstęp

W dzisiejszym wpisie poruszymy temat, który jest absolutnie kluczowy dla każdego, kto chce swobodnie i profesjonalnie poruszać się w świecie Dockera. Mowa o sieciach. Na początku swojej drogi z konteneryzacją pewnie skupiasz się na budowaniu obrazów i uruchamianiu pojedynczych kontenerów. Ale co, gdy Twoja aplikacja składa się z kilku serwisów, które muszą ze sobą rozmawiać? Backend musi odpytać bazę danych, frontend musi zawołać backend, a do tego dochodzi jeszcze jakiś Redis do keszowania.

Zapewne nieraz złapałeś się na tym, że próbujesz połączyć te klocki, żonglując adresami IP, bawiąc się dziwnymi flagami, a na końcu i tak coś nie działa. Kontenery się nie widzą, porty się blokują, a frustracja rośnie. Znam to doskonale.

Na szczęście Docker dostarcza wbudowane narzędzia sieciowe, które pozwalają mieć kontrolę nad sieciami w kontenerach. W tym wpisie pokażę Ci, jak działają sieci w Dockerze, jakie masz możliwości konfiguracji i jak uniknąć najczęstszych problemów. Przedstawię praktyczne przykłady, które pomogą Ci zrozumieć, kiedy używać którego typu sieci i jak debugować problemy z komunikacją między kontenerami.

Sieci w dockerze – podstawy (docker network)

Na początek przyjrzyjmy się bliżej podstawą sieci w Dockerze. To właśnie od zrozumienia tych mechanizmów zależy, czy Twoje kontenery będą ze sobą sprawnie współpracować, czy też utkniesz na etapie debugowania połączeń.

Czym są sięci w dockerze?

Najprościej mówiąc, sieć w Dockerze to wirtualna sieć komputerowa (LAN) stworzona specjalnie dla Twoich kontenerów. Kiedy tworzysz taką sieć, Docker działa jak wirtualny router – przydziela kontenerom adresy IP, zarządza ruchem i pozwala im na komunikację.

Dzięki temu kontenery działające w tej samej sieci mogą się nawzajem „widzieć” i komunikować, tak jak komputery podłączone do tego samego routera w Twoim domu. Co więcej, są one domyślnie odizolowane od kontenerów działających w innych sieciach, co daje nam świetne narzędzie do porządkowania i zabezpieczania naszych aplikacji.

Typy sieci

Docker oferuje kilka typów sieci, każdy z różnym przeznaczeniem:

Bridge Network – To domyślny i najczęściej używany typ sieci. Kiedy instalujesz Dockera, automatycznie tworzona jest sieć o nazwie bridge. Każdy kontener, który uruchomisz bez określania sieci, zostanie do niej podłączony. Kontenery na tej samej sieci bridge mogą się ze sobą komunikować po nazwie. Co ważniejsze, możesz tworzyć własne sieci typu bridge, co jest zdecydowanie rekomendowaną praktyką.

Host Network – W tym trybie kontener nie dostaje własnego, izolowanego stosu sieciowego. Zamiast tego korzysta bezpośrednio z interfejsu sieciowego maszyny-hosta (np. z Twojego komputera, na którym uruchamiasz kontener). Oznacza to brak izolacji na poziomie sieci. Jeśli Twoja aplikacja w kontenerze nasłuchuje na porcie 8000, będzie ona dostępna na porcie 8000 hosta, bez potrzeby mapowania portów. Daje to nieco lepszą wydajność, ale kosztem bezpieczeństwa i ryzyka konfliktów portów. Używaj go świadomie i tylko wtedy, gdy naprawdę musisz.

None Network – Jak sama nazwa wskazuje, kontener podłączony do tej sieci nie ma żadnego interfejsu sieciowego. Jest całkowicie odizolowany od świata. Przydaje się w bardzo specyficznych przypadkach, np. do uruchamiania zadań, które mają tylko przetwarzać dane i nie potrzebują żadnej komunikacji.

Overlay Network – To sieć przeznaczona do zastosowań w klastrach (grupa połączonych ze sobą komputerów, które ze sobą współpracują, aby działać jak jeden wspólny system), takich jak Docker Swarm czy Kubernetes. Pozwala kontenerom działającym na różnych maszynach-hostach komunikować się ze sobą tak, jakby były w jednej, płaskiej sieci. To temat na tyle duży, że można byłoby z tego zrobić cały osobny wpis.

Custom Bridge Networks – Pozwala przypisać kontenerowi adres MAC, dzięki czemu w sieci lokalnej wygląda on jak fizyczne urządzenie, a nie jak kontener schowany za hostem. Używane w bardziej zaawansowanych scenariuszach sieciowych.

Tworzenie własnych sieci

Domyślnie Docker tworzy kilka predefiniowanych sieci. Możesz je zobaczyć poleceniem:

docker network ls

Wynik będzie podobny do poniższego:

Wynik zapytania docker network ls

Na początek stwórzmy swoją pierwszą prostą sieć typu bridge:

docker network create my-network

Teraz ponownie wyświetlając listę sieci dostaniemy naszą nowo utworzoną sieć:

Wynik zapytania docker network ls po utworzeniu własnej sieci

Uruchomienie kontenera w sieci

Mamy już sieć, więc podłączmy do niej jakiś kontener. Użyjemy do tego flagi --network. Uruchommy kontener z bazą danych PostgreSQL w naszej nowej sieci:

docker run -d --name mydb --network my-network -e POSTGRES_PASSWORD=sekretnehaslo postgres

Przeanalizujmy tę komendę:

  • -d – Uruchamia kontener w tle (detached).
  • --name mydb – Nadajemy kontenerowi przyjazną nazwę. To bardzo ważne!
  • --network my-networkPodłączamy kontener do naszej sieci.
  • -e POSTGRES_PASSWORD=... – Zmienna środowiskowa wymagana przez obraz PostgreSQL.
  • postgres – Nazwa obrazu do uruchomienia.

Teraz nasz kontener mydb działa wewnątrz sieci my-network.

Mapowanie portów

W tej chwili nasza baza danych jest dostępna tylko dla innych kontenerów w tej samej sieci. Nie możemy się do niej podłączyć z naszej maszyny-hosta (np. przez DBeaver czy inne narzędzie). Aby to umożliwić, musimy zamapować port kontenera na port hosta.

Służy do tego flaga -p (publish) w formacie PORT_HOSTA:PORT_KONTENERA.

Zatrzymajmy i usuńmy poprzedni kontener, a następnie uruchommy go ponownie z mapowaniem portów:

docker stop mydb
docker rm mydb

docker run -d --name mydb --network my-network -p 5433:5432 -e POSTGRES_PASSWORD=sekretnehaslo postgres

Co się zmieniło? Dodaliśmy -p 5433:5432. Oznacza to: „weź ruch przychodzący na port 5433 mojej maszyny-hosta i przekaż go na port 5432 wewnątrz kontenera mydb„.

Dzięki temu możesz teraz połączyć się ze swoją bazą danych, używając adresu localhost:5433.

Uwaga! Mapowanie portów jest potrzebne tylko wtedy, gdy chcesz uzyskać dostęp do usługi z zewnątrz sieci Dockera. Kontenery w tej samej sieci będą komunikować się ze sobą bezpośrednio, bez mapowania portów.

Podglądanie i inspekcja sieci (docker network inspect)

Często musimy sprawdzić, które kontenery są podłączone do danej sieci, albo jakie mają adresy IP. Do tego służy poniższa komenda:

docker network inspect my-network

W odpowiedzi dostaniemy informację o sieci w postaci JSON:

[
    {
        "Name": "my-network",
        "Id": "99130b0e08c7f556f2488412124136dbcc933fd2c69a1189e2d00df45560c868",
        "Created": "2025-06-08T10:56:58.084759025Z",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": {},
            "Config": [
                {
                    "Subnet": "172.18.0.0/16",
                    "Gateway": "172.18.0.1"
                }
            ]
        },
        "Internal": false,
        "Attachable": false,
        "Ingress": false,
        "ConfigFrom": {
            "Network": ""
        },
        "ConfigOnly": false,
        "Containers": {
            "63e1dfc9d319a967a246c85e62ae31f92b407a2206f23226b35c4a8deb352c48": {
                "Name": "mydb",
                "EndpointID": "844cce952dc8559d85180a575b8a33f24d6a70d64918da11268759aeccd35e49",
                "MacAddress": "02:42:ac:12:00:02",
                "IPv4Address": "172.18.0.2/16",
                "IPv6Address": ""
            }
        },
        "Options": {},
        "Labels": {}
    }
]

Z tego wyniku można odczytać:

  • Jakie kontenery są podłączone do sieci
  • Jakie mają adresy IP
  • Konfigurację podsieci
  • Ustawienia IPAM (IP Address Management)

A w naszym przypadku widzimy, że nasz kontener mydb jest podłączony i ma wewnętrzny adres IP 172.18.0.2. Moglibyśmy używać tego adresu do komunikacji, ale za chwilę zobaczysz znacznie lepszy sposób.

Więcej o sieciach w Dockerze

W tym punkcie dalej skupimy się na temacie sieci w Dockerze, ale tym razem pójdziemy o krok dalej. Zagłębimy się w bardziej zaawansowane aspekty. Tutaj skupimy się na praktycznych rozwiązaniach, które pozwolą lepiej izolować sieć środowiska, efektywniej zarządzać komunikacją i unikać typowych pułapek w codziennej pracy.

Dostęp po nazwie kontenera (DNS w Dockerze)

Gdy kontenery znajdują się w tej samej, stworzonej przez użytkownika sieci bridge, Docker zapewnia automatyczne wykrywanie usług (service discovery) za pomocą wbudowanego serwera DNS.

Co to oznacza w praktyce? To, że nie musimy znać adresu IP kontenera. Możemy się do niego odwołać, używając jego nazwy.

Uruchommy 2 kontenery w tej samej sieci i następnie wejdźmy do jednego z naszych kontenerów:

# Tworzenie wspólnej sieci
docker network create my-network

# Tworzymy pierwszy kontener z bazą danych
docker run -d --name my-database --network my-network -p 5433:5432 -e POSTGRES_PASSWORD=admin postgres

# Tworzymy drugi kontener i wchodzimy od razu do konsoli
docker run -it --network my-network --name my-backend alpine sh

Jesteśmy teraz wewnątrz powłoki kontenera my-backend. Spróbujmy „pingnąć” naszą bazę danych po nazwie:

# Wewnątrz kontenera my-backend
ping my-database

W rezultacie powinieneś dostać podobny wynik do poniższego:

Wynik pingowania kotenera po nazwie DNS wewnątrz innego kontenera

To pokazuje, że Docker potrafi automatycznie tłumaczyć nazwę kontenera na jej wewnętrzy adres IP.

Uwaga! Ta funkcja nie działa w domyślnej sieci bridge. To główny powód, dla którego powinieneś zawsze tworzyć własne sieci dla swoich projektów.

Izolacja środowisk – sieci projektowe

Wyobraź sobie, że pracujesz nad dwoma różnymi projektami. Każdy z nich używa bazy danych PostgreSQL na domyślnym porcie 5432.

  • Projekt A: backend-a, db-a
  • Projekt B: backend-b, db-b

Jeśli uruchomisz wszystko w jednej, domyślnej sieci, zrobi się bałagan. Kontener backend-a mógłby przez pomyłkę połączyć się z db-b, jeśli nazwy byłyby podobne.

Znacznie lepszym podejściem jest stworzenie osobnej sieci dla każdego projektu:

  • docker network create projekt-a-net
  • docker network create projekt-b-net

Następnie uruchamiasz kontenery w dedykowanych im sieciach:

  • backend-a i db-a w projekt-a-net
  • backend-b i db-b w projekt-b-net

Dzięki temu kontenery z projektu A są całkowicie odizolowane od kontenerów z projektu B. Nie widzą się nawzajem i nie mogą się ze sobą komunikować. To zapewnia porządek, bezpieczeństwo i eliminuje ryzyko konfliktów.

Dobre praktyki i wskazówki dotyczące sieci

Z mojego doświadczenia wynika kilka zasad, których warto się trzymać:

  1. Dobrze jest używać własnych sieci bridge dla aplikacji wielokontenerowych. Nigdy nie powinniśmy polegać na domyślnej sieci bridge. Daje nam to DNS i izolację.
  2. Warto pamiętać, żeby odpowiednio nazywać swoje kontenery i sieci np. nazwa sieci my-project-net jest lepsze niż siec123. Na początku może się to wydawać zbędne, ale jak ma się to dobrze poukładane to naprawdę potrafi ułatwić życie np. w debugowaniu.
    Ewentualnie też można używać etykiet do lepszego opisu: docker network create --label project=myapp --label environment=dev dev-net.
  3. Dobrze jest też unikać sieci typu host, chyba że są ku temu dobre powody (np. aplikacja do monitoringu sieci, która musi widzieć cały ruch hosta) i też należy wiedzieć jakie to potencjalne konsekwencje może nieść m.in. temat bezpieczeństwa.
  4. Nie warto mapować wszystkich portów jak leci, a robić to tylko wtedy, gdy potrzebujemy faktycznie dany port na zewnątrz. Jeśli backend komunikuje się z bazą danych, nie trzeba mapować portu bazy danych na hosta, chyba że chcemy mieć do niej dostęp z narzędzi deweloperskich (dla deweloperskich potrafi bardzo ułatwić życie).

Typowe problemy i najczęstsze pytania

W tym punkcie przyjrzymy się najczęstszym problemom oraz pytaniom związanym z sieciami w Dockerze. Dzięki temu łatwej będzie Ci uniknąć schematycznych problematycznych sytuacji, które niejednokrotnie potrafią marnować niepotrzebnie czas.

Kontenery się nie widzą – co może być nie tak?

Pingujesz kontener po nazwie i dostajesz bad address lub ping: unknown host:

  • Czy kontenery są w tej samej sieci? Użyj docker network inspect nazwa_sieci i sprawdź, czy oba kontenery są na liście Containers.
  • Czy używasz własnej sieci bridge, a nie domyślnej? Pamiętaj, DNS po nazwie działa tylko w sieciach, które sam stworzyłeś.
  • Czy nie ma literówki w nazwie kontenera? Nazwa kontera my-db to nie to samo co my_db. Sprawdź nazwy za pomocą docker ps.
  • Czy firewall wewnątrz kontenera nie blokuje ruchu? Niektóre obrazy (np. z bardziej restrykcyjnymi systemami operacyjnymi) mogą mieć włączony firewall. Sprawdź konfigurację obrazu.

Konflikty portów, DNS, firewalle

Konflikty portów – Błąd Error starting userland proxy: listen tcp4 0.0.0.0:8080: bind: address already in use jest jednoznaczny. Próbujesz zmapować kontener na port hosta (8080), który jest już zajęty przez inny proces (inny kontener lub aplikację działającą bezpośrednio na hoście). Rozwiązania są dwa: zatrzymaj proces, który zajmuje port, albo zmapuj kontener na inny, wolny port (np. -p 8081:80).

Problemy z DNS – Czasem, zwłaszcza w środowiskach korporacyjnych z własnymi serwerami DNS lub przy korzystaniu z VPN, Docker może mieć problem z rozwiązywaniem nazw, zarówno wewnętrznych, jak i zewnętrznych (np. przy próbie pobrania pakietów z internetu w trakcie budowania obrazu). Możesz skonfigurować, jakich serwerów DNS ma używać demon Dockera (edycja pliku /etc/docker/daemon.json) lub przekazać serwer DNS bezpośrednio do kontenera za pomocą flagi --dns.

Firewall – Pamiętaj, że ruch sieciowy Dockera (zwłaszcza ten zmapowany na porty) musi przejść przez firewall hosta. Reguły iptables (na Linuksie) lub Windows Firewall mogą blokować komunikację. Docker stara się zarządzać iptables automatycznie, ale czasem może dojść do konfliktów z innymi narzędziami (np. ufw). Jeśli masz problemy z dostępem do zmapowanego portu z innej maszyny w sieci, sprawdź w pierwszej kolejności ustawienia firewalla na hoście Dockera.

*firewall to mechanizm bezpieczeństwa, który filtruje ruch sieciowy między komputerem (lub serwerem, kontenerem) a światem zewnętrznym, blokując lub przepuszczając połączenia zgodnie z ustalonymi regułami.

Porównanie sieci bridge i host

CechaSieć bridge (własna)Sieć host
IzolacjaWysoka. Kontener ma własny stos sieciowy.Brak. Kontener współdzieli stos sieciowy hosta.
BezpieczeństwoWyższe. Izolacja ogranicza potencjalne szkody. Niższe. Proces w kontenerze ma dostęp do interfejsów sieciowych hosta.
KomunikacjaPo nazwie kontenera (wbudowany DNS).Bezpośrednio, tak jak procesy na hoście (np. przez localhost).
Mapowanie PortówWymagane do wystawienia usług na zewnątrz (-p HOST:CONTAINER).Niedostępne/Niepotrzebne. Aplikacja od razu bindowana jest na porcie hosta.
WydajnośćNieco niższa. Dodatkowa warstwa NAT/proxy.Maksymalna. Brak narzutu sieciowego.
Konflikty PortówŁatwe do zarządzania (mapujesz na dowolny wolny port hosta).Kontener musi używać portów, które nie są zajęte na hoście.
Typowe UżycieDomyślny wybór dla większości aplikacji wielokontenerowych.Aplikacje wymagające wydajności sieciowej lub zarządzające wieloma portami (np. monitoring).

Warto zaznaczyć, że w większości przypadków stosuję sieć bridge z własnymi nazwami, a host tylko do debugowania lub specyficznych integracji.

Zbiór przydatnych komend

Dla utrwalenia, oto mała ściągawka z najważniejszych komend dotyczących sieci:

  • docker network ls – Wyświetla listę wszystkich sieci.
  • docker network create <nazwa_sieci> – Tworzy nową sieć (domyślnie bridge).
  • docker network rm <nazwa_sieci> – Usuwa sieć.
  • docker network inspect <nazwa_sieci> – Pokazuje szczegółowe informacje o sieci, w tym podłączone kontenery.
  • docker network connect <nazwa_sieci> <nazwa_kontenera> – Podłącza działający kontener do dodatkowej sieci.
  • docker network disconnect <nazwa_sieci> <nazwa_kontenera> – Odłącza kontener od sieci.
  • docker run --network <nazwa_sieci> ... – Uruchamia kontener w określonej sieci.
  • docker run -p <port_hosta>:<port_kontenera> ... – Mapuje port kontenera na port hosta.

Podsumowanie

Dotarliśmy do końca! Mam nadzieję, że ten wpis rozjaśnił Ci temat sieci w Dockerze. Jest to kluczowy element każdej architektury opartej na kontenerach. Dzięki nim zyskujemy elastyczność, izolację i łatwość zarządzania środowiskiem – niezależnie, czy budujesz system mikroserwisowy, czy zwykły zestaw narzędzi developerskich.

Opanowanie sieci to absolutny fundament, który otwiera drzwi do budowania skomplikowanych, ale jednocześnie uporządkowanych i przenośnych środowisk. To inwestycja, która zwraca się wielokrotnie w postaci mniejszej liczby problemów, łatwiejszego dewelopmentu i stabilniejszych wdrożeń.

Jeśli masz jakieś pytania, uwagi, albo chcesz podzielić się swoimi doświadczeniami z sieciami w Dockerze – śmiało pisz w komentarzach! Chętnie pomogę i podyskutuję.

Subskrybuj
Powiadom o
guest
0 komentarzy
Najstarsze
Najnowsze Najwięcej głosów
Opinie w linii
Zobacz wszystkie komentarze