ťařina
Obsah Soubory
markdown

Site-v-Dockeru.md

markdown
# Sítě v Dockeru Docker vytváří virtuální sítě a většina zmatků kolem něj pramení z toho, že si člověk neuvědomí, že kontejner je vlastní stroj s vlastním síťovým prostorem. Souvislost s bezpečností je v [Docker a firewall](Docker-a-firewall) — přečti si to, i když tě sítě jinak nezajímají. ## Režimy | Režim | Co dělá | Kdy použít ||---|---|---|| `bridge` | vlastní privátní síť, NAT ven | výchozí, skoro vždy || `host` | kontejner sdílí síť hostitele | když potřebuješ výkon nebo broadcast || `macvlan` | kontejner má vlastní MAC a IP ve tvé LAN | když má vypadat jako fyzické zařízení || `none` | žádná síť | izolované výpočty | ### bridge Výchozí. Docker udělá virtuální switch `docker0`, kontejnery dostanou adresy z `172.17.0.0/16` a ven jdou přes [NAT](NAT-a-port-forwarding). Zásadní rozdíl proti výchozí síti: **v uživatelsky vytvořené síti funguje DNS podle jmen kontejnerů, ve výchozí `bridge` ne.** Proto vždycky vytvářej vlastní síť, nebo používej Compose, který to dělá sám. ```bashdocker network create moje-sitdocker run -d --network moje-sit --name db postgresdocker run -d --network moje-sit --name app mojeapp# app se na databázi připojí přes hostname "db"``` ### host Kontejner nemá vlastní síť, používá přímo hostitelovu. Žádný NAT, žádné mapování portů — co kontejner otevře, je otevřené na stroji. Použij pro věci, které potřebují vidět broadcast nebo mDNS: Home Assistant, Pi-hole, monitorovací sondy. Cenou je ztráta izolace a to, že `-p` přestane fungovat (a nedává smysl). ### macvlan Kontejner dostane vlastní [MAC adresu](MAC-ARP-a-prepinani) a IP přímo z tvé LAN. Z pohledu sítě je to samostatné zařízení a můžeš mu dát vlastní [VLANu](VLANy) i firewallová pravidla. ```bashdocker network create -d macvlan \  --subnet=192.168.1.0/24 \  --gateway=192.168.1.1 \  -o parent=eth0 \  lan-sit``` Jedna past, která překvapí každého: **hostitel se na macvlan kontejnery nedostane.** Je to omezení jádra, ne chyba konfigurace. Obchází se to vytvořením pomocného macvlan rozhraní na hostiteli, ale je to otrava. Když potřebuješ komunikaci hostitel–kontejner, macvlan není správná volba. ## Co dělá `-p` doopravdy ```bashdocker run -p 8080:80 nginx``` Levé číslo je port na hostiteli, pravé v kontejneru. Docker k tomu vytvoří DNAT pravidlo v netfilteru. Vazba na rozhraní je klíčová pro bezpečnost: ```bash-p 8080:80              # 0.0.0.0, tedy všude včetně internetu-p 127.0.0.1:8080:80    # jen z hostitele-p 192.168.1.5:8080:80  # jen přes konkrétní adresu``` Podrobně v [Docker a firewall](Docker-a-firewall). ## `localhost` v kontejneru není hostitel Nejčastější chyba začátečníků. Když v kontejneru napíšeš `localhost` nebo `127.0.0.1`, míníš tím **ten kontejner**, ne hostitele ani jiný kontejner. Jak se dostat kam: | Odkud kam | Adresa ||---|---|| kontejner → jiný kontejner ve stejné síti | jméno kontejneru, třeba `db` || kontejner → hostitel | `host.docker.internal` (Docker Desktop) nebo IP mostu || kontejner → internet | normálně, přes NAT || hostitel → kontejner | `localhost:publikovaný-port` | Na Linuxu `host.docker.internal` ve výchozím stavu nefunguje. Přidej: ```yamlextra_hosts:  - "host.docker.internal:host-gateway"``` ## Compose Compose vytvoří pro každý projekt vlastní síť a kontejnery se v ní vidí podle jmen služeb. To je obvykle přesně to, co chceš. Rozumný vzor pro self-hosting: **jediná služba s publikovanými porty je proxy**, ostatní jsou vnitřní. ```yamlservices:  caddy:    image: caddy:2    ports:      - "80:80"      - "443:443"    volumes:      - ./Caddyfile:/etc/caddy/Caddyfile      - caddy_data:/data    networks: [web]   app:    image: mojeapp    expose: ["3000"]    networks: [web, backend]   db:    image: postgres:16    environment:      POSTGRES_PASSWORD_FILE: /run/secrets/db_heslo    networks: [backend]    volumes:      - db_data:/var/lib/postgresql/data networks:  web:  backend:    internal: true volumes:  caddy_data:  db_data:``` Dvě věci, které stojí za povšimnutí: **`internal: true`** znamená, že síť `backend` nemá cestu ven. Databáze se nedostane na internet ani kdyby chtěla. Užitečné proti exfiltraci a proti tomu, aby si image samo něco stahovalo. **Aplikace je ve dvou sítích.** Vidí proxy i databázi, ale proxy databázi nevidí. Minimální propojení. ## Diagnostika ```bashdocker network lsdocker network inspect moje-sitdocker ps --format "table {{.Names}}\t{{.Ports}}" # z kontejneru, i když v něm nejsou nástrojedocker run --rm -it --network moje-sit nicolaka/netshoot bash``` Ten poslední trik je zlatý. `netshoot` je image plný síťových nástrojů — připojíš ho do stejné sítě jako problémový kontejner a máš k dispozici `dig`, `tcpdump`, `curl`, `nmap` a všechno ostatní z [nástrojů](Nastroje). Odposlech provozu kontejneru z hostitele: ```bashdocker network inspect moje-sit -f '{{.Id}}' | cut -c1-12   # zjistí idtcpdump -i br-<id> -n``` ## Časté potíže **Kontejnery se nevidí podle jména** → jsi ve výchozí síti `bridge`. Vytvoř vlastní. **Kontejner se nedostane na internet** → chybí forwarding (`net.ipv4.ip_forward=1`), nebo ti do toho mluví vlastní firewall. Viz [Docker a firewall](Docker-a-firewall). **Kolize adresního rozsahu s LAN** → Docker používá `172.17.0.0/16`, což se občas potká s firemní VPN. Změň v `/etc/docker/daemon.json`: ```json{ "default-address-pools": [{"base": "10.200.0.0/16", "size": 24}] }``` **DNS v kontejneru nefunguje** → kontejner dědí resolver z hostitele. Když máš `systemd-resolved` s `127.0.0.53`, kontejner na to nedosáhne. Nastav v `daemon.json` konkrétní servery: ```json{ "dns": ["192.168.1.1", "1.1.1.1"] }```