Napsat kód je jen půlka práce — ještě se musí dostat z tvého počítače tam, kde poběží pro reálné uživatele, a to spolehlivě a bez výpadku. Tahle kapitola je o tom: jak appku zabalit, nasadit, sledovat a v případě průšvihu vrátit zpátky. Dobrý backend engineer tohle umí, ne jen psát funkce.
Pár pojmů na úvod
- Produkce (production) = ostré prostředí, kde tvou appku používají skuteční uživatelé. Opak je vývojové prostředí na tvém počítači.
- Deploy (nasazení) = dostat novou verzi kódu do produkce.
- Rollout = postupné vypouštění nové verze.
- Rollback = vrácení zpátky na předchozí (fungující) verzi, když se nová pokazí.
- Výpadek (downtime) = doba, kdy služba nefunguje.
Kontejnery (Docker)
Problém, který řeší: „na mém počítači to jede, na serveru ne" — kvůli jiné verzi knihoven, runtime apod. Kontejner zabalí tvoji appku i s celým jejím prostředím (knihovny, runtime) do jednoho balíčku, který běží stejně všude.
- Image = neměnná šablona toho balíčku. Container = běžící instance vytvořená z image.
- Kontejner vs virtuální stroj (VM): kontejner sdílí jádro (kernel) hostitelského systému, takže je lehký (megabajty, start v sekundách). VM virtualizuje celý operační systém — je těžší, ale izolovanější. Pro nasazování běžných služeb se používají kontejnery.
- Dobré návyky: malé image, oddělit fázi sestavení od běhu (multi-stage build), neběžet jako root, a nikdy nedávat tajné údaje (secrets) přímo do image.
Orchestrace (Kubernetes)
Když máš mnoho kontejnerů na mnoha strojích, potřebuješ něco, co je řídí — spouští, restartuje, rozkládá zátěž. Tomu se říká orchestrace a nejznámější nástroj je Kubernetes (zkráceně k8s). Jako junior ho nemusíš umět ovládat, ale měl bys chápat, co dělá:
- Spouští a hlídá kontejnery, udržuje zadaný počet běžících kopií (replik).
- Self-healing (samoléčení): když kontejner spadne, restartuje ho; když umře celý stroj, přeplánuje kontejnery jinam (využívá liveness/readiness z Observability).
- Autoscaling: podle zátěže sám přidává nebo ubírá kopie.
Kubernetes je mocný, ale složitý. Pro menší projekty existují jednodušší nástroje (PaaS jako Railway, Render, Coolify), které tohle zařídí za tebe — víc v Tech Choices.
CI/CD — automatizace cesty do produkce
- CI (Continuous Integration) — při každém nahrání kódu se automaticky spustí sestavení a kontroly (lint, typová kontrola, testy). Chyba se chytí dřív, než se dostane do hlavní větve.
- CD (Continuous Delivery/Deployment) — po úspěšném CI se kód automaticky nasadí.
- Celé to tvoří pipeline (potrubí):
commit → sestavení → testy → (staging) → nasazení.
(Staging je předprodukční prostředí co nejvíc podobné produkci, kde se věci vyzkouší nanečisto.)
Deploy strategie — jak nasadit bez výpadku
Když nasazuješ novou verzi, nechceš, aby uživatelé viděli chybovou stránku. Možnosti:
| Strategie | Jak funguje | Za co se platí |
|---|---|---|
| Recreate | Vypni starou verzi, pusť novou | Nejjednodušší, ale je výpadek |
| Rolling | Vyměňuj instance po dávkách | Bez výpadku; chvíli běží dvě verze naráz |
| Blue-Green | Dvě prostředí, přepneš provoz naráz | Okamžitý rollback; ale dvojnásobek zdrojů |
| Canary | Pusť nejdřív na malé % uživatelů, sleduj, pak na zbytek | Nejbezpečnější; ale složitější |
Pozor: u rolling a canary běží během nasazení stará i nová verze naráz, takže změny API a databáze musí být zpětně kompatibilní (viz dál).
⚠️ A pozor na past blue-green: „okamžitý rollback" platí pro kód, ale obě prostředí typicky sdílejí jednu databázi — takže jakmile nová verze provede nevratnou migraci, rollback je iluze (databáze zpátky nejde, viz expand-contract níže). I u blue-green proto musí být DB změny zpětně kompatibilní.
Aby „bez výpadku" platilo, musí instance umět graceful shutdown. Při rolling deploy dostane stará
instance signál k ukončení (SIGTERM). Nesmí spadnout uprostřed rozdělané práce — má:
- přestat hlásit readiness (load balancer ji přestane posílat nové requesty),
- dokončit rozpracované requesty (drain) v rámci časového limitu,
- teprve pak skončit.
Bez tohohle ti rolling deploy utne requesty, které zrovna běžely (a u dlouhých spojení jako WebSockets
je drain o to důležitější — viz Realtime). Když instance do limitu neskončí, orchestrátor
ji tvrdě zabije (SIGKILL).
Databázové migrace — kde se to nejčastěji rozbije
Migrace je řízená změna struktury databáze (přidat sloupec, tabulku…). Protože při nasazení běží chvíli stará i nová verze kódu nad stejnou databází, musí být migrace zpětně kompatibilní — jinak stará verze kódu na nové databázi spadne.
Bezpečný postup se jmenuje expand-contract: nejdřív jen přidej nové (sloupec), nasaď kód, který umí obojí, převeď data, přepni čtení na nové, a teprve nakonec smaž staré. Nikdy „přejmenuj sloupec" v jednom kroku během běžícího provozu.
Infrastructure as Code (IaC)
Místo ručního naklikávání serverů ve webové konzoli se infrastruktura popíše kódem (nástroji jako Terraform). Výhody: dá se verzovat, projít revizí a kdykoli přesně zopakovat. Souvisí s immutable infrastructure — běžící servery neupravuješ, ale nahradíš je novými z definice, takže se vyhneš „config driftu" (server, který někdo ručně osahal a teď funguje jen tam a nikdo neví proč).
Prostředí a konfigurace
- Mívají se tři prostředí: dev (vývoj) → staging (zkušební) → production (ostré).
- Konfigurace (adresy, klíče) patří do proměnných prostředí, ne do kódu. Tajné údaje přes secret manager.
- Napříč prostředími nasazuj stejný balíček, liší se jen konfigurací.
Feature flags, autoscaling a disaster recovery
- Feature flags (přepínače funkcí). Někdy chceš novou funkci nasadit do produkce, ale zapnout ji až později (nebo jen pro pár uživatelů). Feature flag je vypínač v konfiguraci, kterým funkci zapneš/vypneš bez nového nasazení. Oddělíš tím deploy (kód je venku) od release (funkce je vidět) — a když je s ní problém, vypneš ji za vteřinu místo zdlouhavého rollbacku.
- Autoscaling (automatické škálování). Místo abys počet instancí nastavoval ručně, systém ho sám přidává a ubírá podle zátěže (např. podle vytížení CPU). V noci míň, ve špičce víc. Šetří peníze i nervy, ale potřebuje, aby služba byla stateless (Performance).
- Disaster recovery (zotavení po katastrofě). Plán, co když vypadne celé datacentrum nebo se smažou data. Dvě čísla, kterými se to měří: RPO (Recovery Point Objective — kolik dat smíš v nejhorším ztratit, určuje frekvenci záloh) a RTO (Recovery Time Objective — jak dlouho smí trvat, než zase běžíš). A pravidlo z Databází: obnovu pravidelně zkoušej.
Failure modes — kde se to kazí
- Nekompatibilní migrace během nasazení → stará verze kódu spadne na novém schématu databáze.
- Žádný plán na rollback → nasazení se pokazí a nemáš cestu zpět (proto blue-green/canary).
- Config drift → ručně osahané servery, které nejde zopakovat („funguje jen na jednom").
- Secrets v image nebo v gitu → únik tajných údajů.
🛠️ Cvičení
- Napiš Dockerfile. Pro jednoduchou appku udělej build oddělený od běhu (multi-stage), běh jako
ne-root a
.dockerignore. Vysvětli, proč do image nepatří secrets. - Vyber deploy strategii. Pro rychlou opravu kritické chyby vs velký rizikový release vyber recreate / rolling / blue-green / canary a zdůvodni.
- Expand-contract migrace. Přejmenuj sloupec
namenafull_namebez výpadku, když během nasazení běží stará i nová verze kódu naráz. Napiš jednotlivé kroky. - Rozbij rollout. Proč „rolling nasazení + migrace, co rovnou smaže starý sloupec" položí starou verzi kódu? Oprav to.
- CI pipeline. Navrhni kroky od commitu po produkci (sestavení, lint, testy, staging, nasazení) a urči, co má zastavit nasazení.
Náčrt řešení — rozbal, až si cvičení zkusíš sám
- Napiš Dockerfile — multi-stage build: jedna fáze sestaví, druhá (běhová) si vezme jen výsledek; přidej
USERmimo root a.dockerignore, ať do image neletínode_modules/.git/.env. Secrets do image nepatří, protože image je neměnná šablona, kterou si kdokoli s přístupem stáhne a vrstvy přečte — tajné údaje předávej až za běhu přes proměnné prostředí / secret manager. - Vyber deploy strategii — rychlou opravu kritické chyby nasaď nejrychlejší bezpečnou cestou (rolling, případně blue-green pro okamžitý rollback); velký rizikový release pусť přes canary (malé % uživatelů, sleduj metriky, pak zbytek). Pozor: u rolling i canary běží stará a nová verze naráz, takže API i DB změny musí být zpětně kompatibilní.
- Expand-contract migrace — kroky: přidej nový sloupec
full_name, nasaď kód, který zapisuje do obou a čte zfull_names fallbackem naname, převeď stará data, přepni čtení čistě nafull_name, a teprve po odejití staré verze smažname. Pozor: nikdy ne „přejmenovat v jednom kroku" za běhu — stará verze kódu by spadla na chybějícím sloupci. - Rozbij rollout — během rolling deploye běží i stará verze, která starý sloupec ještě čte; migrace, co ho rovnou smaže, jí ho podtrhne a ta padá. Oprava: rozděl to na expand-contract — smazání sloupce dej až do samostatné pozdější migrace, kdy už žádná stará verze neběží. Pozor: stejná past platí i u blue-green, kvůli sdílené databázi.
- CI pipeline — kroky:
commit → build → lint → typová kontrola → testy → (staging) → nasazení do produkce. Nasazení má zastavit cokoli, co selže — padající test, typová chyba, chyba lintu, neúspěšný build. Pozor: smyslem je rychlá zpětná vazba a pořád funkční hlavní větev, ne „protlačit to dál".
🧠 Otázky & odpovědi
Jaký problém řeší kontejnery a čím se liší od virtuálního stroje?
Kontejner zabalí appku i s jejím prostředím (knihovny, runtime), takže běží stejně na tvém počítači i v produkci — konec „u mě to jede". Oproti virtuálnímu stroji sdílí jádro hostitele, takže je lehký (megabajty, start v sekundách), zatímco VM virtualizuje celý operační systém (těžší, ale izolovanější). Pro nasazování služeb jsou kontejnery výchozí volba.
Porovnej rolling, blue-green a canary nasazení.
Rolling vyměňuje instance po dávkách — bez výpadku, ale chvíli běží dvě verze naráz. Blue-green drží dvě prostředí a přepne provoz naráz — okamžitý rollback, ale potřebuje dvojnásobek zdrojů. Canary pustí novou verzi nejdřív na malé procento uživatelů, sleduje, jestli je vše OK, a pak ji rozšíří — nejbezpečnější, ale složitější. (Recreate = vypni staré, pusť nové; nejjednodušší, ale s výpadkem.)
Proč musí být databázová migrace zpětně kompatibilní?
Při rolling/canary nasazení běží během rolloutu stará i nová verze kódu naráz nad stejnou databází. Když migrace rovnou smaže nebo přejmenuje sloupec, stará verze spadne, protože ho čeká. Proto expand-contract: nejdřív přidej, nasaď kód umějící obojí, převeď data, přepni čtení a teprve pak smaž staré. Nikdy ne „přejmenovat v jednom kroku".
Co je Infrastructure as Code a immutable infrastructure?
Infrastructure as Code = infrastruktura popsaná kódem (např. Terraform), takže ji lze verzovat, projít revizí a přesně zopakovat — žádné ruční naklikávání. Immutable infrastructure = běžící servery neupravuješ, místo toho je nahradíš novými z definice. Tím se vyhneš config driftu (server, co funguje „jen na jednom místě" a nikdo neví proč).
K čemu je CI a co má zastavit nasazení?
CI (Continuous Integration) při každém nahrání kódu automaticky sestaví projekt a pustí kontroly — lint, typovou kontrolu, testy — takže se chyba chytí dřív, než se dostane do hlavní větve. Nasazení má zastavit cokoli, co selže: padající test, typová chyba, chyba lintu. Smysl je rychlá zpětná vazba a udržet hlavní větev pořád funkční.
K čemu jsou feature flags a co oddělují?
Feature flag je vypínač v konfiguraci, kterým funkci zapneš nebo vypneš bez nového nasazení. Tím oddělíš deploy (kód je nasazený v produkci) od release (funkce je opravdu vidět uživatelům): kód můžeš nasadit dřív a zapnout ho až později, jen pro část uživatelů, a když je s ním problém, vypneš ho za vteřinu místo zdlouhavého rollbacku.
Co znamenají RPO a RTO u disaster recovery?
Jsou to dvě čísla, kterými měříš plán zotavení po katastrofě. RPO (Recovery Point Objective) = kolik dat smíš v nejhorším ztratit — určuje, jak často musíš zálohovat. RTO (Recovery Time Objective) = jak dlouho smí trvat, než zase běžíš. Menší čísla = lepší ochrana, ale dražší. A platí: záloha, kterou nikdy nezkusíš obnovit, ti v krizi nepomůže.
