Porozumění kontejnerům
Modul 9: Docker a docker compose · Doba čtení: 10 min.
Cíl lekce: Po této lekci dokážete vysvětlit, co je kontejner, čím se liší od virtuálního stroje, kde zůstávají data kontejneru a kdy má Docker na Vašem serveru smysl.
Klíčové pojmy: image, kontejner, vrstva, registry (Docker Hub), tag, digest, namespaces, cgroups, sdílené jádro, nestálý souborový systém, volume, bind mount, publikování portu, oficiální image
Proč kontejnery?
Představte si, že chcete na svém VPS provozovat stavovou stránku, která ukazuje, zda Váš web funguje. Program je napsaný v Node.js, potřebuje jeho konkrétní verzi a k tomu zhruba dvě stě knihoven. Bez kontejnerů to všechno nainstalujete na server, vedle webového serveru a databáze. O rok později budete chtít druhý program, který potřebuje jinou verzi Node.js. A začne skládání puzzle.
Kontejner tento problém řeší. Autor programu dodá program spolu se vším, co potřebuje, v jednom balíčku: v image. Na serveru tento image spustíte jako kontejner. Program vidí své vlastní soubory, svůj vlastní Node.js, své vlastní knihovny a nepřekáží zbytku serveru. Už ho nepotřebujete? Smažete kontejner, smažete image a v /usr ani v /etc nic nezůstane.
Docker je nejznámější nástroj pro stahování images a spouštění kontejnerů. Existují i alternativy (Podman, samotný containerd), ale pojmy jsou všude stejné.
Image, kontejner a registry
Tři slova, se kterými se budete setkávat neustále:
- Image: šablona jen pro čtení se souborovým systémem (program, knihovny, nastavení) a příkazem, který se má spustit. Image se skládá z vrstev: základní vrstva (například holý Debian), nad ní vrstva s Node.js a nad ní samotný program. Dva images se stejnou základní vrstvou sdílejí tuto vrstvu na disku.
- Kontejner: běžící (nebo zastavená) instance image. Nad vrstvami jen pro čtení dostane kontejner vlastní tenkou zapisovatelnou vrstvu. Z jednoho image můžete spustit deset kontejnerů.
- Registry: místo, kde jsou images uložené, například Docker Hub (
docker.io) nebo registry GitHubu (ghcr.io). Docker stáhne image příkazemdocker pull.
Název image vypadá takto:
louislam/uptime-kuma:2
caddy:2
vaultwarden/server:latestČást za dvojtečkou je tag: označení verze. Tag se může měnit: caddy:2 dnes ukazuje na jiný build než za tři měsíce, jakmile vyjde nová verze 2.x. Pokud chcete přesně zafixovat, jaký image provozujete, použijte digest: otisk obsahu, například caddy@sha256:.... Ten se nikdy nemění. Tag latest je obyčejný název, který zvolí autor; neznamená automaticky "nejnovější stabilní verze", a proto je to špatná volba, pokud chcete vědět, co na serveru běží.
Žádný virtuální stroj
Kontejner se podobá malému virtuálnímu stroji, ale není jím. Tento rozdíl je důležitý pro bezpečnost.
| Virtuální stroj (jako Váš VPS) | Kontejner | |
|---|---|---|
| Jádro | Vlastní jádro | Sdílí jádro hostitele |
| Spuštění | Sekundy až minuty, celý operační systém | Obvykle do sekundy, jen program |
| Oddělení | Pomocí hypervisoru, na úrovni hardwaru | Pomocí jádra: namespaces a cgroups |
| Velikost | Gigabajty | Často desítky až stovky megabajtů |
Kontejner je ve skutečnosti obyčejný proces na Vašem serveru, který jádro umístí do izolovaného prostředí:
- namespaces zajišťují, že proces má vlastní pohled na soubory, procesy, síť a uživatele. V kontejneru se programu zdá, že je procesem číslo 1, a zbytek serveru nevidí;
- cgroups omezují, kolik procesoru a paměti smí používat.
Protože všechny kontejnery sdílejí stejné jádro, je oddělení méně přísné než mezi dvěma VPS. Chyba v jádře nebo kontejner s příliš velkými oprávněními může zasáhnout hostitele. Proto platí pravidla z tohoto modulu: spouštějte jen images, kterým důvěřujete, nedávejte kontejnerům více oprávnění, než potřebují, a nikdy do kontejneru nepřipojujte /var/run/docker.sock ani / (lekce 9.3 a 10.2).
Kde zůstávají Vaše data?
Toto je klasická past pro začátečníky. Zapisovatelná vrstva kontejneru je nestálá: když kontejner smažete (například při aktualizaci, lekce 9.4), zmizí vše, co do ní program zapsal. Data, která mají zůstat, proto patří mimo kontejner:
- Volume: úložiště, které spravuje sám Docker (v
/var/lib/docker/volumes/). Dáte mu název, napříkladuptime-kuma, a připojíte ho ke složce v kontejneru:-v uptime-kuma:/app/data. - Bind mount: běžná složka na Vašem serveru, kterou připojíte do kontejneru:
-v /srv/vaultwarden:/data. Praktické, protože soubory vidíte přímo a snadno je zahrnete do zálohy (modul 8).
Kontejner se správně nastavenými volumes můžete zahodit a vytvořit znovu, aniž byste o cokoli přišli. Přesně tak funguje aktualizace: stáhnout nový image, odstranit starý kontejner, spustit nový kontejner nad stejnými volumes. Volumes proto zařaďte do svého plánu záloh (lekce 8.1).
Publikování portů
Kontejner má vlastní síť. Webový program, který v kontejneru naslouchá na portu 3001, není zvenčí serveru dostupný, dokud tento port nepublikujete: -p 3001:3001 (port hostitele:port kontejneru). Pozor: bez uvedení adresy publikuje Docker port na všech adresách Vašeho serveru, tedy 0.0.0.0 a [::]. To znamená: dostupný z celého internetu, a Docker to zařídí mimo ufw (lekce 9.3). Bezpečným zvykem je publikovat na loopback, -p 127.0.0.1:3001:3001, a před to postavit reverse proxy s https (lekce 9.4).
Kdo image vytváří?
Image je software od někoho jiného, který může na Vašem serveru běžet jako root. Proto si ověřte, kdo je jeho autorem:
- Docker Official Images (například
caddy,nginx,postgres) udržuje Docker společně s autory; - images přímo od autora (například
louislam/uptime-kumaavaultwarden/server) poznáte podle názvu, který uvádí web projektu; - images od neznámých lidí s podobně znějícími názvy: nepoužívat.
Vždy použijte název uvedený na oficiálním webu projektu, ne ten, který Vám jako první nabídne vyhledávání.
Kdy ano, kdy ne?
Docker se hodí pro programy, které autor dodává jako image, pro služby, které chcete rychle zahodit nebo přesunout, a pro souběžný provoz více programů s rozdílnými požadavky. Pro základ serveru (SSH, firewall, aktualizace) kontejnery nepoužíváte. A jednoduchý web s nginx a PHP z repozitáře balíčků (lekce 7.2) funguje skvěle i bez Dockeru. Kontejner přidává vrstvu, které musíte rozumět a kterou musíte aktualizovat; nasaďte ho tehdy, když Vám něco přinese.
Shrnutí
- Image je šablona jen pro čtení složená z vrstev; kontejner je její běžící instance s vlastní zapisovatelnou vrstvou.
- Kontejnery sdílejí jádro hostitele a jsou izolované pomocí namespaces a cgroups: jsou lehčí než VM, ale méně přísně oddělené.
- Zapisovatelná vrstva je nestálá: trvalá data patří do volume nebo bind mountu a ty patří do zálohy.
- Tag se může změnit, digest ne;
latesttoho moc neříká. - Publikujte porty na 127.0.0.1 a používejte jen images od autora nebo oficiální images.
Kvíz
Úkol
Úkol O9.1: Kontejner, nebo ne? Vyberte dva programy, které chcete na svém serveru provozovat (nebo použijte jako příklad Uptime Kuma a web ve WordPressu). U každého programu zjistěte, zda autor dodává oficiální image a pod jakým názvem, jaký tag byste zvolili, která složka obsahuje trvalá data a na jakém portu program naslouchá. Poté vysvětlete, zda byste ho provozovali v kontejneru, nebo z repozitáře balíčků, a proč.
Úkol O9.1: Kontejner, nebo ne?
Tento úkol provádíte sami; nikdo ho nekontroluje. Odškrtněte, co jste udělali, a označte úkol jako splněný.
Uptime Kuma: louislam/uptime-kuma s tagem verze, data v /app/data, port 3001, publikovat na 127.0.0.1 za reverzní proxy. Zvolte image od autora nebo Official Image, s tagem verze a pojmenovanou složkou pro data.
Vaše zaškrtnutí a poznámky zůstávají pouze v tomto prohlížeči; nikam je neposíláme. Pokud jste přihlášeni, ukládáme v sekci Moje kurzy pouze to, že jste úkol splnili.
Doporučujeme k přečtení
- Dokumentace Dockeru, What is a container?: https://docs.docker.com/get-started/docker-concepts/the-basics/what-is-a-container/
- Dokumentace Dockeru, Volumes: https://docs.docker.com/engine/storage/volumes/
- Dokumentace Dockeru, Port publishing and mapping: https://docs.docker.com/engine/network/port-publishing/
- Docker Official Images: https://docs.docker.com/docker-hub/repos/manage/trusted-content/official-images/
