Modul 9 · 9.3
Docker compose a firewall
Modul 9: Docker a docker compose · Čas čítania: 12 minút
Cieľ lekcie: Po tejto lekcii dokážete opísať služby v súbore compose, spustiť ich, aktualizovať a zastaviť a viete vysvetliť, prečo publikované porty Dockeru obchádzajú ufw a ako tomu zabrániť.
Kľúčové pojmy: compose.yaml, services, image, ports, volumes, environment, .env, restart, networks, depends_on, healthcheck, docker compose up -d, pull, logs, down, zastarané version:, Docker a ufw, DOCKER-USER, publikovanie na 127.0.0.1, tajné údaje, docker.sock
Prečo compose?
Pomocou docker run (lekcia 9.2) spustíte jeden kontajner s dlhým riadkom volieb. Skutočná aplikácia však často pozostáva z viacerých kontajnerov: z programu, databázy a reverse proxy. Pamätať si tieto riadky a po reštarte alebo aktualizácii ich znova vypisovať sa raz nevyhnutne pokazí.
Docker Compose opisuje všetky kontajnery aplikácie v jednom súbore: compose.yaml. Tento súbor uložíte do vlastného priečinka, napríklad /srv/status/compose.yaml, a všetko spravujete pomocou docker compose. Súbor je zároveň vašou dokumentáciou: čo beží, aký image, aké porty, kde sú uložené údaje. Zahrňte tento priečinok do zálohy (lekcia 8.1) a aplikáciu dokážete na novom serveri obnoviť za pár minút.
Plug-in sa volá docker compose (s medzerou, verzia 2). Starý samostatný program docker-compose (s pomlčkou) bol nahradený; stále ho uvidíte v starých návodoch. Zastarané je aj pole version: "3.8" na začiatku starých súborov: Compose vždy používa najnovšiu schému a pri version: zobrazí iba upozornenie.
Čítanie súboru compose
Príklad s programom a databázou PostgreSQL:
# /srv/notities/compose.yaml
services:
app:
image: ghcr.io/example/notities:1.4
restart: unless-stopped
ports:
- "127.0.0.1:8081:8080"
environment:
DB_HOST: db
DB_USER: notities
DB_PASSWORD: ${DB_PASSWORD}
depends_on:
db:
condition: service_healthy
db:
image: postgres:17
restart: unless-stopped
environment:
POSTGRES_USER: notities
POSTGRES_PASSWORD: ${DB_PASSWORD}
volumes:
- db-data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U notities"]
interval: 10s
retries: 5
volumes:
db-data:Krok za krokom:
- services: z každej služby sa stane kontajner. Názov (
app,db) je zároveň hostname, podľa ktorého sa kontajnery navzájom nájdu. Compose vytvorí pre aplikáciu vlastnú sieť, takžeappsa pripojí k databáze nadb:5432. - image: vždy s tagom verzie (lekcia 9.1).
- restart: čo Docker urobí, keď sa kontajner zastaví alebo sa server reštartuje.
unless-stoppedho znova spustí, okrem prípadu, keď ho zámerne zastavíte. Bez pravidla pre reštart sa vaša aplikácia po reštarte (lekcia 4.2) nevráti. - ports: port publikuje iba aplikácia, a to iba na
127.0.0.1. Databáza nepublikuje nič: aplikácia sa k nej dostane cez internú sieť. Databáza sports: - "5432:5432"patrí medzi najčastejšie chyby (pozri nižšie). - environment: nastavenia programu. Heslo v nich nie je napísané priamo, ale ako
${DB_PASSWORD}. - volumes: pomenovaný zväzok
db-datauchová databázu, aj keď sa kontajner nahradí. - depends_on s healthcheck: aplikácia sa spustí až vtedy, keď je databáza skutočne pripravená, nielen spustená.
Tajné údaje v súbore .env
Compose načíta premenné ako ${DB_PASSWORD} zo súboru .env v tom istom priečinku:
# /srv/notities/.env
DB_PASSWORD=Kies-hier-een-lang-willekeurig-wachtwoordanna@web1:/srv/notities$ sudo chmod 600 .envHeslo tak nie je v súbore compose, ktorý možno uchovávate v Gite alebo vkladáte do fóra, keď žiadate o pomoc. Pridajte .env do .gitignore. Heslo vytvorte pomocou správcu hesiel alebo príkazom openssl rand -base64 24.
Každodenné používanie
Všetky príkazy spúšťajte v priečinku so súborom compose:
anna@web1:/srv/notities$ sudo docker compose config # skontrolovať súbor, premenné doplnené
anna@web1:/srv/notities$ sudo docker compose up -d # spustiť všetko (alebo aktualizovať podľa súboru)
anna@web1:/srv/notities$ sudo docker compose ps # stav jednotlivých služieb
anna@web1:/srv/notities$ sudo docker compose logs -f app
anna@web1:/srv/notities$ sudo docker compose pull # stiahnuť nové obrazy
anna@web1:/srv/notities$ sudo docker compose up -d # nahradiť kontajnery novými obrazmi
anna@web1:/srv/notities$ sudo docker compose down # zastaviť a odstrániť kontajnerydown ponechá vaše zväzky. down -v odstráni aj zväzky aplikácie, a tým aj vašu databázu. Zadajte to iba vtedy, keď naozaj chcete začať odznova.
docker compose config je obdobou nginx -t a sshd -t: ukáže, ako Compose rozumie vášmu súboru, so všetkými dosadenými premennými, ešte predtým, ako čokoľvek spustíte. Dávajte pozor, aby ste tento výstup nikam nevkladali, pretože obsahuje heslá.
Docker obchádza ufw
Teraz najdôležitejší bezpečnostný bod tohto modulu. V lekcii 5.2 ste nastavili ufw na "všetko zakázať okrem SSH, 80 a 443". Dalo by sa očakávať, že kontajner s ports: - "5432:5432" potom nebude dostupný. Nie je to tak.
Dokumentácia Dockeru to hovorí doslova: Docker a ufw používajú pravidlá firewallu spôsobom, ktorý nie je navzájom kompatibilný. Keď publikujete port, Docker sám zapíše pravidlá do firewallu jadra. Tieto pravidlá presmerujú prevádzku do kontajnera (preklad adries, DNAT) ešte predtým, ako sa uplatnia pravidlá ufw. Paket teda ufw obíde. ufw status neukáže nič zvláštne, hoci je port dostupný z celého internetu. To isté platí pre firewalld.
Navyše Docker bez zadanej adresy publikuje na 0.0.0.0 a [::], teda na IPv4 aj IPv6 (lekcia 9.1).
Tri spôsoby, ako to urobiť správne, od jednoduchého po zložitý:
- Nepublikujte nič, čo nemusí byť verejné. Databázy, cache a interné služby nedostanú
ports:. Kontajnery v tej istej aplikácii compose sa navzájom dostanú cez internú sieť. - Publikujte na loopback.
"127.0.0.1:8081:8080". Potom k službe má prístup iba samotný server a pred ňu postavíte reverse proxy (nginx alebo Caddy, modul 7), ktorá počúva na 443. Docker to môže mať aj ako predvolené správanie: nastavenie démona zabezpečí, že všetky publikované porty bez adresy skončia na127.0.0.1. - Pravidlá v reťazci DOCKER-USER. Docker vytvorí prázdny reťazec
DOCKER-USER, ktorým prevádzka prejde pred jeho vlastnými pravidlami. Tam môžete pridať vlastné pravidlá, napríklad "k publikovaným portom smie iba táto IP adresa". Ide o pokročilú prácu s iptables alebo nftables, pri ktorej sa ľahko urobí chyba. Pre väčšinu malých serverov stačia spôsoby 1 a 2.
Vždy kontrolujte zvonku, ako v lekcii 5.1: nc -vz -w 3 <ip> 5432 z vášho notebooku alebo kontrolou kurzu v úlohe Z5.1 a Z10.4.
Ďalšie dve veci, ktoré nerobte
- Nepripájajte
/var/run/docker.sockdo kontajnera, pokiaľ presne neviete prečo. Kontajner s prístupom k socketu Dockeru môže sám spúšťať kontajnery, aj taký, ktorý má celý disk hostiteľa (lekcia 9.2). Niektoré pomocné programy (dashboardy, automatické aktualizátory) to vyžadujú; v skutočnosti tým danému programu dávate práva root. - Nepoužívajte
privileged: trueaninetwork_mode: hostlen preto, že to uvádza nejaký návod. Obe voľby z veľkej časti odstraňujú izoláciu kontajnera. Používajte ich iba vtedy, keď autor vysvetlí, prečo sú potrebné.
Zhrnutie
- Súbor compose (
compose.yaml) opisuje všetky kontajnery aplikácie; zároveň slúži ako dokumentácia a patrí do vašej zálohy. - Používajte tagy verzií, pravidlo pre reštart, pomenované zväzky, healthcheck tam, kde je to možné, a tajné údaje v súbore
.envs právami 600. docker compose config,up -d,ps,logs,pull,down;down -vodstráni aj zväzky.- Publikované porty obchádzajú ufw aj firewalld. Publikujte iba to, čo musí byť verejné, a inak na
127.0.0.1s reverse proxy pred službou. - Žiadny docker.sock,
privilegedaninetwork_mode: hostbez dobrého dôvodu.
Kvíz
Úloha
Úloha Z9.3: Kontrola súboru compose. V ukážkovom súbore compose-nakijken.txt sa nachádza (ako textový súbor) súbor compose malého e-shopu s aplikáciou, databázou, cache a nástrojom na správu. Je v ňom šesť chýb, ktoré boli preberané v tejto lekcii alebo v lekciách 9.1 a 9.2. Pri každom očíslovanom bloku riadkov uveďte, či je správny alebo chybný, a pri každej chybe vyberte správnu opravu. Program porovná vaše odpovede s pevným kľúčom. Ak máte vlastný súbor compose, prejdite ho potom podľa rovnakých bodov.
Ďalšie čítanie
- Dokumentácia Dockeru, How Compose works (compose.yaml): https://docs.docker.com/compose/intro/compose-application-model/
- Dokumentácia Dockeru, Version and name top-level elements: https://docs.docker.com/reference/compose-file/version-and-name/
- Dokumentácia Dockeru, Packet filtering and firewalls (Docker and ufw): https://docs.docker.com/engine/network/packet-filtering-firewalls/
- Dokumentácia Dockeru, Port publishing and mapping: https://docs.docker.com/engine/network/port-publishing/
- Dokumentácia Dockeru, Interpolation (premenné a .env): https://docs.docker.com/reference/compose-file/interpolation/
