Žádné okno není otevřené.
Žádné okno není otevřené.
Výukový materiál pro technicky zdatného začátečníka. Od instalace přes interní model až po práci v GUI a řešení problémů.
Git je samostatný nástroj – není součástí VS Code ani jiného editoru, musí se nainstalovat zvlášť. Po instalaci ho používají všechny GUI klienty i terminál.
Doporučeno: Git for Windows – instaluje Git, Git Bash (terminál), Git Credential Manager (bezpečné ukládání hesel) a volitelně GUI nástroj.
# Spusťte PowerShell nebo CMD jako běžný uživatel winget install --id Git.Git -e --source winget # Po instalaci ověřte – zavřete a znovu otevřete terminál! git --version git version 2.55.0.windows.1
# Stáhněte instalátor z git-scm.com/download/win # Při instalaci doporučená nastavení: Default editor: Visual Studio Code (nebo Notepad++) Initial branch name: main ← ZMĚŇTE z "master" PATH environment: Git from command line (doporučeno) Line ending: Checkout Windows / Commit Unix (výchozí) Credential helper: Git Credential Manager
Doporučeno: Homebrew. macOS sice Git obsahuje, ale jeho verze je zastaralá (Apple ji neaktualizuje). Homebrew nainstaluje aktuální verzi.
# Nejdřív nainstalujte Homebrew (pokud ho nemáte) /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" # Pak nainstalujte Git brew install git # Ověření – musí to zobrazit Homebrew cestu, ne /usr/bin/git which git /opt/homebrew/bin/git ← správně (Apple Silicon) git --version git version 2.55.0
# Nainstaluje Git spolu s vývojářskými nástroji Apple xcode-select --install # Nevýhoda: starší verze Gitu, aktualizace jen s macOS updatem
brew install --cask git-credential-manager – bezpečné ukládání přihlašovacích údajů do systémové klíčenky (Keychain). Bez něj budete zadávat heslo při každém push/pull.
Na Linuxu je Git dostupný přímo v balíčkovacím systému distribuce.
sudo apt update sudo apt install git # Nebo kompletní balík s extra nástroji: sudo apt install git-all
sudo dnf install git
sudo pacman -S git
git --version git version 2.55.0
Git samotný je jen nástroj příkazového řádku. Klient je aplikace, která ho obaluje grafickým rozhraním. Použití klienta není povinné – vše jde dělat v terminálu – ale pro denní práci s kódem kombinace editoru a terminálu funguje nejlépe.
| Klient | Typ | OS | Pro koho | Cena |
|---|---|---|---|---|
| Terminál (Git Bash, PowerShell, zsh) | CLI | Všechny | Přesná kontrola, scripty, CI/CD – základ, který by měl znát každý | zdarma |
| VS Code (vestavěný + rozšíření) | GUI v editoru | Všechny | Vývojáři, kteří chtějí Git přímo v editoru – doporučeno pro tento materiál | zdarma |
| GitHub Desktop | GUI standalone | Win, macOS | Absolutní začátečníci na GitHubu, velmi jednoduchý workflow | zdarma |
| GitKraken | GUI standalone | Všechny | Vizualizace složitých branch grafů, týmová spolupráce | freemium |
| SourceTree | GUI standalone | Win, macOS | Uživatelé Atlassian stacku (Jira, Bitbucket) | zdarma |
| TortoiseGit | Shell extension | Windows | Uživatelé Průzkumníka Windows, zvyklí na TortoiseSVN | zdarma |
| IntelliJ / Rider / WebStorm | GUI v editoru | Všechny | Uživatelé JetBrains IDE – velmi propracovaná integrace | placené |
Po instalaci Gitu je potřeba nastavit identitu – Git ji připisuje každému commitu. Toto nastavení je globální (platí pro všechny projekty na počítači).
# Vaše jméno – zobrazí se u každého commitu git config --global user.name "Jan Novák" # Váš e-mail – měl by odpovídat účtu na GitHubu/GitLabu git config --global user.email "jan@example.com" # Výchozí název hlavní větve (moderní standard) git config --global init.defaultBranch main # Výchozí editor pro zprávy commitů (vyberte jeden) git config --global core.editor "code --wait" ← VS Code git config --global core.editor "notepad" ← Poznámkový blok git config --global core.editor "nano" ← nano (macOS/Linux) # Ověření – zobrazí všechna nastavení git config --list --global user.name=Jan Novák user.email=jan@example.com init.defaultbranch=main core.editor=code --wait
--global nastavení se ukládají do souboru ~/.gitconfig (macOS/Linux) nebo C:\Users\VašeJméno\.gitconfig (Windows). Lze ho otevřít a editovat přímo jako textový soubor.
Nastavení bez --global platí jen pro aktuální repozitář a ukládají se do .git/config ve složce projektu.
Pro push a pull potřebujete způsob autentizace. Doporučujeme SSH klíč – heslo zadáte jen jednou (při vytvoření klíče) a dál vše funguje automaticky.
# 1. Vygenerujte SSH klíč (funguje na Windows i macOS i Linux) ssh-keygen -t ed25519 -C "jan@example.com" # Potvrďte výchozí cestu (Enter), nastavte heslo (nebo nechte prázdné) # 2. Zkopírujte veřejný klíč # Windows: cat ~/.ssh/id_ed25519.pub ← zkopírujte celý výstup # macOS: pbcopy < ~/.ssh/id_ed25519.pub ← uloží do schránky # 3. Přidejte klíč na GitHub: # github.com → Settings → SSH and GPG keys → New SSH key # Vložte zkopírovaný klíč a uložte # 4. Ověřte připojení ssh -T git@github.com Hi jan! You've successfully authenticated.
# GitHub již nepřijímá heslo – potřebujete Personal Access Token (PAT) # github.com → Settings → Developer settings → Personal access tokens → Fine-grained # Nastavte oprávnění: Contents (Read and write), Metadata (Read) # Git Credential Manager (součást Git for Windows) uloží token automaticky # Při prvním push/pull se zobrazí přihlašovací okno – vložte token jako heslo # Manuální uložení tokenu (macOS/Linux bez GCM): git config --global credential.helper store # Token se uloží při příštím push/pull (pozor: ukládá nešifrovaně)
git commit -m "zpráva commitu" # Toto je komentář – vysvětluje co příkaz dělá. Do terminálu ho nepište. On branch main ← toto Git vypsal jako odpověď CONFLICT: ... ← varování nebo chybová zpráva ← kurzíva = naše vysvětlivka, ne součást příkazu
| Zkratka | Co znamená v praxi |
|---|---|
| HEAD~1 | „o jeden commit zpět" – HEAD~3 = o tři zpět. HEAD je vždy aktuální pozice. |
| origin | Výchozí název vzdáleného repozitáře (GitHub/GitLab). Nastavuje se automaticky při git clone. |
| origin/main | Lokální záložka stavu větve main na serveru – aktualizuje se jen při git fetch. |
| upstream | Vazba mezi vaší lokální větví a větví na serveru. Po nastavení (git push -u origin main) stačí psát jen git push. |
| a1b2c3d | Zkrácený hash commitu (7 znaků). Git si domyslí zbytek 40znakového hashe. |
Git ukládá vše do skryté složky .git/ ve vašem projektu jako čtyři typy objektů. Každý objekt je jednoznačně identifikován kryptografickým hashem svého obsahu.
| Typ | Co obsahuje | Příklad |
|---|---|---|
| blob | Obsah jednoho souboru – jen data, bez názvu a cesty | Obsah README.md |
| tree | Adresář: seznam názvů + hash blobu nebo podadresáře | Složka src/ |
| commit | Snímek projektu: hash tree, hash předchozího commitu, autor, čas, zpráva | Každý váš git commit |
| tag | Nepohyblivý, pojmenovaný ukazatel na commit | v1.0.0 |
tree 4b825dc642cb6eb9a060e54bf8d69288fbee4904 ← snímek souborů parent f3a9b1c8d27e44f1a5c3b9e0d7f2a6c4b8e1d5f9 ← předchozí commit author Jan Novák <jan@example.com> 1706000000 +0100 committer Jan Novák <jan@example.com> 1706000000 +0100 feat: přidán modul pro autentizaci
.git/ ├── objects/ ← všechny objekty (blob/tree/commit/tag) │ ├── a1/b2c3d4... ← první 2 znaky hashe = složka │ └── pack/ ← zabalené objekty po automatické optimalizaci ├── refs/heads/main ← soubor s jedním řádkem: hash posledního commitu větve ├── refs/remotes/ ← stav větví na serveru (aktualizuje se při fetch) ├── HEAD ← "ref: refs/heads/main" = kde se právě nacházíte ├── index ← staging area – seznam souborů připravených ke commitu └── config ← nastavení tohoto repozitáře
Soubor může existovat ve třech různých „stavech" zároveň. Toto je nejdůležitější věc k pochopení – zdroj většiny zmatení u začátečníků.
| Termín | Vysvětlení | Analogie |
|---|---|---|
| Working Directory | Soubory na disku – jak je vidíte v editoru. Git je sleduje, ale zatím nic nezapsal. | Rozepsaný dokument |
| Index / Staging | Přechodná oblast pro sestavení commitu. Přidáváte sem pomocí git add. Umožňuje zařadit jen část změn. | Krabice připravená k odeslání |
| Commit | Trvalý, neměnný záznam stavu souborů s unikátním hashem a zprávou. | Odeslaná zásilka s razítkem |
| Branch (větev) | Pojmenovaný ukazatel na commit. Po každém commitu se automaticky posune vpřed. | Záložka v knize |
| HEAD | Speciální reference říkající „kde teď jsem". Ukazuje na aktuální větev. | „Jste zde" na mapě |
| Remote | Vzdálený repozitář (GitHub…). Lokálně vidíte jeho stav jako origin/main – aktualizuje se jen při git fetch. | Sdílená schránka pro tým |
| Tag | Nepohyblivý štítek na commitu – neposouvá se při nových commitech. Pro označení verzí. | Trvalá etiketa |
mkdir muj-projekt && cd muj-projekt git init Initialized empty Git repository in /muj-projekt/.git/ echo "# Můj projekt" > README.md git add README.md git commit -m "chore: initial commit" [main (root-commit) a1b2c3d] chore: initial commit
# Stáhne kompletní historii a nastaví "origin" automaticky git clone https://github.com/org/repo.git # SSH varianta (po nastavení SSH klíče, viz 03) git clone git@github.com:org/repo.git git remote -v origin git@github.com:org/repo.git (fetch) origin git@github.com:org/repo.git (push)
# 1. Zjistěte stav git status modified: src/auth.py ← upraveno, není ve staging Untracked: docs/api.md ← nový soubor, Git ho nezná # 2. Přidejte do staging git add src/auth.py docs/api.md # 3. Zkontrolujte co půjde do commitu git diff --staged # 4. Zapište commit git commit -m "feat(auth): přidána podpora JWT tokenů" # 5. Odešlete na server git push
Branch je jen soubor s hashem commitu – vytvoření trvá milisekundy. Pro každou novou funkci nebo opravu si vytvořte samostatnou větev.
# Vytvořte novou větev a přepněte se na ni git switch -c feature/prihlaseni # Seznam větví (* = aktuální) git branch -a * feature/prihlaseni main remotes/origin/main # Přepnutí zpět git switch main # Smazání po mergi (Git hlídá, aby byla větev sloučena) git branch -d feature/prihlaseni
git checkout a1b2c3d), HEAD přestane ukazovat na větev. Nové commity v tomto stavu nemají větev – Git je po čase smaže. Okamžitá záchrana: git switch -c nova-vetev.
| Aspekt | git merge | git rebase |
|---|---|---|
| Co udělá | Vytvoří nový „merge commit" se dvěma rodiči | Přepíše commity vaší větve od vrcholu jiné větve |
| Výsledná historie | Zachová skutečný průběh vývoje | Lineární – jako by větvení nebylo |
| Bezpečné na sdílenou větev? | ✓ Ano | ✗ Ne – přepíše hashe |
| Kdy použít | Integrace feature do main | Čištění feature větve před PR |
Nejjednodušší případ: main se od odbočení nezměnil. Git jen posune ukazatel vpřed – žádný merge commit.
git switch main git merge feature/prihlaseni Fast-forward ← žádný merge commit, jen posunutí ukazatele # Pokud chcete merge commit i přesto (pro přehlednost v historii): git merge --no-ff feature/prihlaseni
Obě větve měly vlastní commity. Git najde společného předka, porovná obě větve a vytvoří merge commit.
git switch main git merge feature/prihlaseni Merge made by the 'ort' strategy. # Výsledný graf: * e5f6a7b Merge branch 'feature/prihlaseni' |\ | * d2e3f4a feat: JWT tokeny * | f1g2h3i docs: README |/ * b5c6d7e feat: auth module
Konflikt nastane, když obě větve upravily stejné řádky stejného souboru. Git se zastaví a čeká na vaše rozhodnutí.
git merge feature/prihlaseni CONFLICT (content): Merge conflict in src/config.py Automatic merge failed; fix conflicts and then commit. git status Unmerged paths: both modified: src/config.py ← tento soubor má konflikt
Sekce od <<<<<<< HEAD po ═══ je vaše verze. Sekce od ═══ po >>>>>>> je příchozí verze.
Smažte všechny markery (<<<<<<<, =======, >>>>>>>) a ponechte výsledný kód:
git add src/config.py ← říká Gitu: „konflikt vyřešen" git commit ← Git nabídne výchozí zprávu, potvrďte # Chcete vše vrátit a začít merge znovu? git merge --abort ← vrátí stav přesně před merge
git switch feature/prihlaseni git rebase main Successfully rebased and updated refs/heads/feature/prihlaseni. # Interaktivní – přepis posledních 3 commitů (squash, rename, drop…) git rebase -i HEAD~3 # Pokud nastane konflikt: git add soubor.py git rebase --continue ← nebo --abort pro zrušení celého rebase
main, develop ani jiné společné větve. Pouze vaše vlastní feature větve.
| Příkaz | Co dělá | Mění lokální větve? |
|---|---|---|
| git fetch | Stáhne nové commity ze serveru, aktualizuje origin/main | Ne |
| git pull | fetch + automatický merge do aktuální větve | Ano |
| git push | Odešle lokální commity na server | – |
# První push větve – -u nastaví upstream (vazbu na server) # Po nastavení stačí příště psát jen "git push" git push -u origin feature/prihlaseni Branch set up to track 'origin/feature/prihlaseni'. # Bezpečné stažení: nejdřív fetch, pak se podívejte co přišlo git fetch origin git log main..origin/main --oneline ← co přibylo na serveru git merge origin/main # Nebo zkratkou (= fetch + merge) git pull origin main # Vynucený push po rebase (jen pro VLASTNÍ větve) # --force-with-lease selže, pokud někdo jiný mezitím pushnul – bezpečnější než --force git push --force-with-lease origin feature/prihlaseni
Soubor .gitignore říká Gitu, které soubory a složky má ignorovat – neřadit je do staging ani do commitů. Typicky se jedná o sestavovací výstupy, dočasné soubory, citlivé informace a závislosti stažené ze správce balíčků.
# OS .DS_Store Thumbs.db # Logs *.log logs/ # Temp tmp/ temp/ *.tmp # IDE .vscode/ .idea/ *.user # Secrets .env *.key *.pfx # Build bin/ obj/ dist/ build/ # Node node_modules/ # Python __pycache__/ *.pyc # Misc *.bak *.swp
.git/. Pravidla platí rekurzivně pro všechny podsložky – pokud chcete omezit pravidlo jen na jednu složku, přidejte lomítko na začátek: /build/.
Přidání pravidla do .gitignore nezastaví sledování souborů, které Git již zná. Nejprve je musíte odebrat z indexu příkazem git rm --cached.
# 1. Přidejte (nebo doplňte) pravidlo do .gitignore echo ".env" >> .gitignore # 2. Odeberte konkrétní soubor z indexu (soubor na disku zůstane) git rm --cached .env # Alternativa: odebrání celé složky rekurzivně git rm --cached -r node_modules/ # 3. Ověřte stav – soubor by měl zmizet ze sledovaných git status Changes to be committed: deleted: .env ← bude odstraněn z Gitu, ale fyzicky zůstane # 4. Zacommitujte změnu git commit -m "chore: remove .env from tracking, update .gitignore" # Hromadný cleanup – přepsat celý index podle aktuálního .gitignore # Pozor: dočasně odebere vše a znovu přidá jen neignorvané soubory git rm --cached -r . git add . git commit -m "chore: apply .gitignore cleanup"
.gitignore – musíte přepsat historii (git filter-repo) a zneplatnit všechna kompromitovaná tajemství.
VS Code má Git integraci vestavěnou – nepotřebujete žádné rozšíření pro základní operace. Tato sekce popisuje, kde co najít.
| Prvek UI | Co znamená |
|---|---|
| Staged Changes | Soubory přidané do staging (git add) – půjdou do příštího commitu |
| Changes | Upravené soubory, které ještě nejsou ve staging |
| A / M / D / U | Added / Modified / Deleted / Untracked – stav souboru |
| ↑2 ↓0 | Stavový řádek: máte 2 lokální commity, které jste nepushnuli; 0 stažených ze serveru |
| ⎇ main | Aktuální větev – kliknutím ji změníte nebo vytvoříte novou |
| Pole pro zprávu commitu | Sem napište zprávu a stiskněte Ctrl+Enter (nebo Cmd+Enter na macOS) pro commit |
Ikona ✓ v panelu | Commit tlačítko (alternativa k Ctrl+Enter) |
Ikona … v panelu | Rozbalovací menu – Push, Pull, Fetch, Branch, Stash a další |
Klikněte na soubor ve Changes – VS Code otevře diff editor s původní verzí vlevo a upravenou vpravo. Kliknutím na soubor ve Staged Changes uvidíte, co přesně půjde do commitu (ekvivalent git diff --staged).
Každou operaci z terminálu lze provést i ve VS Code. Tabulka ukazuje obě cesty pro nejčastější úkony.
| Operace | Příkaz (terminál) | VS Code GUI |
|---|---|---|
| Zobrazit stav | git status | Source Control panel – automaticky, vždy aktuální |
| Přidat soubor do staging | git add soubor.py | Klik na + vedle souboru ve Changes |
| Přidat vše do staging | git add . | Klik na + vedle nadpisu Changes |
| Odebrat ze staging | git restore --staged soubor.py | Klik na – vedle souboru ve Staged Changes |
| Zahodit lokální změny | git restore soubor.py | Klik na ↩ (Discard Changes) vedle souboru |
| Zobrazit diff souboru | git diff soubor.py | Klik na soubor ve Changes |
| Commit | git commit -m "zpráva" | Napsat zprávu do pole → Ctrl+Enter |
| Push | git push | … menu → Push nebo tlačítko Sync Changes (↑↓) ve stavovém řádku |
| Pull | git pull | … menu → Pull |
| Fetch | git fetch | … menu → Fetch |
| Vytvořit větev | git switch -c nova-vetev | Klik na název větve ve stavovém řádku → Create new branch… |
| Přepnout větev | git switch jina-vetev | Klik na název větve ve stavovém řádku → vyberte větev ze seznamu |
| Merge větve | git merge feature/xyz | … menu → Branch → Merge Branch… |
| Stash (odložit změny) | git stash push -m "popis" | … menu → Stash → Stash All Changes |
| Stash pop (obnovit) | git stash pop | … menu → Stash → Apply Latest Stash |
| Zobrazit historii | git log --oneline --graph | Rozšíření Git Graph (viz 13) – vestavěná integrace je omezená |
| Anotace řádků (blame) | git blame soubor.py | Rozšíření GitLens → inline anotace při najetí myší |
Instalace rozšíření: Ctrl+Shift+X → vyhledejte název → Install.
eamodio.gitlens
Nejpopulárnější Git rozšíření pro VS Code. Zobrazuje inline anotace (kdo a kdy změnil řádek), procházení historie souboru, porovnávání větví a vizuální commit graph.
settings.json){ "gitlens.currentLine.enabled": true, ← blame na aktuálním řádku "gitlens.hovers.currentLine.over": "line", ← detail při hoveru "gitlens.codeLens.enabled": false, ← vypnout pokud ruší v kódu "gitlens.statusBar.enabled": true ← stav v stavovém řádku }
mhutchie.git-graph
Zobrazí interaktivní commit graph přímo ve VS Code – větvení, merges, tagy. Spustíte přes … menu → View Git Graph nebo příkazovou paletou (Ctrl+Shift+P → Git Graph: View Git Graph).
donjayamanne.githistory
Doplňuje vestavěnou integraci o procházení historie konkrétního souboru nebo řádku. Pravý klik na soubor → Git: View File History.
github.vscode-pull-request-github
Pokud pracujete s GitHubem, toto rozšíření přináší Pull Request workflow přímo do VS Code: vytvoření PR, code review s komentáři inline, merge – vše bez otevírání prohlížeče.
Po instalaci: přihlaste se přes GitHub Account (ikona účtu v sidebar) a repozitář musí mít origin nastavený na GitHub.
{ // Automatický fetch každých 3 minuty (zobrazí ↓ v stavovém řádku) "git.autofetch": true, "git.autofetchPeriod": 180, // Potvrzení před synchronizací (push + pull najednou) "git.confirmSync": true, // Automatický commit po stage (vypnuto – lepší mít kontrolu) "git.enableSmartCommit": false, // Zobrazit počet commitů čekajících na push v stavovém řádku "scm.countBadge": "all", // Výchozí větev pro nové repozitáře "git.defaultBranchName": "main", // Řádkové konce – důležité pro týmy s různými OS "files.eol": "\n" }
git commit.
VS Code (od verze 1.69) obsahuje Merge Editor – grafické rozhraní pro řešení konfliktů. Aktivuje se automaticky při otevření konfliktního souboru.
Merge Editor zobrazí tři panely vedle sebe:
| Panel | Obsah | Odpovídá |
|---|---|---|
| Current (vlevo) | Vaše aktuální verze (větev, kam mergujete) | Sekce <<<<<<< HEAD |
| Incoming (vpravo) | Verze přicházející z mergované větve | Sekce >>>>>>> v souboru |
| Result (dole) | Výsledný soubor – zde vidíte a editujete konečnou podobu | Co bude zapsáno |
VS Code zobrazí v horní části souboru banner s konfliktem. Klikněte na tlačítko Resolve in Merge Editor.
Nad každým konfliktem se zobrazí tlačítka – vyberte jedno:
| Tlačítko | Co udělá |
|---|---|
| Accept Current | Zachová vaši verzi (levý panel) |
| Accept Incoming | Přijme příchozí verzi (pravý panel) |
| Accept Both | Vloží obě verze za sebou (nejdřív Current, pak Incoming) |
| (ruční editace) | Klikněte přímo do panelu Result a upravte text libovolně |
Zkontrolujte panel Result – musí být syntakticky správný, bez zbylých markerů. Pak klikněte Complete Merge v pravém dolním rohu Merge Editoru.
VS Code automaticky přidá vyřešený soubor do staging. Napište zprávu do Source Control panelu a stiskněte Ctrl+Enter.
# Zruší commit, soubory zůstanou ve staging (připravené ke commitu) git reset --soft HEAD~1 # Zruší commit, soubory zůstanou na disku ale ne ve staging git reset HEAD~1 # Zruší commit a smaže i změny na disku (DESTRUKTIVNÍ – nelze vrátit) git reset --hard HEAD~1
# Přidejte zapomenuté soubory do staging, pak: git commit --amend ← přepíše poslední commit (nový hash) git commit --amend -m "nová zpráva" ← jen změna zprávy # Pokud jste commit již pushnuli na VLASTNÍ feature větev: git push --force-with-lease # Pushnuto na sdílenou větev? Amend NEPROVÁDĚJTE. # Místo toho vytvořte nový opravný commit: git revert HEAD ← nový commit, který předchozí bezpečně „odvolá"
Git málokdy opravdu smaže data – jen je přestane referencovat. git reflog zaznamenává všechny pohyby HEAD za posledních 90 dní.
git reflog d2e3f4a HEAD@{0}: merge: Fast-forward b5c6d7e HEAD@{1}: checkout: moving to main c9d0e1f HEAD@{2}: commit: fix: login bug ← tento commit hledáte # Obnovte smazanou větev z konkrétního commitu: git branch zachrana c9d0e1f # Nebo se přepněte přímo: git switch -c zachrana HEAD@{2}
Někdo jiný pushnul změny na server dříve než vy. Vaše větev a serverová větev se „rozcházejí".
! [rejected] main -> main (non-fast-forward) hint: Updates were rejected because the remote contains work you do not have. # Stáhněte a integrujte cizí změny, pak znovu pushněte: git pull --rebase origin main git push origin main
Git 2.27+ odmítá automaticky rozhodnout strategii při divergentních větvích – je nutné ji specifikovat explicitně.
| Strategie | Příkaz | Kdy použít |
|---|---|---|
| Rebase (doporučeno pro solo projekty) | git pull --rebase origin <větev> | Čistá lineární historie |
| Merge | git pull --no-rebase origin <větev> | Zachování merge commitu |
| Fast-forward only | git pull --ff-only origin <větev> | Jen pokud je FF možný |
git fetch origin git log --oneline --graph main origin/main
git pull --rebase origin main # Nastavit jako trvalý default pro tento repozitář: git config pull.rebase true
git rebase --abort # vrátí stav přesně před git pull --rebase
# Uloží všechny neuložené změny do zásobníku (working dir + staging) git stash push -m "WIP: přihlašovací formulář" # Přepněte, udělejte jiný úkol, vraťte se… git stash list stash@{0}: On feature/prihlaseni: WIP: přihlašovací formulář # Obnovte a smažte ze zásobníku git stash pop
Pokud jste spustili merge nebo rebase a situace je nepřehledná, můžete celou operaci zrušit a vrátit repozitář přesně do stavu před ní.
# Zrušit probíhající merge (včetně všech konfliktů) git merge --abort # Zrušit probíhající rebase git rebase --abort # Ověřte stav – mělo by hlásit čistý stav git status On branch main nothing to commit, working tree clean
# Aplikuje konkrétní commit na aktuální větev (bez přepínání) git cherry-pick c9d0e1f # Více commitů najednou: git cherry-pick c9d0e1f d2e3f4a # Bez okamžitého commitu (pro ruční úpravu před zápisem): git cherry-pick -n c9d0e1f
git-crypt umožňuje transparentně šifrovat vybrané soubory přímo v repozitáři pomocí GPG nebo sdíleného symetrického klíče. Ostatní soubory zůstávají nešifrované – spolupráce na nich funguje normálně.
Šifrování probíhá přes Git smudge/clean filtry: při git add se soubor zašifruje, při git checkout automaticky dešifruje. Pro kohokoli bez klíče vypadají chráněné soubory v repozitáři jako binární šum.
# macOS (Homebrew) brew install git-crypt # Debian / Ubuntu sudo apt install git-crypt # Windows – přes WSL nebo Scoop scoop install git-crypt
# 1. Inicializujte git-crypt v repozitáři (vytvoří symetrický klíč) git-crypt init # 2. Nastavte, které soubory se mají šifrovat – editujte .gitattributes # Přidejte řádky ve formátu: <vzor> filter=git-crypt diff=git-crypt .gitattributes !filter !merge !diff secretfile filter=git-crypt diff=git-crypt *.key filter=git-crypt diff=git-crypt secrets/** filter=git-crypt diff=git-crypt # 3. Zacommitujte .gitattributes (samotná pravidla nejsou tajná) git add .gitattributes git commit -m "chore: add git-crypt config"
# Export klíče do souboru – tento soubor NIKDY necommitujte! git-crypt export-key ./git-crypt-key # Na jiném počítači / pro kolegu – odemknutí repozitáře klíčem git-crypt unlock ./git-crypt-key
# Přidejte GPG klíč kolegy (musí mít veřejný klíč v keyring) git-crypt add-gpg-user KLÍČ_ID_NEBO_EMAIL # git-crypt automaticky přidá zašifrovanou kopii klíče do .git-crypt/ # Kolega pak odemkne repozitář svým GPG klíčem: git-crypt unlock
# Zobrazí, které soubory jsou šifrované a které ne git-crypt status encrypted: secrets/api.key not encrypted: README.md not encrypted: src/main.py # Zamknout repozitář (šifrované soubory se znovu zakódují) git-crypt lock
.gitattributes, zůstane v historii nešifrovaný (viz 18 pro vyčištění).
git-crypt-key) uchovávejte v password manageru nebo bezpečném úložišti – bez něj jsou data nenávratně ztracená.git-crypt-key do .gitignore, aby se klíč nikdy nedostal do repozitáře.git-crypt status, zda je správně označen k šifrování.Pokud do repozitáře omylem projde citlivý soubor (heslo, API klíč, binárka), samo odstranění souboru nestačí – data zůstávají dostupná ve starší historii. Tato sekce popisuje dvě metody vyčištění.
git clone --mirror).
Hodí se tehdy, kdy chcete zachovat aktuální stav souborů, ale celou historii zahodit – například při startu open-source projektu z interního repozitáře.
# 1. Vytvořte orphan branch (nová větev bez jakékoli historie) git switch --orphan clean-main # 2. Přidejte všechny aktuální soubory do staging git add -A # 3. Vytvořte nový initial commit git commit -m "Initial clean commit" # 4. Smažte starou větev git branch -D main # 5. Přejmenujte novou větev na main git branch -m main # 6. Force push na GitHub (přepíše vzdálenou historii) git push origin main --force # 7. Smažte ostatní vzdálené větve, které už nepotřebujete git push origin --delete <název-větve>
git reflog a git fsck --unreachable, dokud neproběhne garbage collection. Pro skutečné odstranění z lokálního repozitáře spusťte:
git reflog expire --all --expire=now && git gc --prune=now --aggressive
Hodí se tehdy, kdy chcete zachovat historii, ale z každého commitu vymazat jeden konkrétní soubor (nebo složku).
# Instalace (git filter-repo není součástí Gitu) brew install git-filter-repo ← macOS pip install git-filter-repo ← cross-platform # Odstraňte soubor z celé Git historie (--invert-paths = "vše kromě") git filter-repo --path secrets.env --invert-paths # Odstraňte celou složku z celé Git historie git filter-repo --path config/secrets/ --invert-paths # Ověřte, že soubor v historii opravdu chybí git log --all --full-history -- secrets.env ← prázdný výstup = soubor byl úspěšně smazán ze všech commitů # Force push – přepíše vzdálený repozitář git push origin --force --all git push origin --force --tags
| Kategorie | Příkaz | Popis |
|---|---|---|
| Nastavení | git config --global user.name "X" | Nastavit jméno |
| git config --list --global | Zobrazit globální konfiguraci | |
| git config --global core.editor "code --wait" | Nastavit VS Code jako editor | |
| Staging | git status | Stav working directory |
| git add soubor | Přidat soubor do staging | |
| git add -p | Interaktivní přidávání po částech | |
| git diff | Změny na disku oproti staging | |
| git diff --staged | Staging oproti poslednímu commitu | |
| Historie | git log --oneline --graph --all | Kompaktní vizuální log |
| git show HEAD | Detail posledního commitu | |
| git blame soubor | Kdo a kdy upravil každý řádek | |
| Vrácení | git restore soubor | Zahodit změny na disku (od posl. commitu) |
| git restore --staged soubor | Vyjmout ze staging (zachová změny) | |
| git reset --soft HEAD~1 | Zrušit commit, zachovat staging | |
| git revert HEAD | Nový opravný commit (bezpečné) | |
| Tagy | git tag v1.0.0 -m "Release 1.0" | Annotovaný tag |
| git push origin --tags | Odeslat tagy na remote | |
| Záchrana | git reflog | Historie všech pohybů HEAD (90 dní) |
| git stash pop | Obnovit naposledy odložené změny |
Pro nasazení statického webu existují dvě časté cesty: kontejner (Docker + hosting) nebo serverless edge. Kontejner dává plnou kontrolu, ale vyžaduje správu serveru, škálování a platbu za běžící instanci i v době nulového provozu. Cloudflare Workers fungují jinak – kód nebo soubory běží na hraničních uzlech sítě Cloudflare, spouštějí se jen při požadavku a požadavky na statické soubory jsou zdarma a bez limitu (spouštění Worker kódu má na bezplatném tarifu limit 100 000 požadavků denně). Pro jednoduché weby bez backendu je to nejjednodušší volba: žádný server, žádná údržba, globální CDN v ceně.
Cloudflare Workers je serverless platforma servírující statické soubory nebo spouštějící kód na globální CDN síti. Pro statický web jsou požadavky zdarma a bez limitu.
Poznámka: Cloudflare pro nové projekty doporučuje Workers se statickými assety. Cloudflare Pages zůstává nadále podporován, ale nový vývoj směřuje do Workers (deprecated je starší Workers Sites, nikoli Pages).
| Pojem | Popis |
|---|---|
| Worker | Serverless funkce nebo statický web nasazený na Cloudflare |
| Wrangler | CLI nástroj Cloudflare pro správu Workers |
| wrangler.toml | Konfigurační soubor projektu |
| Static Assets | Statické soubory (HTML, CSS, JS, obrázky) servírované přímo |
| Routes | Pravidla pro mapování URL na Worker |
| Custom Domain | Vlastní doména nebo subdoména napojená na Worker |
| Zone | Doménová zóna spravovaná Cloudflare |
| Proxied (oranžový mrak) | DNS záznam prochází přes Cloudflare proxy |
| Redirect | HTTP přesměrování – prohlížeč změní adresu |
| Rewrite | Interní přepis URL – prohlížeč adresu nezmění |
Uživatel → DNS (Cloudflare) → Worker (redirect / rewrite / logika) → Static Assets
Potřebný software: Node.js v22+ (včetně npm; doporučeno aktuální LTS, v září 2026 Node.js 24) a Git. Node.js 20 skončil s podporou v březnu 2026.
# PowerShell nebo CMD jako běžný uživatel winget install OpenJS.NodeJS.LTS winget install Git.Git # Po instalaci zavřete a znovu otevřete terminál node --version # očekáváno v22+ git --version
# Stáhněte nvm-setup.exe z github.com/coreybutler/nvm-windows/releases nvm install lts nvm use lts node --version
brew install node git node --version # očekáváno v22+
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.7/install.sh | bash # Znovu načtěte shell (source ~/.bashrc nebo nové okno terminálu) nvm install --lts sudo apt install git node --version
sudo dnf install nodejs npm git node --version
mkdir muj-web && cd muj-web
npm init -y
npm install -D wrangler
npx wrangler --version # ověření
npx wrangler login # otevře prohlížeč, token se uloží do ~/.wrangler/
npx wrangler whoami # ověření přihlášení
muj-web/
├── .git/ ← Git repozitář
├── .gitignore
├── wrangler.toml ← konfigurace Workers
├── package.json
└── public/
├── index.html
├── style.css
└── 404.html
muj-web/
├── .git/
├── .gitignore
├── wrangler.toml
├── package.json
├── src/
│ └── worker.js ← Worker script
└── public/
├── index.html
├── style.css
└── 404.html
name = "muj-web"
compatibility_date = "2026-09-01"
[assets]
directory = "./public"
not_found_handling = "404-page"
name = "muj-web"
compatibility_date = "2026-09-01"
[assets]
directory = "./public"
not_found_handling = "404-page"
[[routes]]
pattern = "www.jan-zak.cz/*"
zone_name = "jan-zak.cz"
[[routes]]
pattern = "jan-zak.cz/*"
zone_name = "jan-zak.cz"
name = "wtest-jan-zak"
compatibility_date = "2026-09-01"
[assets]
directory = "./public"
not_found_handling = "404-page"
[[routes]]
pattern = "wtest.jan-zak.cz/*"
zone_name = "jan-zak.cz"
name = "jan-zak-web"
compatibility_date = "2026-09-01"
main = "src/worker.js"
[assets]
directory = "./public"
not_found_handling = "404-page"
[[routes]]
pattern = "jan-zak.cz/*"
zone_name = "jan-zak.cz"
[[routes]]
pattern = "www.jan-zak.cz/*"
zone_name = "jan-zak.cz"
[[routes]]
pattern = "tools.jan-zak.cz/*"
zone_name = "jan-zak.cz"
| Pole | Popis | Příklad |
|---|---|---|
name | Interní název Workeru (bez teček) | "muj-web" |
compatibility_date | Datum kompatibility runtime | "2026-09-01" |
main | Cesta k Worker scriptu | "src/worker.js" |
assets.directory | Složka se statickými soubory | "./public" |
assets.not_found_handling | Chování při 404 | "404-page" |
routes[].pattern | URL vzor (vždy s /*) | "jan-zak.cz/*" |
routes[].zone_name | Apex doména (zone v Cloudflare) | "jan-zak.cz" |
npx wrangler dev # → http://localhost:8787, live reload
<!DOCTYPE html>
<html lang="cs"><head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Jan Novák</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<h1>Jan Novák</h1>
<nav><a href="/">Úvod</a> <a href="/o-mne.html">O mně</a></nav>
</body></html>
<!DOCTYPE html><html lang="cs"><head><meta charset="UTF-8"><title>404</title></head>
<body><h1>404 – Stránka nenalezena</h1><p><a href="/">Zpět na úvod</a></p></body></html>
npx wrangler deploy # nasazení na Cloudflare
npx wrangler deployments list # výpis verzí
Po úspěšném deployi Wrangler vrátí URL ve tvaru https://muj-web.<nazev>.workers.dev. Každý deploy vytváří novou verzi – Cloudflare uchovává posledních 100 verzí.
| Typ | Name | Value | Proxy status |
|---|---|---|---|
| AAAA | wtest | 100:: | Proxied |
Pokud CNAME již existuje: Zkontrolujte, že je Proxied. Worker přes
[[routes]]CNAME nemodifikuje – pouze zachytí provoz. Původní CNAME zůstane zachováno.
Resolve-DnsName wtest.jan-zak.cz # ověření DNS
nslookup wtest.jan-zak.cz
dig wtest.jan-zak.cz # ověření DNS
dig wtest.jan-zak.cz # ověření DNS # Pokud dig chybí: sudo apt install dnsutils (Debian/Ubuntu) # sudo dnf install bind-utils (Fedora/RHEL)
Redirecty vyžadují Worker script. Čistý wrangler.toml přesměrování neumí.
export default {
async fetch(request, env) {
const url = new URL(request.url);
if (url.hostname === "tools.jan-zak.cz") {
return Response.redirect("https://jan-zak.cz/tools/jz-tools.html", 301);
}
return env.ASSETS.fetch(request);
}
};
const redirects = {
"tools.jan-zak.cz": "https://jan-zak.cz/tools/jz-tools.html",
"blog.jan-zak.cz": "https://jan-zak.cz/blog/",
"cv.jan-zak.cz": "https://jan-zak.cz/dokumenty/cv.pdf",
};
export default {
async fetch(request, env) {
const url = new URL(request.url);
const target = redirects[url.hostname];
if (target) return Response.redirect(target, 301);
return env.ASSETS.fetch(request);
}
};
if (url.hostname === "www.jan-zak.cz") {
url.hostname = "jan-zak.cz";
return Response.redirect(url.toString(), 301);
}
// tools.jan-zak.cz/neco → jan-zak.cz/tools/neco
if (url.hostname === "tools.jan-zak.cz") {
const newUrl = `https://jan-zak.cz/tools${url.pathname}${url.search}`;
return Response.redirect(newUrl, 301);
}
| Kód | Typ | Cachování | Použití |
|---|---|---|---|
| 301 | Trvalý | Ano | Trvalé přejmenování, migrace |
| 302 | Dočasný | Ne | Testování, dočasné přesměrování |
Upozornění: 301 redirect si prohlížeč zakešuje. Při testování vždy nejprve používejte 302.
URL rewrite servíruje jiný obsah, než odpovídá adrese v prohlížeči – adresa v adresním řádku se nemění.
| Redirect (301/302) | Rewrite | |
|---|---|---|
| Adresa v prohlížeči | Změní se na cílovou URL | Zůstane původní |
| HTTP odpověď | 301 / 302 | 200 (obsah cíle) |
| Viditelnost pro uživatele | Ano | Ne |
| Vhodné pro | Trvalé přejmenování, SEO | Hezké URL, skrytí struktury |
Uživatel vidí /tools, Worker interně načte /tools/jz-tools.html:
export default {
async fetch(request, env) {
const url = new URL(request.url);
if (url.pathname === "/tools") {
url.pathname = "/tools/jz-tools.html";
return env.ASSETS.fetch(url.toString()); // prohlížeč stále vidí /tools
}
return env.ASSETS.fetch(request);
}
};
Uživatel vidí https://tools.jan-zak.cz, Worker interně servíruje /tools/jz-tools.html:
export default {
async fetch(request, env) {
const url = new URL(request.url);
if (url.hostname === "tools.jan-zak.cz") {
const rewriteUrl = new URL(request.url);
rewriteUrl.hostname = "jan-zak.cz";
rewriteUrl.pathname = "/tools/jz-tools.html";
return fetch(rewriteUrl.toString());
}
return env.ASSETS.fetch(request);
}
};
const rewrites = {
"/tools": "/tools/jz-tools.html",
"/cv": "/dokumenty/jan-zak-cv.pdf",
"/kontakt": "/stranky/kontaktni-formular.html",
};
export default {
async fetch(request, env) {
const url = new URL(request.url);
const target = rewrites[url.pathname];
if (target) {
const rewriteUrl = new URL(request.url);
rewriteUrl.pathname = target;
return env.ASSETS.fetch(rewriteUrl.toString());
}
return env.ASSETS.fetch(request);
}
};
const redirects = { "tools.jan-zak.cz": "https://jan-zak.cz/tools" };
const rewrites = { "/tools": "/tools/jz-tools.html", "/cv": "/dokumenty/cv.pdf" };
export default {
async fetch(request, env) {
const url = new URL(request.url);
// 1. Redirect subdomény (prohlížeč změní adresu)
const redirectTarget = redirects[url.hostname];
if (redirectTarget) return Response.redirect(redirectTarget, 301);
// 2. Rewrite cesty (prohlížeč adresu nezmění)
const rewritePath = rewrites[url.pathname];
if (rewritePath) {
const rUrl = new URL(request.url);
rUrl.pathname = rewritePath;
return env.ASSETS.fetch(rUrl.toString());
}
return env.ASSETS.fetch(request);
}
};
| Scénář | Doporučení |
|---|---|
| Trvalé přejmenování stránky (SEO) | Redirect 301 |
Hezká URL (/tools místo /tools/jz-tools.html) | Rewrite |
| Subdoména jako alias sekce (transparentní) | Rewrite |
| Subdoména jako alias sekce (viditelný přesun) | Redirect |
| Testování nové verze stránky | Redirect 302 |
| Skrytí interní struktury souborů | Rewrite |
Git a Wrangler jsou zcela nezávislé nástroje – nedochází mezi nimi ke konfliktům.
| Nástroj | Co spravuje | Kde ukládá data |
|---|---|---|
| Git | Verzování souborů projektu | .git/ (v adresáři projektu) |
| Wrangler | Deploy na Cloudflare, tokeny | ~/.wrangler/ (globálně, mimo projekt) |
# npm závislosti
node_modules/
# Wrangler lokální cache
.wrangler/
# macOS
.DS_Store
| Soubor / složka | Do Gitu? | Důvod |
|---|---|---|
wrangler.toml | Ano | Konfigurační soubor, ne citlivá data |
src/worker.js | Ano | Zdrojový kód |
public/ | Ano | Statické soubory webu |
package.json | Ano | Definice projektu |
node_modules/ | Ne | Generováno npm install |
.wrangler/ | Ne | Lokální cache Wrangleru |
.DS_Store | Ne | macOS systémový soubor |
Praktický důsledek pro rollback: Routes v
wrangler.tomlse při Cloudflare rollbacku neobnoví – Worker rollback vrátí pouze kód. Verzováníwrangler.tomlv Gitu to řeší:git restore --source=<commit> -- wrangler.toml+ nový deploy.
cd muj-web
git init
# vytvořte .gitignore
git add .
git commit -m "Initial commit: Cloudflare Workers static site"
Cloudflare Workers uchovává posledních 100 verzí pro každý Worker.
npx wrangler deployments list # výpis verzí
npx wrangler rollback --message "Důvod rollbacku" # poslední stabilní
npx wrangler rollback <version-id> --message "Popis" # konkrétní verze
| Omezení | Popis |
|---|---|
| Počet verzí | Posledních 100 verzí |
| Routes | Rollback nevrátí změny routes – pouze kód |
| KV / R2 / D1 | Data se nerolují zpět |
| Secrets | Použije aktuální hodnoty, ne historické |
Praktický důsledek: Routes obnoví Git (
git restore --source=<commit> -- wrangler.toml+wrangler deploy), ne Cloudflare rollback.
Správný vzor: definujte hlavičky jako konstantu a aplikujte je přes pomocnou funkci. Přepisujte jen ty, které CF Assets sám nenastavuje.
const SECURITY_HEADERS = {
// Zabraňuje MIME sniffingu – prohlížeč respektuje Content-Type bez hádání.
"X-Content-Type-Options": "nosniff",
// Vypíná legacy XSS auditor (IE/starý Chrome). Hodnota "1; mode=block" je dnes nebezpečná.
"X-XSS-Protection": "0",
// Omezuje obsah Referer při navigaci na jiné domény.
"Referrer-Policy": "strict-origin-when-cross-origin",
// Nahrazuje X-Frame-Options – CSP frame-ancestors má vyšší prioritu, XFO se pak ignoruje.
"Content-Security-Policy": "frame-ancestors 'none'",
// Zakazuje přístup k browser API, která stránka nepotřebuje.
"Permissions-Policy": "geolocation=(), camera=(), microphone=()",
// Izoluje browsing context – mitigace Spectre přes sdílenou paměť.
"Cross-Origin-Opener-Policy": "same-origin",
// Zabraňuje načtení zdrojů této domény cross-origin stránkami.
"Cross-Origin-Resource-Policy": "same-origin",
// Cache-Control – CF Assets ho sám nenastavuje; 7 dní v prohlížeči i CDN.
"Cache-Control": "public, max-age=604800",
};
function addSecurityHeaders(response) {
const headers = new Headers(response.headers);
for (const [key, value] of Object.entries(SECURITY_HEADERS)) {
headers.set(key, value);
}
return new Response(response.body, { status: response.status, statusText: response.statusText, headers });
}
export default {
async fetch(request, env) {
const response = await env.ASSETS.fetch(request);
return addSecurityHeaders(response);
},
};
Poznámky:
Strict-Transport-Securitypřidává Cloudflare automaticky – ve Workeru je zbytečná.X-Frame-Optionsje zastaralé; pokud jsou přítomny oba, prohlížeč ignoruje XFO ve prospěch CSPframe-ancestors.Content-Security-Policy: default-src 'self'je příliš restriktivní pro statické weby načítající fonty nebo CDN skripty – upravte dle potřeby.
Nastavení v dashboardu: SSL/TLS → Edge Certificates → Always Use HTTPS. Worker script není potřeba.
Worker může chránit obsah nebo API různými způsoby. Každá metoda odpovídá jinému use-case:
| Metoda | Vhodné pro | Kde se ověřuje |
|---|---|---|
| Basic Auth | Jednoduchá ochrana stránky heslem | Hlavička Authorization: Basic … |
| Bearer token | Ochrana API endpointu statickým tokenem | Hlavička Authorization: Bearer … |
| API key v hlavičce | Strojový přístup (M2M), třetí strany | Vlastní hlavička, např. X-Api-Key |
| Cookie / session token | Přihlášení přes formulář, SPA | Cookie session=… |
Tajné hodnoty (hesla, tokeny) nikdy nevkládejte přímo do kódu – ukládejte je jako Worker Secrets (npx wrangler secret put NAZEV) a čtěte přes env.NAZEV.
export default {
async fetch(request, env) {
const auth = request.headers.get("Authorization");
const expected = "Basic " + btoa("uzivatel:" + env.HESLO);
if (!auth || auth !== expected) {
return new Response("Přístup odepřen", {
status: 401,
headers: { "WWW-Authenticate": 'Basic realm="Sekce"' },
});
}
return env.ASSETS.fetch(request);
}
};
export default {
async fetch(request, env) {
const url = new URL(request.url);
if (url.pathname.startsWith("/api/")) {
const auth = request.headers.get("Authorization") ?? "";
if (!auth.startsWith("Bearer ") || auth.slice(7) !== env.API_TOKEN) {
return new Response("Unauthorized", { status: 401 });
}
}
return env.ASSETS.fetch(request);
}
};
const key = request.headers.get("X-Api-Key");
if (key !== env.API_KEY) {
return new Response("Forbidden", { status: 403 });
}
// Pomocná funkce pro čtení cookie ze záhlaví
function getCookie(request, name) {
const header = request.headers.get("Cookie") ?? "";
const match = header.match(new RegExp(`(?:^|;\\s*)` + name + `=([^;]*)`));
return match?.[1] ?? null;
}
export default {
async fetch(request, env) {
const session = getCookie(request, "session");
if (session !== env.SESSION_SECRET) {
return Response.redirect("/login", 302);
}
return env.ASSETS.fetch(request);
}
};
Worker může sám volat externí API (databáze, notifikace, třetí strany). Tajné klíče předávejte vždy přes env, nikdy napevno v kódu.
const response = await fetch("https://api.sluzba.cz/data", {
headers: {
"X-Api-Key": env.SLUZBA_API_KEY,
"Content-Type": "application/json",
},
});
const data = await response.json();
const response = await fetch("https://api.sluzba.cz/items", {
headers: { "Authorization": "Bearer " + env.ACCESS_TOKEN },
});
const credentials = btoa(env.API_USER + ":" + env.API_PASS);
const response = await fetch("https://legacy.api.cz/endpoint", {
headers: { "Authorization": "Basic " + credentials },
});
// 1. Získejte přístupový token
const tokenRes = await fetch("https://auth.sluzba.cz/oauth/token", {
method: "POST",
headers: { "Content-Type": "application/x-www-form-urlencoded" },
body: new URLSearchParams({
grant_type: "client_credentials",
client_id: env.CLIENT_ID,
client_secret: env.CLIENT_SECRET,
scope: "read",
}),
});
const { access_token } = await tokenRes.json();
// 2. Zavolejte chráněné API s tokenem
const data = await fetch("https://api.sluzba.cz/resource", {
headers: { "Authorization": "Bearer " + access_token },
}).then(r => r.json());
Poznámka k caching: OAuth token má životnost (typicky 3 600 s). Worker je bezstavový – token se získává znovu při každém požadavku. Pro omezení počtu token requestů použijte Cloudflare KV jako cache: uložte token s TTL a čtěte ho při dalším požadavku.
const country = request.cf?.country;
if (country === "CZ" || country === "SK") {
if (!url.pathname.startsWith("/cs/")) {
url.pathname = "/cs" + url.pathname;
return Response.redirect(url.toString(), 302);
}
}
if (url.pathname === "/api/status") {
return new Response(
JSON.stringify({ status: "ok", timestamp: new Date().toISOString() }),
{ headers: { "Content-Type": "application/json" } }
);
}
const routes = {
"jan-zak.cz": null,
"www.jan-zak.cz": "https://jan-zak.cz",
"tools.jan-zak.cz": "https://jan-zak.cz/tools/jz-tools.html",
"blog.jan-zak.cz": "https://jan-zak.cz/blog/",
};
export default {
async fetch(request, env) {
const url = new URL(request.url);
const target = routes[url.hostname];
if (target) {
if (target === "https://jan-zak.cz") {
url.hostname = "jan-zak.cz";
return Response.redirect(url.toString(), 301);
}
return Response.redirect(target, 301);
}
return env.ASSETS.fetch(request);
}
};
/* v route pattern – bez hvězdičky Worker neobsluhuje podsložky.name) nesmí obsahovat tečky – používejte pomlčky.compatibility_date nastavte na aktuální datum při vytváření projektu; neměňte ho bez důvodu.wrangler.toml v Git repozitáři.100:: (Proxied).[[routes]], ne custom_domain = true.302, na produkci přepněte na 301 až po ověření.env.ASSETS.fetch(rewriteUrl.toString())).npx wrangler secret put MOJE_HESLO # přístup přes env.MOJE_HESLO
wrangler.toml – routes se při Cloudflare rollbacku neobnoví, Git je má.node_modules/ a .wrangler/ do .gitignore.npx wrangler deployments list).| Příkaz | Popis |
|---|---|
npx wrangler login | Přihlášení ke Cloudflare |
npx wrangler whoami | Zobrazení přihlášeného uživatele |
npx wrangler logout | Odhlášení od Cloudflare |
npx wrangler dev | Lokální dev server (localhost:8787) |
npx wrangler deploy | Nasazení Workeru na Cloudflare |
npx wrangler deployments list | Výpis posledních deploymentů |
npx wrangler rollback | Rollback na poslední stabilní verzi |
npx wrangler rollback <id> | Rollback na konkrétní verzi |
npx wrangler secret put <NAZEV> | Uložení citlivého parametru |
npx wrangler secret list | Výpis názvů uložených secrets |
npx wrangler secret delete <NAZEV> | Smazání secretu |
npx wrangler tail | Živý log requestů (streaming) |
npx wrangler --version | Verze Wrangleru |
zone_name – musí odpovídat apex doméně./*.origin_conflict_existing_dns_recordcustom_domain = true s existujícím CNAME.[[routes]].assets.directory ukazuje na správnou složku a index.html je přímo v ní.public/.env.ASSETS.fetch(url.toString()).wrangler dev nefunguje (chyba autentizace)npx wrangler logout && npx wrangler login
public/assets.directory musí být "./public", nikoli "public"..wrangler/ a node_modules/ do .gitignore.| Dokument | URL |
|---|---|
| Static Assets – Get Started | developers.cloudflare.com/workers/static-assets/ |
| Wrangler – instalace | …/wrangler/install-and-update/ |
| Wrangler – konfigurace | …/wrangler/configuration/ |
| Wrangler – příkazy | …/wrangler/commands/ |
| Routes | …/routing/routes/ |
| Custom Domains | …/routing/custom-domains/ |
| Fetch handler (rewrite) | …/runtime-apis/handlers/fetch/ |
| Rollbacks | …/versions-and-deployments/rollbacks/ |
| Ceny a limity | …/platform/pricing/ |
| GitHub Actions pro Workers | …/ci-cd/external-cicd/github-actions/ |
Claude Code je interaktivní AI agent od Anthropic, který běží přímo v terminálu (nebo IDE). Rozumí celému repozitáři, čte a upravuje soubory, spouští příkazy a vykonává vícekrokové úlohy autonomně. Není to jen chatbot – vidí váš kód, git historii a filesystem.
Klíčový rozdíl od ChatGPT / Copilot: Claude Code má přístup k nástrojům (čtení souborů, spouštění příkazů, prohledávání kódu) a jedná autonomně. Sám prochází kódovou základnou a provádí změny.
| Prostředí | Popis |
|---|---|
| Terminál (CLI) | Základní režim – příkaz claude v jakémkoli adresáři |
| VS Code rozšíření | Integrovaný panel přímo v editoru |
| JetBrains plugin | Podpora IntelliJ, PyCharm, WebStorm… |
| claude.ai/code | Webová verze s přístupem k souborům |
| Desktop aplikace | Grafické rozhraní pro macOS, Windows a Linux bez terminálu |
| Model ID | Doporučení pro |
|---|---|
| claude-opus-5-5 | Architektura, složité plánování |
| claude-sonnet-5 | Implementace – výchozí volba |
| claude-haiku-4-5 | Rychlý boilerplate, jednoduché tasky |
# Doporučeno: nativní instalátor (macOS, Linux, WSL) – aktualizuje se sám
curl -fsSL https://claude.ai/install.sh | bash
# Windows PowerShell
irm https://claude.ai/install.ps1 | iex
# Alternativy: Homebrew, WinGet, npm (npm vyžaduje Node.js 22+)
brew install --cask claude-code
winget install Anthropic.ClaudeCode
npm install -g @anthropic-ai/claude-code
# Ověření
claude --version
# První spuštění – přihlášení přes prohlížeč
claude
# Nebo nastavení API klíče přímo
export ANTHROPIC_API_KEY="sk-ant-..."
API klíč: Nikdy necommitujte API klíč do repozitáře. Používejte proměnné prostředí nebo
.envsoubory v.gitignore.
Základní použití – spustíte claude v adresáři projektu a komunikujete v přirozeném jazyce. Claude vidí všechny soubory v pracovním adresáři.
# Spuštění v aktuálním projektu
cd muj-projekt
claude
# Jednorázový dotaz bez interaktivního režimu (-p = print)
claude -p "Vysvětli funkci parseConfig v src/config.ts"
# Pokračování v předchozí konverzaci
claude --resume
# Komprimace kontextu při dlouhých sezeních
# V interaktivním režimu zadejte:
/compact
Claude se před každou destruktivní akcí (zápis souboru, spuštění příkazu) zeptá na potvrzení. Toto chování lze upravit:
| Režim | Chování |
|---|---|
| Výchozí | Potvrzení před každou akcí mimo čtení |
| --dangerously-skip-permissions | Bez potvrzení – jen pro CI/CD nebo izolovaná prostředí |
Slash příkazy jsou zkratky pro časté operace. Zadávají se přímo v interaktivním režimu.
| Příkaz | Popis |
|---|---|
| /help | Nápověda ke všem příkazům |
| /clear | Vymaže kontext konverzace |
| /compact | Komprimuje dlouhou konverzaci – šetří kontext |
| /review | Code review aktuálních změn (deprecated – doporučeno jako vlastní příkaz) |
| /init | Inicializuje CLAUDE.md pro aktuální projekt |
| /cost | Zobrazí využití tokenů a odhadované náklady |
| /model | Přepne model (opus / sonnet / haiku) |
| /fast | Přepne do rychlého režimu (Opus s rychlejším výstupem) |
Slash příkazy lze rozšířit vlastními soubory v .claude/commands/. Každý .md soubor se stane dostupným jako /nazev-souboru. Soubor obsahuje prompt, který se spustí při zavolání příkazu.
.claude/
└── commands/
├── codereview.md → /codereview
├── deploy-check.md → /deploy-check
└── publish.md → /publish
<!-- .claude/commands/codereview.md -->
Proveď code review změněných souborů. Zaměř se na:
- Bezpečnostní problémy
- Výkonnostní antipatterns
- Chybějící ošetření chyb
Výstup: odrážkový seznam, max 10 bodů.
<!-- .claude/commands/publish.md -->
Commituj všechny změny a nasaď web na Cloudflare.
## Kroky
1. Spusť `git status` – zjisti, co se změnilo.
2. Spusť `git add -A`.
3. Z diffu (`git diff --cached`) sestav výstižnou českou commit zprávu a spusť `git commit -m "..."`.
4. Spusť `npx wrangler deploy` z kořene repozitáře.
5. Vypiš nasazenou URL.
Pokud není co commitovat (čistý working tree), přeskoč na krok 4.
Claude Code používá několik souborů pro konfiguraci chování, kontextu projektu a přístupu k souborům. Každý slouží jinému účelu.
| Soubor | Účel | Commitovat? |
|---|---|---|
| CLAUDE.md | Kontext a pravidla projektu – načítá se automaticky | ano |
| CLAUDE.local.md | Osobní poznámky, lokální overrides – nepublikuje se | ne (.gitignore) |
| ~/.claude/CLAUDE.md | Globální kontext – platí pro všechny projekty | – |
| ~/.claude/settings.json | Globální nastavení – oprávnění, hooks, model | – |
| .claude/settings.json | Projektové nastavení – oprávnění (včetně zákazu čtení citlivých souborů) a hooks pro celý tým | ano |
| .claude/settings.local.json | Lokální přepisy projektového nastavení | ne (.gitignore) |
| .claude/commands/ | Vlastní slash příkazy – každý .md soubor = jeden příkaz | ano |
| .mcp.json | MCP servery sdílené v projektu (scope project) | ano |
| ~/.claude.json | Osobní MCP servery (scope user a local) a stav aplikace | – |
Automaticky načítaný „briefing" – říká Claudovi, co je projekt zač, jaká jsou pravidla a jak má pracovat.
# Název projektu – Claude Context
## Scope (NON-NEGOTIABLE)
- Edituj POUZE soubory relevantní k úloze
- Neptej se zbytečně – jednej autonomně
## Pravidla
- Kód v angličtině, obsah/data v češtině
- Žádné spekulativní abstrakce
## Projekt
Krátký popis – co projekt dělá, jak se buildí, jak se nasazuje.
## Apps / Moduly
| Modul | Popis |
|-------|-------|
| api | REST backend, Node.js + Fastify |
Nedávejte do CLAUDE.md: Kódové vzory, architekturu, git historii – ty jsou v kódu samotném. CLAUDE.md je pro kontext a pravidla, ne pro dokumentaci.
Claude Code nemá soubor typu .gitignore pro skrytí souborů. Přístup se řídí pravidly oprávnění v settings.json: pravidlo deny s nástrojem Read Claudovi zakáže daný soubor číst. Pro celý tým patří do .claude/settings.json (commituje se), pro vás osobně do ~/.claude/settings.json.
{
"permissions": {
"deny": [
"Read(./.env)",
"Read(./.env.*)",
"Read(./secrets/**)"
]
}
}
Poznámka: Soubory nastavení jsou striktní JSON – komentář
//ani čárka za poslední položkou v nich být nesmí, jinak Claude Code soubor při startu nahlásí jako chybný. Co se skutečně načetlo, ukáže příkaz/status. Vyhledávání v Claude Code (postavené na ripgrepu) standardně vynechává soubory uvedené v.gitignore, takže velké vygenerované složky jakonode_modules/nebodist/stačí mít tam.
Každý .md soubor v .claude/commands/ se stane dostupným slash příkazem – viz sekci 4.2 pro příklady a strukturu souborů.
Hooks jsou shell příkazy, které se spouštějí automaticky v reakci na události Claude Code (před/po volání nástroje, při odeslání zprávy…). Konfigurují se v settings.json.
| Událost | Kdy se spustí |
|---|---|
| PreToolUse | Před každým voláním nástroje (čtení, zápis, bash…) |
| PostToolUse | Po dokončení nástroje |
| UserPromptSubmit | Při odeslání zprávy uživatelem |
| Stop | Při ukončení konverzace |
Soubor ~/.claude/settings.json (nebo projektový .claude/settings.json):
{
"hooks": {
"PostToolUse": [
{
"matcher": "Write|Edit",
"hooks": [
{
"type": "command",
"command": "npm run lint --silent"
}
]
}
]
}
}
Použití: Automatické spuštění linteru po každém zápisu souboru, notifikace, logování, formátování kódu…
MCP (Model Context Protocol) je otevřený standard pro připojení externích nástrojů a datových zdrojů k AI agentům. Claude Code podporuje MCP servery – přidají nové nástroje dostupné v konverzaci.
| Server | Přidá nástroje pro |
|---|---|
| GitHub | Správu issues, PR, repozitářů |
| Postgres / SQLite | Dotazy přímo na databázi |
| Slack | Čtení a odesílání zpráv |
| Filesystem | Přístup k souborům mimo pracovní adresář |
| Playwright | Ovládání prohlížeče, screenshoty |
MCP servery se nepřidávají do settings.json. Nejjednodušší je příkaz claude mcp add; volba --scope určuje, kam se konfigurace uloží: local (výchozí, jen vy a jen tento projekt) a user (vy ve všech projektech) do ~/.claude.json, project do souboru .mcp.json v kořeni repozitáře, který se commituje a sdílí s týmem.
# Vzdálený (HTTP) server – GitHub
claude mcp add --transport http github https://api.githubcopilot.com/mcp/ \
--header "Authorization: Bearer VAS_GITHUB_PAT"
# Lokální (stdio) server – příkaz za oddělovačem --
claude mcp add --transport stdio playwright -- npx -y @playwright/mcp@latest
# Sdílený server pro celý tým (zapíše se do .mcp.json)
claude mcp add --transport http --scope project docs https://example.com/mcp
# Výpis nakonfigurovaných serverů; stav připojení ukáže /mcp v relaci
claude mcp list
Soubor .mcp.json (projektový scope):
{
"mcpServers": {
"docs": {
"type": "http",
"url": "https://example.com/mcp"
}
}
}
Tokeny: Přístupový token do
.mcp.jsonnepište – soubor se commituje. Použijte volbu--headerpři přidání serveru v osobním scope nebo proměnnou prostředí.
src/auth.ts:42 oprav X"/compact u dlouhých sezení – ušetří kontext a zrychlí odpovědi--dangerously-skip-permissions na produkčních systémech| Úloha | Doporučený model |
|---|---|
| Architektura, plánování, složitý refaktoring | opus |
| Implementace, opravy bugů, přidání feature | sonnet |
| Boilerplate, jednoduché překlady, formátování | haiku |
| Zdroj | URL |
|---|---|
| Dokumentace Claude Code | code.claude.com/docs |
| Model Context Protocol | modelcontextprotocol.io |
| GitHub – claude-code | github.com/anthropics/claude-code |
| Anthropic API dokumentace | docs.anthropic.com/en/api |
| MCP servery (komunita) | github.com/modelcontextprotocol/servers |
Kontejnerizační platforma postav na Linux kernel namespaces + cgroups
Docker obaluje aplikaci a všechny její závislosti do izolované jednotky – kontejneru – která běží identicky na jakémkoli hostu s Docker daemonem. Eliminuje problém "na mém stroji to funguje" a přináší reprodukovatelné buildy, rychlé nasazení a efektivní využití zdrojů oproti VM.
VM virtualizuje celý hardware včetně Guest OS (GiB overhead). Kontejner sdílí kernel hostu – izolace přes namespaces, overhead jen MiB.
Namespaces – izolace PID, NET, MNT, UTS, IPC, USER
cgroups v2 – limity CPU, RAM, I/O, PIDs
OverlayFS – vrstveného filesystemu
Plná virtualizace (Hyper-V, VMware Workstation) vytvoří virtuální hardware – CPU, RAM, disk, síťovou kartu – a na něj se instaluje celý operační systém včetně vlastního jádra. VM „neví“, že je virtuální, a je od hostitele zcela izolovaná. Cena: každá VM nese kompletní OS (gigabajty místa, desítky sekund až minuty na start) a její disk je jeden velký soubor (.vhdx, .vmdk).
Kontejner vlastní jádro nemá. Běží izolovaně (vlastní souborový systém, síť, procesy), ale s hostitelem sdílí jádro. Image obsahuje jen aplikaci a její závislosti (desítky až stovky MB), start trvá sekundy. Analogie: VM je samostatný dům s vlastními rozvody, kontejner je byt v bytovém domě – vlastní zamčené dveře a interiér, ale sdílená infrastruktura.
Práce se proto liší: místo „vytvořím si VM a nainstaluji do ní aplikaci“ pracujete s kontejnerem jako jednotkou – rychle ho vytvoříte, smažete a znovu vytvoříte, a trvalá data držíte odděleně ve volumes.
Každý RUN / COPY instrukce v Dockerfile přidá novou read-only vrstvu. Kontejner přidá přes ně thin read-write vrstvu (Copy-on-Write). Sdílené vrstvy jsou na hostu uloženy pouze jednou – šetří disk i čas pull.
# Příklad vrstev image node:24-alpine Layer 0 (base): alpine 3.24 ← sdíleno všemi alpine images Layer 1: node 24 runtime Layer 2: npm dependencies (package.json) Layer 3: app source ─────────────────────────────────────────────── Container layer: R/W (dočasný, ztracen po rm)
Klíčové pojmy Docker ekosystému
| Termín | Definice | Analogie |
|---|---|---|
| Image | Neměnná, vrstevnatá šablona kontejneru. Vzniká buildem Dockerfile. Uložena v registry. | ISO / VM šablona |
| Container | Běžící instance image. Má vlastní PID, NET, filesystem namespace. Po docker rm zaniká. | Spuštěná VM |
| Dockerfile | Textový recept pro build image. Sekvence instrukcí (FROM, RUN, COPY…). | Kickstart / Packer template |
| Registry | Server pro ukládání a distribuci image. Docker Hub = výchozí veřejný. Harbor/ACR = privátní. | NuGet / npm registry |
| Tag | Label verze image. nginx:1.30-alpine = repo:tag. latest je jen konvence, ne "nejnovější stable". | Git tag |
| Volume | Perzistentní úložiště spravované Dockerem, nezávislé na životním cyklu kontejneru. | Datový disk VM |
| Bind mount | Přímé namapování adresáře hostu do kontejneru. Vhodné pro dev, ne pro prod. | SMB share mount |
| Network | Virtuální síť propojující kontejnery. Typy: bridge, overlay, host, macvlan, none. | vSwitch / VNet |
| Layer | Jedna přírůstková vrstva filesystemu v image. Sdílena mezi images (dedup). | Git commit / delta |
| Digest | SHA256 hash image manifestu. Imutable reference – vždy přesně určí verzi. | Git commit SHA |
| dockerd | Docker daemon – background service, přijímá API požadavky. | Windows Service |
| containerd | CNCF project, podkomponenta dockerd pro lifecycle kontejnerů. Také standalone (K8s). | Hypervisor pod VMM |
| runc | OCI-kompatibilní runtime – vytvoří namespace, cgroup, spustí proces. | Kernel VM entry |
| Compose | YAML definice multi-kontejnerové aplikace. docker compose up = celý stack. | ARM/Bicep template |
| Context | Nastavení CLI pro přepínání mezi Docker hosts (local / remote / Swarm). | kubectl context |
| Compose projekt | Pojmenovaná skupina kontejnerů, sítí a volumes vzniklá z jednoho Compose souboru (docker compose -p <jméno>). Jméno je prefixem názvů volumes a kontejnerů. | Resource group |
| Port mapping | Přesměrování portu hostu na port v kontejneru, zápis host:kontejner (9200:9200). | NAT / port forwarding |
| Colima | Open-source nástroj pro macOS a Linux, který spravuje lehkou Linux VM s Docker Engine a bez GUI. | Docker Desktop bez GUI |
| Lima | Nižší vrstva, na které Colima staví – obecný správce lehkých Linux VM na macOS. | Hyper-V Manager pro lehké VM |
| QEMU | Emulátor a hypervisor, ve kterém Colima ve výchozím nastavení VM spouští (alternativa: Apple Virtualization.framework, vz). | Hypervisor |
| virtiofs | Rychlé sdílení složek mezi macOS a VM; dostupné jen s typem VM vz. Další způsoby: sshfs, 9p. | SMB share |
# Plný formát: registry.example.com/namespace/repo:tag@sha256:abc123... # Příklady: nginx:1.30-alpine # Docker Hub, official mycompany/api:v2.1.0 # Docker Hub, org namespace harbor.corp.local/prod/app:latest # Private registry mcr.microsoft.com/dotnet/aspnet:10.0 # Microsoft Container Registry
Docker Engine (Linux) vs Docker Desktop (macOS/Win)
| Platforma | Produkt | Runtime | Poznámka |
|---|---|---|---|
| Linux (Ubuntu/Debian) | Docker Engine | nativní | Doporučeno pro servery/CI |
| macOS / Windows | Docker Desktop | VM (LinuxKit / WSL2) | Licence req. pro firmy >250 zaměst. |
| Linux (rootless) | Docker Engine rootless | nativní, user ns | Bez root – bezpečnější pro dev |
Doporučeno: Docker Desktop – obsahuje Docker Engine, CLI, Compose i GUI. Kontejnery běží přes WSL2 (odlehčené linuxové jádro), který je proto potřeba mít zapnutý.
# Spusťte PowerShell jako správce winget install --id Docker.DockerDesktop -e # Pokud WSL2 ještě není nainstalován: wsl --install # Po instalaci a restartu ověřte (v novém terminálu): docker --version docker run --rm hello-world
Doporučeno: Docker Desktop přes Homebrew. Podporuje Apple Silicon (M-čipy) i Intel; kontejnery běží v odlehčeném Linux VM.
# Nainstaluje Docker Desktop.app do /Applications brew install --cask docker # Spusťte Docker Desktop z Applications (poprvé povolte oprávnění), poté ověřte: docker --version docker run --rm hello-world
colima nebo podman – odlehčené runtime poskytující Docker-kompatibilní CLI bez GUI a bez licenčního omezení. Postup pro Colimu je v sekci Lab na macOS – Colima.
Docker Engine – nativní, bez VM, ideální pro servery a CI. Níže oficiální repozitář pro Ubuntu/Debian.
# 1. Přidání oficiálního repozitáře curl -fsSL https://download.docker.com/linux/ubuntu/gpg \ | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg echo "deb [arch=amd64 signed-by=/etc/apt/keyrings/docker.gpg] \ https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" \ | sudo tee /etc/apt/sources.list.d/docker.list # 2. Instalace sudo apt update && sudo apt install -y \ docker-ce docker-ce-cli containerd.io docker-compose-plugin # 3. Přidání uživatele do skupiny (aby nebylo nutné sudo) sudo usermod -aG docker $USER newgrp docker # 4. Ověření docker info docker run --rm hello-world
# Pull image z registry docker pull nginx:1.30-alpine # Spustit kontejner interaktivně docker run -it --rm ubuntu bash # Spustit jako daemon, mapovat port, pojmenovat docker run -d --name webserver \ -p 8080:80 \ -v /srv/html:/usr/share/nginx/html:ro \ nginx:1.30-alpine # Výpis běžících / všech kontejnerů docker ps docker ps -a # Logy, exec, stats docker logs -f webserver docker exec -it webserver sh docker stats # Stop / remove docker stop webserver docker rm webserver
latest) – jinak pull přepíše image při update a rozbije reprodukovatelnost.
Build pipeline, best practices, multi-stage
| Instrukce | Funkce | Nová vrstva? |
|---|---|---|
FROM | Base image (nebo scratch pro minimalismus) | ne (metadata) |
RUN | Spustí příkaz při buildu | ano |
COPY | Zkopíruje soubory z build contextu | ano |
ADD | Jako COPY + rozbaluje archivy + URL (preferovat COPY) | ano |
ENV | Nastaví env proměnnou (i pro runtime) | ne |
ARG | Build-time proměnná (není v runtime image) | ne |
EXPOSE | Dokumentuje port (nepublikuje ho!) | ne |
ENTRYPOINT | Hlavní proces kontejneru (preferovat exec form) | ne |
CMD | Výchozí argumenty pro ENTRYPOINT, nebo příkaz | ne |
USER | Nastaví uživatele pro RUN/CMD/ENTRYPOINT | ne |
WORKDIR | Pracovní adresář (vytvoří, pokud neexistuje) | ne |
VOLUME | Deklaruje mount point | ne |
HEALTHCHECK | Příkaz pro health probe | ne |
# ── Stage 1: Builder (velký image s toolchain) ────────────── FROM node:24-alpine AS builder WORKDIR /app COPY package*.json . RUN npm ci --omit=dev COPY . . RUN npm run build # ── Stage 2: Runtime (minimální image) ────────────────────── FROM node:24-alpine WORKDIR /app # Pouze dist + prod deps z builder stage COPY --from=builder /app/dist ./dist COPY --from=builder /app/node_modules ./node_modules # Bezpečnost: non-root user RUN addgroup -S appgroup && adduser -S appuser -G appgroup USER appuser EXPOSE 3000 ENTRYPOINT ["node", "dist/server.js"]
# Základní build docker build -t myapp:1.0 . # S build argumentem a konkrétním Dockerfile docker build -f Dockerfile.prod \ --build-arg APP_ENV=production \ -t registry.corp.cz/myapp:1.0 . # BuildKit (výchozí od Docker 23.x) – paralelní stages, cache mount docker buildx build --platform linux/amd64,linux/arm64 \ --push -t registry.corp.cz/myapp:1.0 . # Zobrazit vrstvy & velikosti docker history myapp:1.0 docker image inspect myapp:1.0
# Vždy vytvořit – omezí build context zasílaný daemonu
.git
node_modules
*.md
.env
dist
__tests__
Lifecycle, resource limits, health checks, logging
docker run -d \ --memory=512m \ # hard limit RAM --memory-swap=512m \ # swap=0 (disabled) --cpus="1.5" \ # max 1.5 CPU --pids-limit=100 \ # ochrana fork bomb --restart=unless-stopped \ # restart policy myapp:1.0
| Policy | Chování |
|---|---|
no | Výchozí – bez restartu |
always | Vždy restartuje (i po docker start daemonu) |
unless-stopped | Jako always, ale respektuje manuální stop |
on-failure[:N] | Jen při nenulové exit code, max N pokusů |
# V Dockerfile HEALTHCHECK --interval=30s --timeout=5s --retries=3 \ CMD wget -qO- http://localhost:3000/health || exit 1 # CLI override docker run --health-cmd='curl -f http://localhost/ || exit 1' \ --health-interval=30s nginx
| Driver | Destination | Použití |
|---|---|---|
json-file | Lokální JSON soubor | Výchozí; docker logs funguje |
journald | systemd journal | Linux servery, centrální log |
syslog | syslog daemon | Syslog infrastruktura |
fluentd | Fluentd collector | EFK stack |
awslogs | CloudWatch Logs | AWS deployment |
none | Žádný output | Debug / test |
# Limit velikosti JSON log souborů (daemon.json nebo per-container) docker run --log-driver=json-file \ --log-opt max-size=50m \ --log-opt max-file=3 \ myapp:1.0
Network drivers, DNS, port mapping
| Driver | Izolace | Použití |
|---|---|---|
bridge | NAT přes docker0 / custom bridge | Výchozí pro single-host. User-defined bridge = DNS resolution by name. |
host | Žádná – sdílí síť hostu | High-throughput, monitoring. Bez port mapping. |
overlay | VXLAN mezi hosty | Docker Swarm, multi-host cluster |
macvlan | Vlastní MAC adresa – kontejner jako fyzický host | Legacy apps, potřeba přímého L2 přístupu |
ipvlan | Sdílí MAC hostu, vlastní IP | Nízkolatentní, VLAN trunk |
none | Pouze loopback | Izolované zpracování, batch jobs |
# Výchozí bridge (docker0) NEMÁ embedded DNS – nepoužívat pro prod # Vytvořit vlastní síť: docker network create \ --driver bridge \ --subnet 172.20.0.0/24 \ --gateway 172.20.0.1 \ myapp-net # Kontejnery ve stejné network se vidí jménem: docker run -d --name db --network myapp-net postgres:18 docker run -d --name api --network myapp-net myapp:1.0 # api kontejner může pingovat "db" – DNS name = container name # Port publishing -p 8080:80 # host:container (all interfaces) -p 127.0.0.1:8080:80 # jen localhost (security!) -p 8080:80/udp # UDP
-p 8080:80 binduje na 0.0.0.0 – obchází iptables/UFW pravidla hostu. Vždy specifikovat 127.0.0.1: pro interní služby nebo použít reverse proxy.
Volumes, bind mounts, tmpfs – kdy co použít
| Typ | Umístění | Lifecycle | Výkon | Použití |
|---|---|---|---|---|
| Volume | /var/lib/docker/volumes/ | Nezávislý na kontejneru | Nejlepší (nativní) | DB data, shared data, prod |
| Bind mount | Libovolná cesta hostu | Závisí na hostu | Dobrý (OS cache) | Dev: live reload kódu |
| tmpfs | RAM hostu | Ztracen po stopu | Nejrychlejší | Citlivá data, cache, secrets |
# Vytvoření named volume docker volume create pgdata # Použití ve run – od PostgreSQL 18 se volume připojuje na /var/lib/postgresql, ne na …/data docker run -d \ -v pgdata:/var/lib/postgresql \ --name postgres \ postgres:18-alpine # Inspect, seznam, cleanup docker volume inspect pgdata docker volume ls docker volume prune # odstraní nepřipojené volumes! # Backup volume → tar docker run --rm \ -v pgdata:/data:ro \ -v $(pwd):/backup \ alpine tar czf /backup/pgdata-backup.tar.gz -C /data .
Pro vzdálené úložiště (NFS, S3, Azure Blob, vSAN) existují volume driver pluginy:
Výchozí. Podporuje NFS mount options přímo:
--opt type=nfs --opt o=addr=nfs.host,rw
rexray/s3fs (S3), Azure File driver, NetApp Trident, Portworx. Vhodné pro Swarm / on-prem clustery.
Docker Hub, privátní registry, Harbor, MCR, ACR
| Registry | Typ | Auth | Poznámka |
|---|---|---|---|
| Docker Hub | Public / private | PAT / OIDC | Rate limit: 100 pull/6h anon, 200 free user |
| GitHub Container Registry (ghcr.io) | Public / private | PAT | Integrovaný s GitHub Actions |
| Azure Container Registry (ACR) | Private | Entra ID / admin | Geo-replication, Tasks, Cosign |
| AWS ECR | Private | IAM | Per-region, token refresh 12h |
| Harbor | Self-hosted | LDAP/OIDC | RBAC, vulnerability scan (Trivy), proxy cache |
| Microsoft MCR | Public | anon | Všechny Microsoft images |
# Login (ukládá credential do ~/.docker/config.json nebo credential helper) docker login registry.corp.cz docker login -u USERNAME -p $(cat token.txt) ghcr.io # Tag local image pro push docker tag myapp:1.0 registry.corp.cz/prod/myapp:1.0 docker tag myapp:1.0 registry.corp.cz/prod/myapp:latest # Push docker push registry.corp.cz/prod/myapp:1.0 docker push registry.corp.cz/prod/myapp:latest # Pull explicitně (nebo implicitně při run) docker pull registry.corp.cz/prod/myapp:1.0 # Pull by digest (imutable, pro prod doporučeno) docker pull registry.corp.cz/prod/myapp@sha256:abc123...
Harbor je CNCF graduated projekt. Přidává nad distribution/registry: RBAC projekty, vulnerability scanning (Trivy), image signing (Cosign/Notary), proxy cache pro Docker Hub (eliminuje rate limit), retention policies a audit log. Doporučená volba pro enterprise on-prem.
# Sigstore Cosign – moderní alternativa k Docker Content Trust cosign sign --key cosign.key registry.corp.cz/prod/myapp:1.0 cosign verify --key cosign.pub registry.corp.cz/prod/myapp:1.0 # Docker Content Trust (legacy Notary v1) export DOCKER_CONTENT_TRUST=1 docker pull nginx:1.30-alpine # ověří signaturu
Docker daemon TLS, privátní registry s interní CA, Cosign
Výchozí socket je UNIX (/var/run/docker.sock). Při expozici TCP portu nutno TLS – jinak root přístup k hostu přes síť.
Docker odmítá push/pull na registry bez platného TLS (nebo explicitně nakonfigurovaného insecure). Interní CA musí být důvěryhodná.
Nginx / Traefik v kontejneru terminuje TLS. Certifikát do kontejneru via volume nebo secret.
Podpis image artefaktu pro supply chain security. Klíče nebo keyless (Sigstore/OIDC).
Nejčastější problém v enterprise: interní registry (Harbor, ACR on-prem) podepsáno interní CA – Docker daemon ji nezná a vrátí x509: certificate signed by unknown authority.
# Ubuntu / Debian sudo cp corp-root-ca.crt /usr/local/share/ca-certificates/ sudo update-ca-certificates sudo systemctl restart docker # RHEL / Rocky sudo cp corp-root-ca.crt /etc/pki/ca-trust/source/anchors/ sudo update-ca-trust extract sudo systemctl restart docker
# Docker hledá certy v /etc/docker/certs.d/{registry-host}/ sudo mkdir -p /etc/docker/certs.d/harbor.corp.cz # Zkopírovat CA certifikát sudo cp corp-root-ca.crt /etc/docker/certs.d/harbor.corp.cz/ca.crt # Pro mTLS (client cert auth): sudo cp client.cert /etc/docker/certs.d/harbor.corp.cz/ sudo cp client.key /etc/docker/certs.d/harbor.corp.cz/ # Soubory musí mít příponu .cert a .key # Restart NENÍ nutný pro certs.d – platí okamžitě
# Generování CA, server cert, client cert (ukázka OpenSSL) # Pro prod: použít AD CS / ACME / Vault PKI # /etc/docker/daemon.json { "hosts": ["unix:///var/run/docker.sock", "tcp://0.0.0.0:2376"], "tls": true, "tlsverify": true, "tlscacert": "/etc/docker/ca.pem", "tlscert": "/etc/docker/server-cert.pem", "tlskey": "/etc/docker/server-key.pem" } # Klientský přístup docker --tlsverify --tlscacert=ca.pem \ --tlscert=cert.pem --tlskey=key.pem \ -H docker.corp.cz:2376 ps
# Varianta 1: Docker Secret (Swarm) docker secret create tls_cert server.crt docker secret create tls_key server.key # Secret namountován jako /run/secrets/{name} # Varianta 2: Volume mount (Compose / standalone) -v /etc/ssl/corp:/certs:ro # Varianta 3: Certbot/ACME sidecar kontejner # Traefik / Caddy zvládnou ACME nativně # Nikdy: COPY cert do image – certy se mění, rebuild = antipattern
# Přidání interní CA do Alpine image RUN apk add --no-cache ca-certificates COPY corp-root-ca.crt /usr/local/share/ca-certificates/ RUN update-ca-certificates
Lehká Linux VM a Docker bez Docker Desktop, vhodné pro krátkodobé testovací stacky
Sekce této skupiny popisují testovací lab: jeden hostitel, jedna VM, Compose stacky, které se dají zálohovat jako soubory a kdykoli smazat. Jednoduchost je záměr – proto je v labu mnohé jinak než v produkci:
| Kritérium | Lab (tato skupina) | Produkce / sdílené prostředí |
|---|---|---|
| Počet uzlů | 1 (Mac + jedna VM) | více fyzických nebo virtuálních uzlů |
| Orchestrace | Docker Compose | Kubernetes / Swarm |
| Vysoká dostupnost | neřešena | replikace, failover |
| Zálohování | ruční nebo skriptované archivy | automatizované, s retencí a offsite kopií |
| Bezpečnost | zjednodušená (security často vypnutá) | TLS všude, autentizace, správa tajemství, segmentace sítě |
| Monitoring | ruční (docker logs, UI) | centrální monitoring a alerting |
| Data | krátkodobá, mazatelná | dlouhodobá, s SLA |
Jakmile lab začne používat více lidí nebo musí běžet nepřetržitě, je čas přejít na produkční přístup – viz Docker Compose, Hardening & Bezpečnost a pro NiFi Cluster & HA.
Kontejner sdílí jádro hostitele a izolaci zajišťují mechanismy linuxového jádra (namespaces, cgroups). macOS je nemá, takže každé řešení pro Mac spouští nejdřív jednu Linux VM a teprve v ní Docker Engine a všechny kontejnery. Příkaz docker na Macu jen posílá požadavky do této VM. Důsledek: data kontejnerů leží uvnitř disku VM, ne ve vašem macOS souborovém systému (viz Kde jsou data).
| Docker Desktop | Colima | |
|---|---|---|
| Licence | placená pro větší firmy | open-source (MIT) |
| Rozhraní | GUI + CLI | jen CLI |
| Více nezávislých VM | ne | ano (colima start -p <profil>) |
| Skriptovatelnost | omezená | navržená pro CLI |
Funkčně jde o stejnou architekturu, rozdíl je v tom, kdo VM spravuje. Pro lab je Colima jednodušší hlavně kvůli licenci a skriptování. Colima je postavená na Lima (správce lehkých VM); VM běží buď v QEMU (qemu, výchozí), nebo přes Apple Virtualization.framework (vz).
# správce VM + Docker CLI + Compose v2 jako plugin brew install colima docker docker-compose
Balíček docker-compose nainstaluje jen binárku. Aby Docker CLI rozeznalo docker compose (s mezerou), musí ji najít jako plugin. Homebrew k tomu doporučuje přidat do ~/.docker/config.json adresář s pluginy:
{
"cliPluginsExtraDirs": [
"/opt/homebrew/lib/docker/cli-plugins"
]
}
Cesta /opt/homebrew platí pro Apple Silicon; na Intel Macu je prefix /usr/local (zjistíte přes brew --prefix). Starší postup – symlink binárky do ~/.docker/cli-plugins/ – funguje dál.
docker compose version
docker compose -p …, když plugin nikdo nenašel: Docker CLI pak compose nezná jako podpříkaz a přepínač -p čte jako vlastní.
colima start --cpu 4 --memory 8 --disk 60 colima status docker context ls # aktivní kontext by měl být "colima" docker run --rm hello-world
První start stáhne image VM a chvíli trvá. Velikost VM si zvolte podle nástrojů, které chcete provozovat (orientační hodnoty, ověřte přes docker stats):
| Scénář | --cpu | --memory | --disk |
|---|---|---|---|
| jeden nástroj, malá data | 2 | 4 | 30 GB |
| Elastic + Kibana + NiFi současně | 4 | 8 | 60 GB |
| větší objemy, více stacků | 6+ | 12+ | 100 GB+ |
qemu a sdílením složek přes sshfs (u --vm-type vz je výchozí virtiofs). Typ VM a způsob sdílení nelze po vytvoření změnit – rozhodněte se před prvním startem. Disk je řídký (thin-provisioned): zabírá jen skutečně obsazené místo.
| Potřeba | Postup |
|---|---|
| Stav VM a spotřeba | colima status, colima list, docker system df |
| Změna CPU nebo RAM | colima stop, poté colima start --cpu 6 --memory 12 |
| Zvětšení disku | zadává se při dalším startu přes --disk; zmenšit nelze – jedině colima delete a nová VM |
| Aktualizace nástrojů | brew upgrade colima docker docker-compose, poté restart VM |
| Úklid v engine | docker system prune (smaže nepoužívané objekty; volumes jen s --volumes) |
| Kompletní reset | colima delete – smaže i všechny images a volumes; předem zálohujte (viz Stacky, záloha a obnova) |
Zaseknutou VM zkuste colima stop, případně colima stop --force, a znovu colima start.
Elasticsearch vyžaduje vm.max_map_count alespoň 262144. Pokud kontejner padá s chybou o „max virtual memory areas“, nastavte hodnotu ve VM:
colima ssh -- sudo sysctl -w vm.max_map_count=262144
Trvale: colima start --edit otevře YAML konfiguraci VM a v sekci provision lze přidat skript, který se provede při každém startu (proto musí být idempotentní). Režim system běží jako root:
provision:
- mode: system
script: sysctl -w vm.max_map_count=262144
Na Linuxu (například Fedora) žádná VM není: Docker Engine nebo Podman běží přímo na jádru hostitele. Odpadá tedy celá údržba VM z této sekce a named volumes jsou vidět jako adresáře pod /var/lib/docker/volumes/ (u Podmanu ~/.local/share/containers/ v rootless režimu).
| Docker Engine | Podman | |
|---|---|---|
| Architektura | démon dockerd běžící jako root | bez démona, kontejner je potomek volajícího procesu |
| Rootless | možný, není výchozí | výchozí |
| Compose | docker compose | podman compose nebo podman-compose, stejné YAML |
| Bind mount na SELinux | přípona :z / :Z | přípona :z / :Z |
Bez přípony :Z (například ~/labs/data:/data:Z) kontejner na systému s SELinux v režimu enforcing k bind mountu obvykle nemá přístup. U named volumes to řešit nemusíte.
Jedna složka = jeden Compose projekt; zálohovat lze celý projekt jako jeden archiv
Každý stack má vlastní adresář s docker-compose.yml a .env. Projekt vždy pojmenujte přes -p, aby názvy volumes a kontejnerů byly předvídatelné (<projekt>_<volume>, <projekt>-<služba>-1).
STACK_VERSION=9.5.4
services:
elasticsearch:
image: docker.elastic.co/elasticsearch/elasticsearch:${STACK_VERSION}
environment:
- discovery.type=single-node
- xpack.security.enabled=false
- ES_JAVA_OPTS=-Xms1g -Xmx1g
ports:
- "9200:9200"
volumes:
- esdata:/usr/share/elasticsearch/data
kibana:
image: docker.elastic.co/kibana/kibana:${STACK_VERSION}
depends_on:
- elasticsearch
environment:
- ELASTICSEARCH_HOSTS=http://elasticsearch:9200
ports:
- "5601:5601"
volumes:
esdata:
elastic, vygenerované heslo). xpack.security.enabled=false je záměrná zkratka pro lokální lab, aby stačilo curl localhost:9200. Nikdy ji nepřenášejte mimo lab.
cd ~/labs/elastic-9x docker compose -p elastic-9x up -d curl localhost:9200 # Kibana: http://localhost:5601
| Akce | Příkaz |
|---|---|
| Spustit | docker compose -p <projekt> up -d |
| Zastavit, data zůstávají | docker compose -p <projekt> stop |
| Odebrat kontejnery, data zůstávají | docker compose -p <projekt> down |
| Odebrat i data (nevratné) | docker compose -p <projekt> down -v |
| Přehled projektů | docker compose ls |
| Log projektu / jedné služby | docker compose -p <projekt> logs -f [služba] |
| Restart jedné služby | docker compose -p <projekt> restart <služba> |
Orientační hodnoty pro jednouzlový testovací režim; skutečnou spotřebu změřte přes docker stats.
| Nástroj | RAM | CPU | Růst dat |
|---|---|---|---|
| Elasticsearch (single-node) | heap 1–2 GB (ES_JAVA_OPTS), s režií 2–4 GB | 1–2 jádra | závisí na objemu indexovaných dat; při aktivním testování desítky MB až GB za den |
| Kibana | 0,5–1 GB | 0,5–1 jádro | zanedbatelný (konfigurace) |
| Apache NiFi | 1–2 GB (výchozí JVM heap) | 1–2 jádra | podle FlowFile a provenance repository; při vysokém průtoku rychle |
Velikost stažených images zjistíte příkazem docker images. Zálohy jsou .tar.gz archivy volumes: strukturovaná data (indexy, databáze) se gzipem zmenší zhruba 2–4×, již komprimovaná hůře. Na disku počítejte s rezervou aspoň 1× velikost aktuálních dat všech stacků na jednu generaci zálohy. Retenci skript neřeší – staré archivy mažte ručně.
Data leží ve named volumes, konfigurace v docker-compose.yml a .env. Záloha musí pokrýt obojí, jinak nejde stack plně obnovit. Jeden volume zálohuje jednoduchý příkaz ze sekce Úložiště & Volumes; skript níže to udělá pro všechny volumes projektu a přidá konfiguraci.
Princip: pomocný kontejner alpine připojí volume jen pro čtení, hostitelskou složku jako cíl a tar obsah zabalí. Díky --rm po sobě nic nezůstane, jen archiv. Volumes projektu skript najde podle štítku com.docker.compose.project, který Compose nastavuje sám.
#!/usr/bin/env bash
set -euo pipefail
PROJECT=${1:?použití: backup.sh <projekt>}
SRC_DIR="$HOME/labs/$PROJECT"
OUT_DIR="$HOME/labs/_backups"
STAMP=$(date +%Y%m%d-%H%M%S)
WORK="$OUT_DIR/${PROJECT}_${STAMP}"
mkdir -p "$WORK/config" "$WORK/volumes"
cp -R "$SRC_DIR"/. "$WORK/config"
echo "$PROJECT" > "$WORK/project.txt"
for VOL in $(docker volume ls --filter "label=com.docker.compose.project=$PROJECT" -q); do
docker run --rm \
-v "${VOL}:/data:ro" \
-v "$WORK/volumes:/backup" \
alpine tar czf "/backup/${VOL}.tar.gz" -C /data .
done
tar czf "$OUT_DIR/${PROJECT}_${STAMP}.tar.gz" -C "$OUT_DIR" "${PROJECT}_${STAMP}"
rm -rf "$WORK"
echo "Záloha hotová: $OUT_DIR/${PROJECT}_${STAMP}.tar.gz"
chmod +x ~/labs/backup.sh docker compose -p elastic-9x stop # za běhu by soubory databáze nemusely být konzistentní ~/labs/backup.sh elastic-9x docker compose -p elastic-9x start
.env. Se zálohou zacházejte jako s tajemstvím.
com.apple.quarantine a skript pak nejde spustit ani s chmod +x. Ověříte přes xattr -l <skript>, odstraníte přes xattr -d com.apple.quarantine <skript>. Atribut se vrací při každém dalším uložení v takovém editoru.
Skript obnoví archiv pod zadaným názvem projektu. Název projektu si archiv pamatuje v project.txt, takže skript umí odstranit původní prefix z názvů volumes a nahradit ho novým. Volumes vytváří se štítky Compose, aby je docker compose up převzal bez varování.
#!/usr/bin/env bash
set -euo pipefail
ARCHIVE=${1:?použití: restore.sh <archiv.tar.gz> <projekt>}
PROJECT=${2:?použití: restore.sh <archiv.tar.gz> <projekt>}
TARGET="$HOME/labs/$PROJECT"
TMP=$(mktemp -d)
tar xzf "$ARCHIVE" -C "$TMP"
BUNDLE=$(find "$TMP" -mindepth 1 -maxdepth 1 -type d | head -n 1)
OLD=$(cat "$BUNDLE/project.txt")
mkdir -p "$TARGET"
cp -R "$BUNDLE/config/." "$TARGET/"
for VOLFILE in "$BUNDLE"/volumes/*.tar.gz; do
FULL=$(basename "$VOLFILE" .tar.gz)
SHORT=${FULL#"${OLD}_"}
NEWVOL="${PROJECT}_${SHORT}"
docker volume create \
--label "com.docker.compose.project=$PROJECT" \
--label "com.docker.compose.volume=$SHORT" \
"$NEWVOL" >/dev/null
docker run --rm \
-v "${NEWVOL}:/data" \
-v "$BUNDLE/volumes:/backup:ro" \
alpine tar xzf "/backup/$(basename "$VOLFILE")" -C /data
done
rm -rf "$TMP"
echo "Obnoveno do $TARGET. Spuštění: docker compose -p $PROJECT -f $TARGET/docker-compose.yml up -d"
Klonování je vedlejší efekt obnovy: stejný archiv obnovte pod jiným názvem projektu a vznikne druhá nezávislá kopie včetně vlastních volumes. Klon ale zdědí namapované porty z docker-compose.yml – před spuštěním obou kopií najednou změňte levou stranu mapování (například "9201:9200"), jinak skončí chybou port is already allocated.
down -v).
Stacky zůstávají samostatné (vlastní start, zastavení, záloha), ale mohou sdílet jednu síť. Kontejnery se pak vidí přes název služby, například http://elasticsearch:9200.
docker network create labs-shared
Do docker-compose.yml obou stacků přidejte:
networks:
default:
name: labs-shared
external: true
Pozor na shodné názvy služeb ve více stacích na jedné síti – DNS pak vrací kontejnery obou. Podrobnosti o sítích jsou v sekci Síťování. Praktické použití: NiFi → Elasticsearch.
Jednorázově lze dva stacky spustit i jako jeden projekt bez úpravy YAML: docker compose -p combined -f a/docker-compose.yml -f b/docker-compose.yml up -d.
Přístup k datům kontejnerů a k disku VM – bez hledání v cizí struktuře
sudo ls /var/lib/docker/volumes/<volume>/_data.
| Situace | Postup |
|---|---|
| Kontejner běží, chcete se podívat dovnitř | docker exec -it <kontejner> /bin/bash (jméno zjistíte přes docker compose -p <projekt> ps) |
| Přenést soubor mezi Macem a kontejnerem | docker cp <kontejner>:<cesta> <cíl na Macu>, případně opačně |
| Kontejner neběží, ale volume existuje | pomocný kontejner: docker run --rm -it -v <volume>:/data alpine sh |
| Diagnostika samotné VM | colima ssh – shell na úrovni OS VM |
Pro práci s daty aplikace používejte první tři. Přímý pohled do /var/lib/docker/volumes/ přes colima ssh je vhodný spíš na diagnostiku (místo na disku, kernel parametry), interní struktura enginu se může měnit.
Chcete-li vidět data jako běžné soubory na Macu, nahraďte named volume bind mountem na složku v $HOME:
volumes:
- ~/labs/elastic-9x/data:/usr/share/elasticsearch/data
Colima připojuje domovský adresář do VM jako zapisovatelný, takže složka bude existovat i na Macu. Výměnou za to je I/O pomalejší než u named volume (data procházejí sdílením mezi macOS a VM) a správa mimo příkazy docker volume. Rychlost závisí na typu sdílení zvoleném při vytvoření VM (sshfs výchozí u qemu, virtiofs u vz). Pro datově náročné testy proto zůstaňte u named volumes.
permission denied, vraťte se k named volume.
Disk VM je jediný soubor uvnitř ~/.colima/_lima/colima/ (pro profil default; u jiných profilů se jmenuje podle profilu). Uvnitř jsou všechny images i volumes.
# nominální (virtuální) velikost – strop z --disk ls -lh ~/.colima/_lima/colima/diffdisk # skutečně obsazené místo na SSD du -sh ~/.colima/_lima/colima/diffdisk # pohled zevnitř VM a rozpad podle typu objektu colima ssh -- df -h /var/lib/docker docker system df
Disk je řídký soubor: ls -l a Finder ukazují nominální velikost, která se nemění, dokud disk nezvětšíte. Proto se může zdát, že soubor „neroste“, ačkoli do VM přibývají gigabajty. Skutečné číslo dá du.
docker system prune se uvolní místo uvnitř VM, ale řídký soubor na disku Macu nemusí zmenšit své reálné obsazení. Spolehlivé uvolnění je zazálohovat stacky, provést colima delete a VM vytvořit znovu. Cesta k souboru a chování se mohou lišit podle typu VM a verze Colimy; při pochybnostech si ověřte colima list a cestu vyhledejte přes find ~/.colima ~/.lima -name diffdisk 2>/dev/null.
Příznak → příčina → řešení pro lab na macOS s Colimou
| Příznak | Pravděpodobná příčina | Řešení |
|---|---|---|
port is already allocated při up -d | port na hostiteli už používá jiný proces nebo stack | změňte levou stranu mapování ("9201:9200") nebo konfliktní stack zastavte |
Elasticsearch padá s chybou o max virtual memory areas | vm.max_map_count ve VM je nižší než 262144 | viz Lab na macOS – Colima, část Kernel parametry |
unknown shorthand flag: 'p' in -p | Docker CLI nenašlo plugin compose | nastavte cliPluginsExtraDirs (nebo symlink) a ověřte docker compose version |
docker: command not found po instalaci | binárky Homebrew nejsou v PATH | otevřete nový terminál; zkontrolujte brew doctor a brew --prefix |
zsh: operation not permitted u skriptu i po chmod +x | soubor má atribut com.apple.quarantine (často po uložení v GUI editoru) | xattr -l <skript>, poté xattr -d com.apple.quarantine <skript>; opakujte po každém dalším uložení |
| Colima nereaguje, příkazy visí | zaseknutá VM | colima stop, případně colima stop --force, poté colima start; zvažte aktualizaci Colimy |
| Došlo místo v disku VM | nahromaděné images, volumes a build cache | docker system df, poté docker system prune (opatrně); případně zvětšit disk přes --disk |
| Pomalé čtení a zápis u bind mountu | sdílení složek mezi macOS a VM má režii | pro datově náročné testy použijte named volume; případně VM typu vz s virtiofs |
Velikost diffdisk v Finderu neroste, i když do VM přibývají data | řídký soubor ukazuje nominální velikost | skutečné obsazení ukáže du -sh, viz Kde jsou data |
| Obnovený stack hlásí, že volume nevytvořil Compose | volume vznikl bez štítků projektu | obnovte skriptem ze sekce Stacky, záloha a obnova, který štítky nastavuje |
Multi-container definice jako kód
# compose.yaml (nová konvence, starší: docker-compose.yml) name: myapp services: db: image: postgres:18-alpine environment: POSTGRES_DB: appdb POSTGRES_USER: app POSTGRES_PASSWORD_FILE: /run/secrets/db_password volumes: - pgdata:/var/lib/postgresql # PostgreSQL 18+: rodičovský adresář, ne …/data secrets: - db_password healthcheck: test: ["CMD-SHELL", "pg_isready -U app"] interval: 10s retries: 5 networks: - backend api: build: context: . dockerfile: Dockerfile.prod image: registry.corp.cz/prod/myapp:1.0 depends_on: db: condition: service_healthy environment: DB_HOST: db DB_PORT: 5432 deploy: resources: limits: cpus: '1' memory: 512M networks: - backend - frontend ports: - "127.0.0.1:3000:3000" proxy: image: traefik:v3 ports: - "80:80" - "443:443" volumes: - ./traefik.yaml:/etc/traefik/traefik.yaml:ro - /var/run/docker.sock:/var/run/docker.sock:ro - certs:/certs networks: - frontend volumes: pgdata: certs: networks: backend: internal: true # bez přístupu k internetu frontend: secrets: db_password: file: ./secrets/db_password.txt
docker compose up -d # start na pozadí docker compose up --build -d # rebuild images + start docker compose down # stop + rm containers + networks docker compose down -v # + smaže volumes! docker compose ps docker compose logs -f api docker compose exec api sh docker compose scale api=3 # scale (bez orchestrace = local only)
compose.yaml # base compose.override.yaml # auto-mergeováno při dev (live reload, debug ports) compose.prod.yaml # explicitní: docker compose -f compose.yaml -f compose.prod.yaml up
Attack surface, best practices, scanning
| Oblast | Opatření | Priorita |
|---|---|---|
| Runtime user | USER nonroot v Dockerfile; nikdy root v produkci | Kritická |
| Read-only rootfs | --read-only + tmpfs pro writable dirs | Kritická |
| No new privileges | --security-opt no-new-privileges:true | Kritická |
| Docker socket | Nikdy mountovat /var/run/docker.sock do prod kontejneru (= root hostu) | Kritická |
| Capabilities | --cap-drop ALL --cap-add NET_BIND_SERVICE (jen co je nutné) | Vysoká |
| Seccomp | Výchozí Docker profil blokuje 44 syscalls; custom pro striktní workloads | Vysoká |
| Image scanning | Trivy / Grype v CI pipeline, Harbor scanner, ACR Defender | Vysoká |
| Base image | Distroless / Alpine / scratch – minimální útočná plocha | Vysoká |
| Secrets | Docker secrets / env z Vault; nikdy v Dockerfile nebo ENV pro prod credentials | Vysoká |
| Resource limits | --memory --cpus --pids-limit vždy v prod | Střední |
| Network isolation | internal: true pro backend sítě, least-privilege port publishing | Střední |
| Content trust | Cosign / DCT pro verifikaci image integrity | Střední |
# /etc/docker/daemon.json { "icc": false, // zakáže inter-container comm na default bridge "no-new-privileges": true, "live-restore": true, // kontejnery přežijí restart daemonu "userland-proxy": false, // výkon: iptables místo userland proxy "log-driver": "json-file", "log-opts": { "max-size": "100m", "max-file": "3" } }
# Scan local image trivy image myapp:1.0 # Scan s threshold (exit 1 při HIGH/CRITICAL) trivy image --exit-code 1 --severity HIGH,CRITICAL myapp:1.0 # Scan Dockerfile (IaC check) trivy config Dockerfile # SBOM generování trivy image --format cyclonedx --output sbom.json myapp:1.0
# Instalace (jako běžný uživatel) dockerd-rootless-setuptool.sh install # Spuštění (user systemd) systemctl --user start docker export DOCKER_HOST=unix:///run/user/1000/docker.sock # Kontejnery nemohou bind-mountovat porty <1024 bez sysctl
Oficální dokumentace, standardy, nástroje
| Kategorie | Příkaz | Popis |
|---|---|---|
| Images | docker pull / push / build / tag / rmi | Lifecycle image |
| Images | docker images / image ls / image prune | Výpis a čištění |
| Containers | docker run / start / stop / rm / pause | Lifecycle |
| Containers | docker ps / logs / exec / inspect / stats / top | Monitoring |
| Containers | docker cp | Kopírování souborů |
| Network | docker network create / ls / inspect / rm | Síťová správa |
| Volume | docker volume create / ls / inspect / rm / prune | Volume správa |
| Registry | docker login / logout / search | Registry auth |
| System | docker system df / prune / info / version | Disk usage, cleanup |
| Build | docker buildx build --platform / --push | Multi-arch build |
| Context | docker context create / use / ls | Přepínání hostů |
# Agresivní cleanup (dev prostředí) docker system prune -af --volumes # Selektivní docker container prune # stopped containers docker image prune -a # untagged + unused images docker volume prune # unused volumes docker network prune # unused networks # Zjistit disk usage docker system df -v
| Standard / Projekt | URL |
|---|---|
| Docker docs (oficální) | https://docs.docker.com |
| OCI Image Spec | https://github.com/opencontainers/image-spec |
| OCI Runtime Spec (runc) | https://github.com/opencontainers/runtime-spec |
| CIS Docker Benchmark | https://www.cisecurity.org/benchmark/docker |
| NIST SP 800-190 (Container Security) | https://csrc.nist.gov/publications/detail/sp/800/190/final |
| Sigstore / Cosign | https://docs.sigstore.dev/cosign/overview |
| Harbor CNCF | https://goharbor.io/docs |
| Trivy (scanner) | https://trivy.dev/latest/docs |
| Docker Compose spec | https://compose-spec.io |
| containerd | https://containerd.io/docs |
| Colima (Docker na macOS bez Docker Desktop) | https://github.com/abiosoft/colima |
| Docker – záloha, obnova a migrace volumes | https://docs.docker.com/engine/storage/volumes/#back-up-restore-or-migrate-data-volumes |
| Elasticsearch v Dockeru (single-node) | https://www.elastic.co/docs/deploy-manage/deploy/self-managed/install-elasticsearch-docker-basic |
| Podman | https://docs.podman.io |
| Image | Velikost | Použití |
|---|---|---|
scratch | 0 MB | Go statically-linked binaries |
distroless/static | ~2 MB | Go / compiled apps, zero shell |
alpine:3.x | ~5 MB | Shell + musl libc, interaktivní debug |
debian:slim | ~75 MB | Glibc závislosti, Python/Node |
ubuntu:24.04 | ~80 MB | Komplexní aplikace, .deb závislosti |
node:24-alpine | ~50 MB | Node.js apps (multi-stage final) |
python:3.14-slim | ~130 MB | Python, slim = bez dev headers |
Dataflow platforma pro spolehlivý, škálovatelný přenos a transformaci dat
encrypt-config.sh a skriptovací jazyky Jython a ECMAScript v ExecuteScript. Dotčená místa jsou níže označena.Apache NiFi je vizuální dataflow nástroj původem z NSA (projekt Niagarafiles, open-source 2014). Řeší integraci heterogenních datových zdrojů – přijímá, transformuje, směruje a doručuje data bez nutnosti psát integrační kód. Klíčové vlastnosti:
Perzistentní fronta na disku (Write-Ahead Log). Data se neztratí při výpadku – každý FlowFile je sledován od vstupu po výstup.
Kompletní auditní stopa každého záznamu – kdy, kde, kým byl modifikován. Klíčová vlastnost pro compliance a debugging.
Automatické řízení toku – pokud downstream nestíhá, upstream se zpomalí. Zabrání memory exhaustion bez ztráty dat.
Drag-and-drop canvas v prohlížeči. Flows jsou verzovatelné přes NiFi Registry. Žádné restarty při změně flow.
| Repository | Co ukládá | Výchozí umístění | Poznámka |
|---|---|---|---|
| FlowFile Repository | Metadata FlowFiles (atributy, stav, pointer do Content Repo) | ./flowfile_repository | WAL (Write-Ahead Log), malý, rychlý. Ztráta = ztráta in-flight dat. |
| Content Repository | Fyzická data (obsah FlowFiles) | ./content_repository | Může být rozděleno na více disků (zvyšuje propustnost). Immutable bloky. |
| Provenance Repository | Auditní události každého FlowFile | ./provenance_repository | Může rapidně růst – nastavit retention. Lze použít Lucene-backed pro vyhledávání. |
| Nástroj | Model | Silná stránka | Omezení |
|---|---|---|---|
| Apache NiFi | Push/Pull, visual flow | Provenance, guaranteed delivery, 300+ processors | Latence (batch-oriented), komplexní cluster setup |
| Apache Kafka | Log-based messaging | Extrémní throughput, replay | Není ETL – potřebuje Kafka Connect/Streams |
| Apache Camel | Code-first EIP | Flexibilita, lightweight | Žádné GUI, žádný provenance |
| MuleSoft / Boomi | iPaaS | Enterprise connectors, SLA | Licence, vendor lock-in |
| Logstash | Log pipeline | ELK integrace | Primárně pro logy, omezené routing |
Klíčové pojmy NiFi ekosystému
| Termín | Definice | Analogie |
|---|---|---|
| FlowFile | Základní datová jednotka v NiFi. Obsahuje content (payload) a attributes (metadata jako key-value páry). | Zpráva / paket / řádek |
| Processor | Komponenta provádějící konkrétní akci s FlowFiles – čtení, zápis, transformace, routing, volání API. Přes 300 built-in. | Funkce / mikroslužba |
| Connection | Fronta FlowFiles mezi dvěma procesory. Nese relationship name (success, failure, …). Má back-pressure nastavení. | Message queue / pipe |
| Relationship | Výsledek zpracování procesoru (success, failure, retry, matched, unmatched…). Processor může mít 1–N relationships. | Exit code / podmínka |
| Process Group | Logické seskupení processorů a connections. Lze vnořovat – hierarchická organizace flow. Verzovatelnév registru. | Namespace / modul |
| Controller Service | Sdílená konfigurace dostupná processorům – DB connection pool, SSL kontext, schema registry. Lifecycle nezávislý na processorech. | Dependency injection / singleton |
| Reporting Task | Periodicky běžící úloha reportující metriky (do Prometheus, InfluxDB, Elasticsearch…). | Scheduled task / exportér |
| NiFi Registry | Verzovací systém pro NiFi flows (Process Groups). Git-backed nebo filesystem backend. CI/CD pro data pipelines. | Git repo pro kód |
| Data Provenance | Kompletní auditní stopa – kde byl FlowFile vytvořen, modifikován, klonován, odeslán. Vyhledatelná v UI. | Audit log / blockchain |
| Back Pressure | Mechanismus zastavení upstream processoru pokud connection překročí limit (počet objectů nebo velikost dat). | TCP flow control |
| Bulletin | Diagnostická zpráva procesoru (warning/error). Zobrazena v UI, historicky uložena. | Application log event |
| Expression Language | Mini-jazyk pro dynamické hodnoty v property hodnotách: ${attribute:toUpper()}. Přístup k atributům a funkcím. | Jinja2 / EL template |
| Template | Export/import části flow jako XML. V NiFi 2.0 odstraněno – nahrazeno verzovanými flow (JSON) v NiFi Registry nebo v registry klientovi napojeném na Git. | ARM template (legacy) |
| Funnel | Vizuální spojovací bod – slučuje více connections do jedné. Žádná logika, pouze routování v canvasu. | Merge junction |
| Port (Input/Output) | Vstupní nebo výstupní bod Process Group – propojuje vnější flow s vnitřkem grupy. | Interface / API endpoint |
| Cluster Coordinator | Role v NiFi clusteru – koordinuje změny flow, health heartbeaty. Volena přes ZooKeeper. | Primary node / leader |
| Primary Node | Speciální role v clusteru – procesory označené "Primary Node Only" běží jen zde (deduplikace zdrojů). | Active node v HA páru |
Orientace v rozhraní, navigace, klávesové zkratky
Pracovní plocha pro stavbu flow. Nekonečný plán – zoom kolečkem, pan táhnutím. Shift+klik = vícenásobný výběr.
Přehled všech processorů, connections, remote process groups v celém clusteru. Filtrování, řazení, bulk akce.
Vyhledávání v auditní stopě FlowFiles. Filtr dle FlowFile UUID, atributu, procesoru, časového rozsahu.
Centrální výpis varování a chyb ze všech processorů. Nenahrazuje logy, ale rychlý přehled problémů.
Správa Controller Services a Reporting Tasks na úrovni celého NiFi instance (root scope).
Nastavení, flow konfigurace, cluster info, uživatelé a přístupová práva (pokud Ranger/vlastní auth).
| Stav / Symbol | Popis |
|---|---|
| ▶ Running | Processor aktivně zpracovává nebo čeká na trigger (timer/event) |
| ⏸ Stopped | Processor zastaven – FlowFiles se hromadí ve vstupní queue |
| ⚠ Invalid | Chybí povinná property nebo Controller Service není enabled |
| ⏳ Validating | Přechodný stav při startu nebo po změně konfigurace |
| 🔴 Bulletin | Červená ikona v rohu = nedávná chyba. Hover = detail. Zmizí po timeout. |
| Záložka | Obsah |
|---|---|
| Settings | Název, scheduling strategy (Timer / CRON / Event), concurrent tasks, run duration, penalty duration, yield duration |
| Scheduling | Run schedule (interval nebo CRON výraz), execution node (all / primary) |
| Properties | Specifické vlastnosti procesoru. Podporují Expression Language. Sensitive values jsou šifrovány. |
| Relationships | Zaškrtnutí "Auto-terminate" = FlowFile se zahazuje (nutno ošetřit všechny relationships) |
| Comments | Poznámky – zobrazeny jako tooltip v canvasu |
| Zkratka | Akce |
|---|---|
Ctrl + A | Vybrat vše |
Ctrl + C / V | Kopírovat / vložit výběr |
Del / Backspace | Smazat výběr |
Ctrl + Z | Undo (omezená hloubka) |
Shift + click | Přidat do výběru |
Ctrl + scroll | Zoom |
Ctrl + Shift + F | Find / Filter processorů |
R | Refresh statistik (bez reload stránky) |
Jednouzlová instance pro učení a testování – jeden soubor, jeden příkaz
docker compose s mezerou). Na macOS bez Docker Desktop postup pro Colimu popisuje sekce Instalace & First steps.Vytvořte adresář, například ~/labs/nifi-2x, a v něm dva soubory. Verze i přihlašovací údaje jsou v .env, aby šla verze měnit bez zásahu do YAML.
NIFI_VERSION=2.12.0
NIFI_USER=admin
NIFI_PASS=nahradte-min-12-znaku
services:
nifi:
image: apache/nifi:${NIFI_VERSION}
environment:
- SINGLE_USER_CREDENTIALS_USERNAME=${NIFI_USER}
- SINGLE_USER_CREDENTIALS_PASSWORD=${NIFI_PASS}
ports:
- "8443:8443"
volumes:
- nifi_content:/opt/nifi/nifi-current/content_repository
- nifi_database:/opt/nifi/nifi-current/database_repository
- nifi_flowfile:/opt/nifi/nifi-current/flowfile_repository
- nifi_provenance:/opt/nifi/nifi-current/provenance_repository
- nifi_state:/opt/nifi/nifi-current/state
- nifi_conf:/opt/nifi/nifi-current/conf
volumes:
nifi_content:
nifi_database:
nifi_flowfile:
nifi_provenance:
nifi_state:
nifi_conf:
docker logs <kontejner> | grep Generated. Soubor .env nevkládejte do gitu.
cd ~/labs/nifi-2x docker compose -p nifi-2x up -d # start trvá zhruba minutu – sledujte log, dokud se neobjeví "Started Application" docker compose -p nifi-2x logs -f
Rozhraní je na https://localhost:8443/nifi. Prohlížeč ohlásí neplatný certifikát (NiFi si při prvním startu vygeneruje vlastní) – v testovacím prostředí potvrďte výjimku. Přihlaste se údaji z .env.
-p nifi-2x pojmenuje projekt. Bez něj se název odvodí od adresáře a názvy kontejnerů a volumes se mohou lišit od příkladů v dalších sekcích.
"9443:8443"), NiFi odmítne požadavek s neznámou hlavičkou Host. Doplňte proměnnou NIFI_WEB_PROXY_HOST=localhost:9443 a případně NIFI_WEB_HTTPS_PORT. Stejné pravidlo platí pro přístup přes jiný hostname nebo reverse proxy.
| Volume | Obsah | Když ho smažete |
|---|---|---|
nifi_conf | konfigurace a definice flow (flow.json.gz) | zmizí všechny vaše flow a vrátí se výchozí konfigurace |
nifi_flowfile | FlowFile repository – stav fronty (Write-Ahead Log) | ztratíte data, která čekala ve frontách |
nifi_content | Content repository – vlastní obsah FlowFiles | totéž; roste podle objemu zpracovaných dat |
nifi_provenance | historie pohybu dat | ztratíte auditní stopu, flow zůstane |
nifi_database, nifi_state | interní databáze a stav processorů | processory začnou od začátku (například „co jsem už stáhl“) |
Repozitáře jsou stejné, jaké popisuje sekce Úvod & Architektura. Obecné zásady pro volumes, zálohy a přístup k datům jsou v Dockeru, sekce Úložiště & Volumes.
nifi_conf nese i konfiguraci ze staré verze. Při změně NIFI_VERSION proto počítejte s tím, že nová verze poběží nad starým nifi.properties. Pro testovací účely je nejjednodušší flow exportovat (pravé tlačítko na Process Group → Download flow definition), docker compose -p nifi-2x down -v a začít s čistým stavem.
| Akce | Příkaz | Data |
|---|---|---|
| Zastavit | docker compose -p nifi-2x stop | zůstávají |
| Znovu spustit | docker compose -p nifi-2x up -d | zůstávají |
| Odebrat kontejner | docker compose -p nifi-2x down | zůstávají ve volumes |
| Odebrat i data | docker compose -p nifi-2x down -v | nevratně smazána |
GenerateFlowFile → UpdateAttribute → PutFile a pohled do provenance
Cíl: vytvořit tři processory, spustit je a v provenance dohledat, co se s jedním FlowFile stalo. Pojmy vysvětluje sekce FlowFile & Atributy a Processors.
GenerateFlowFile. V konfiguraci na záložce Properties nastavte Custom Text na libovolný text a na záložce Scheduling Run Schedule na 10 sec. Výchozí hodnota 0 sec by generovala FlowFiles bez přestávky.lab.zdroj s hodnotou jz-git.Directory na /tmp/lab-out. Na záložce Relationships zaškrtněte u success i failure Terminate. Processor nemá kam dál poslat výsledek a bez toho zůstane neplatný.success) a UpdateAttribute → PutFile (success).# jméno kontejneru zjistíte přes: docker compose -p nifi-2x ps docker exec nifi-2x-nifi-1 ls -l /tmp/lab-out
Ve výpisu se každých 10 sekund objeví nový soubor. Soubor je uvnitř kontejneru, ne na hostiteli – zapisovat přímo do složky na disku by vyžadovalo bind mount (viz Úložiště & Volumes).
V menu vpravo nahoře zvolte Data Provenance, případně pravým tlačítkem na PutFile View data provenance. U libovolného záznamu otevřete detail (ikona i):
CREATE, ATTRIBUTES_MODIFIED, SEND), čas a processor,lab.zdroj = jz-git,docker compose -p nifi-2x down -v.
Dva samostatné stacky na sdílené síti a první zápis do indexu
Předpoklad: běží stack NiFi podle sekce Zprovoznění v kontejneru i stack Elasticsearch podle sekce Stacky, záloha a obnova a oba jsou připojeny ke sdílené síti labs-shared (postup je tamtéž v části Propojení více stacků). Po změně YAML stack znovu vytvořte příkazem docker compose -p <projekt> up -d.
ElasticSearchClientServiceImpl a nastavte HTTP Hosts na http://elasticsearch:9200. Adresa používá název služby z Compose, ne localhost – z pohledu kontejneru NiFi by localhost byl on sám. Službu povolte (Enable).Custom Text v GenerateFlowFile nastavte na platný JSON, například {"zprava": "ahoj z NiFi"}.PutElasticsearchJson, v Client Service vyberte službu z kroku 1 a Index nastavte na lab-test. Relationships success, failure i errors ukončete (Terminate) nebo je zapojte dál.curl "localhost:9200/lab-test/_search?pretty"
Výsledek obsahuje dokumenty s vaším JSON. Kdyby index chyběl, hledejte příčinu v Bulletin Board NiFi a ve stavu failure u processoru; nejčastější je nedosažitelný hostitel (stack není na labs-shared) nebo služba, která zůstala v neplatném stavu.
xpack.security (viz lab stack). Se zapnutým zabezpečením by služba potřebovala HTTPS, přihlašovací údaje a důvěryhodný certifikát – to je téma sekce Bezpečnost & TLS.
Katalog nejdůležitějších vestavěných procesorů podle kategorie
Moderní pattern pro příjem souborů ze vzdálených zdrojů (SFTP, S3, HDFS, Azure) – nahrazuje starší GetXxx procesory:
ListXxx vytvoří FlowFile pro každý nalezený objekt (s atributy jako path, filename, size). FetchXxx pak stáhne obsah. Výhoda: List běží na Primary Node, Fetch se paralelizuje na celý cluster.
| Strategy | Trigger | Použití |
|---|---|---|
| Timer Driven | Interval (0 sec = co nejrychleji) | Výchozí. Polling, continuous processing. |
| CRON Driven | CRON výraz (0 0 * * * ?) | Přesné plánování, batch v konkrétní čas. |
| Event Driven | Příchod FlowFile do vstupní queue | Reaktivní – nespotřebovává thread pokud není data. Ne všechny procesory podporují. |
Datová jednotka NiFi – content + metadata
Binární data uložená v Content Repository. FlowFile je na ně jen pointer – samotná data se nekopírují při klonování. Copy-on-Write při modifikaci.
Map<String, String> – klíč-hodnota páry. Ukládány v FlowFile Repository (rychlý přístup). Procesory čtou/píší atributy bez dotyku content.
| Atribut | Popis | Příklad |
|---|---|---|
uuid | Unikátní identifikátor FlowFile (immutable) | 550e8400-e29b-41d4-a716-446655440000 |
filename | Logický název souboru (lze přepsat) | orders_2024.csv |
path | Logická cesta (nastavena GetFile/ListFile) | /data/input/ |
entryDate | Čas vstupu do flow (epoch millis) | 1711900800000 |
lineageStartDate | Čas vzniku rodičovského FlowFile | – |
fileSize | Velikost content v bytech | 4096 |
mime.type | MIME typ (nastaví IdentifyMimeType) | application/json |
# UpdateAttribute – nejpoužívanější processor pro manipulaci atributů # Přidání / přepis atributu: destination = /archive/${now():format('yyyy/MM/dd')}/${filename} record.count = ${fragment.count} env = production # Podmíněná logika – Advanced tab (rules engine): # Condition: ${fileSize:gt(1000000)} # Action: size.category = large # Smazání atributu: # Přepsat na prázdno nebo použít "Delete Attributes" property # Delete Attributes Expression: ^temp\..*$ (regex)
| Operace | Content zkopírován? | Procesory |
|---|---|---|
| Clone / Fork | Ne (pointer) | SplitJSON, MergeContent, RouteOnAttribute (fanout) |
| Modify content | Ano (CoW) | ReplaceText, TransformXml, ExecuteScript |
| Modify attributes only | Ne | UpdateAttribute, AttributesToJSON (attr mode) |
| Merge | Nová kopie | MergeContent, MergeRecord |
Fronty, back pressure, prioritizace, podmíněné směrování
| Property | Výchozí | Popis |
|---|---|---|
| Name | (relationship) | Volitelný label v canvasu |
| FlowFile Expiration | 0 sec (nikdy) | Automaticky zahodit FlowFile starší než X – prevence zahlcení |
| Back Pressure Object Threshold | 10 000 | Počet FlowFiles, po jehož dosažení upstream processor přestane spouštět |
| Back Pressure Data Size Threshold | 1 GB | Celková velikost dat v queue – alternativní trigger back pressure |
| Load Balance Strategy | Do Not Load Balance | V clusteru: Round Robin / Single Node / Attribute / Partition by Attribute |
| Prioritizers | FIFO | Pořadí zpracování: FirstIn, NewestFlowFile, OldestFlowFile, PriorityAttribute |
Queue pod 60 % obou thresholdů. Normální provoz.
Queue přes 60 %. Varování – sledujte trend.
Back pressure aktivní. Upstream processor se nespustí.
# Property = název relationship, hodnota = EL podmínka is-json ${mime.type:equals('application/json')} is-large ${fileSize:gt(10485760)} # > 10 MB from-prod ${env:equals('production')} # Routing Strategy: # Route to Property Name – FlowFile jde do PRVNÍHO matched # Route to 'matched' / 'unmatched' – binární boolean split
# Regex matching proti obsahu (content) FlowFile has-error (?s).*"status"\s*:\s*"error".* has-warning (?s).*"level"\s*:\s*"WARN".* # Match Requirement: Content Must Match Exactly / Contain Match
LogAttribute nebo PutFile na failure path v produkci.Sdílené zdroje a konfigurace – connection pooly, SSL, schémata
Procesory nesmí udržovat vlastní long-lived připojení – to by vedlo k N×M problému (každý procesor × každý cíl). Controller Services poskytují sdílené, lifecycle-managed instance – DB connection pool, SSL context, schema registry – které jsou konfigurovány jednou a referencovány z processorů.
| Service | Účel | Použití |
|---|---|---|
| DBCPConnectionPool | JDBC connection pool (HikariCP) | ExecuteSQL, QueryDatabaseTable, PutDatabaseRecord |
| StandardSSLContextService | TLS/SSL kontext (keystore, truststore) | InvokeHTTP, PublishKafka, GetSFTP… |
| JsonTreeReader / JsonRecordSetWriter | Čtení/zápis JSON jako Record | ConvertRecord, MergeRecord, ValidateRecord |
| CSVReader / CSVRecordSetWriter | Čtení/zápis CSV | ConvertRecord, PutDatabaseRecord |
| AvroReader / AvroRecordSetWriter | Apache Avro | Kafka Avro pipelines |
| SchemaRegistry (Confluent / NiFi built-in) | Schema lookup pro Record procesory | Avro pipelines, schema evolution |
| HortonworksSchemaRegistry | Confluent / HWX Schema Registry klient | Kafka + Avro |
| StandardHttpContextMap | HTTP session stav pro HandleHttpRequest/Response | NiFi jako HTTP server |
| AWSCredentialsProviderControllerService | AWS auth (keys, IAM role, STS) | S3, SQS, DynamoDB procesory |
| AzureStorageCredentialsService | Azure auth | Azure Blob, ADLS, Event Hub procesory |
| DistributedMapCacheServer/Client | In-memory distributed cache | DetectDuplicate, Wait/Notify pattern |
Service konfigurovaná uvnitř Process Group je viditelná jen processorům ve stejné nebo vnořené skupině. Výchozí chování.
Service přidaná přes Controller Settings (hamburger menu) je dostupná všem processorům v celé instanci.
# Příklad konfigurace pro PostgreSQL: Database Connection URL: jdbc:postgresql://db.corp.cz:5432/appdb Database Driver Class: org.postgresql.Driver Database Driver Location: /opt/nifi/drivers/postgresql-42.7.12.jar Database User: nifi_user Password: {sensitive – použít NiFi sensitive props} Max Total Connections: 10 Max Wait Time: 500 millis Validation Query: SELECT 1 # Ovladače (JDBC JAR) je nutno dodat ručně – NiFi je neobsahuje z licenčních důvodů # Umístit do /opt/nifi/lib/drivers/ nebo nakonfigurovat cestu
Moderní pattern – místo práce s raw textem / JSON jako celkem, Record API parsuje data do strukturovaných řádků a umožňuje schema-aware transformace s výrazně vyšším výkonem:
Dynamické hodnoty v property polích – přístup k atributům, funkcím, systémovým proměnným
# Základní přístup k atributu: ${filename} ${mime.type} ${uuid} # Funkce (chaining): ${filename:toUpper()} ${filename:substring(0, 8):append('.processed')} ${fileSize:gt(1048576):ifElse('large', 'small')} # Systémové proměnné: ${now()} # aktuální čas (epoch ms) ${now():format('yyyy-MM-dd')} # formátovaný datum ${hostname()} # hostname NiFi node ${ip()} # IP NiFi node ${nextInt()} # auto-increment counter ${UUID()} # nový UUID # Environment / System properties (z nifi.properties nebo OS): ${ENV_VAR_NAME} ${nifi.home} # Podmíněné výrazy: ${attr:isNull():ifElse('default', ${attr})} ${status:equals('200'):and(${size:gt(0)})}
| Kategorie | Funkce | Příklad |
|---|---|---|
| String | toUpper() / toLower() | ${env:toUpper()} |
trim() | ${filename:trim()} | |
replace(search, replace) | ${path:replace('/', '_')} | |
substring(start, end) | ${filename:substring(0,8)} | |
| Boolean | equals(value) | ${mime.type:equals('application/json')} |
startsWith() / endsWith() | ${filename:endsWith('.csv')} | |
matches(regex) | ${filename:matches('order_.*\.csv')} | |
| Numeric | gt() / lt() / ge() / le() | ${fileSize:gt(1048576)} |
plus() / minus() / multiply() | ${retries:plus(1)} | |
toNumber() | ${count:toNumber():plus(1)} | |
| Date | now():format(pattern) | ${now():format('yyyy/MM/dd')} |
toDate(pattern) | ${date_str:toDate('yyyy-MM-dd')} | |
format(pattern) | ${entryDate:toNumber():toDate('ms'):format('HH:mm:ss')} | |
| Null / Default | isNull() / isBlank() | ${attr:isNull()} |
ifElse(true, false) | ${isNull:ifElse('N/A', ${attr})} |
Zero-master cluster, ZooKeeper koordinace, load balancing flows
| Role | Počet | Funkce |
|---|---|---|
| Cluster Coordinator | 1 (elected) | Koordinuje změny flow (deploy, start/stop processorů). Všechny UI změny jdou přes něj – ostatní nody synchronizuje. Volba přes ZooKeeper. |
| Primary Node | 1 (elected) | Procesory s "Execution = Primary Node" běží pouze zde. Zamezuje duplicitnímu čtení ze zdrojů (ListFile, ListSFTP, QueryDatabaseTable). |
| Standard Node | N-2 | Zpracovávají FlowFiles přijaté load balancerem nebo distribuované přes Connection load balancing. |
| Strategie | Chování | Použití |
|---|---|---|
| Do Not Load Balance | FlowFile zůstane na původním nodu | Výchozí – stateless processing |
| Round Robin | FlowFiles střídavě distribuovány mezi nody | Paralelizace zpracování (Fetch, transformace) |
| Single Node | Všechny FlowFiles jdou na jeden node | Operace vyžadující lokální stav |
| Partition by Attribute | Stejný atribut → vždy stejný node | Ordering, session affinity |
# Zapnutí cluster módu nifi.cluster.is.node=true nifi.cluster.node.address=nifi-node1.corp.cz nifi.cluster.node.protocol.port=11443 # ZooKeeper nifi.zookeeper.connect.string=zk1:2181,zk2:2181,zk3:2181 nifi.zookeeper.root.node=/nifi # Load balancing komunikace mezi nody nifi.cluster.load.balance.host=nifi-node1.corp.cz nifi.cluster.load.balance.port=6342 # Site-to-Site (příjem dat z jiného NiFi) nifi.remote.input.host=nifi-node1.corp.cz nifi.remote.input.secure=true nifi.remote.input.socket.port=10443
TLS povinné, autentizace uživatelů, autorizace, sensitive properties
NiFi v produkci vždy běží na HTTPS – bez TLS jsou zakázány přihlašování uživatelů a internode komunikace. Keystore a truststore (JKS nebo PKCS12) jsou konfigurovány v nifi.properties.
# nifi.properties – TLS konfigurace nifi.web.https.host=nifi.corp.cz nifi.web.https.port=8443 nifi.web.http.port= # prázdné = HTTP zakázáno nifi.security.keystore=./conf/keystore.p12 nifi.security.keystoreType=PKCS12 nifi.security.keystorePasswd={encrypted} nifi.security.keyPasswd={encrypted} nifi.security.truststore=./conf/truststore.p12 nifi.security.truststoreType=PKCS12 nifi.security.truststorePasswd={encrypted} # Šifrování hodnot v nifi.properties (bootstrap.conf klíč) # NiFi 1.x: nástroj ./bin/encrypt-config.sh; NiFi 2.x ho nemá a hodnoty šifruje samo při startu
| Metoda | Popis | Vhodnost |
|---|---|---|
| Klientský certifikát (mTLS) | Uživatel se přihlásí certifikátem v prohlížeči (CN = identita). Nejsilnější metoda. | Interní enterprise |
| LDAP / Active Directory | Username + password ověřen přes LDAP bind. Skupiny mapovány na NiFi role. | Korporátní prostředí |
| OIDC (OpenID Connect) | SSO přes Keycloak, Azure AD, Okta. Token exchange, redirect flow. | Moderní enterprise, cloud |
| Kerberos (SPNEGO) | Hadoop/Kerberos prostředí – ticket-based SSO. | Hadoop ekosystém |
| Single User (dev) | Jedno username/heslo v nifi.properties. Pouze pro vývoj / test. | Nikdy prod |
Granulární přístupová práva na úrovni každé komponenty (processor, connection, process group). Definovány v authorizations.xml nebo delegovány na Apache Ranger.
| Policy | Oprávnění |
|---|---|
| view the component | Vidět processor / connection v canvasu |
| modify the component | Editovat konfiguraci procesoru |
| view the data | Prohlížet FlowFile content a atributy ve frontách |
| modify the data | Mazat FlowFiles z front, replay z provenance |
| receive data via S2S | Přijímat FlowFiles přes Site-to-Site |
| operate | Start/stop komponenty (bez možnosti editace) |
| access provenance | Prohlížet Data Provenance záznamy |
# Všechna citlivá property v processor konfiguraci jsou šifrována # Klíč definován v bootstrap.conf: nifi.bootstrap.sensitive.key=0123456789ABCDEF... # 256-bit hex # Šifrování nifi.properties (Encrypt-Config tool) – jen NiFi 1.x, v NiFi 2.x odstraněno: ./bin/encrypt-config.sh \ -n conf/nifi.properties \ -b conf/bootstrap.conf \ -k $MASTER_KEY # NiFi 1.14+ podporuje HashiCorp Vault pro správu klíčů: nifi.sensitive.props.provider=vault nifi.sensitive.props.vault.token=s.xxx
<provider> <identifier>ldap-provider</identifier> <class>org.apache.nifi.ldap.LdapProvider</class> <property name="Authentication Strategy">SIMPLE</property> <property name="Manager DN">CN=svc-nifi,OU=SA,DC=corp,DC=cz</property> <property name="Manager Password">{encrypted}</property> <property name="Url">ldaps://dc.corp.cz:636</property> <property name="User Search Base">OU=Users,DC=corp,DC=cz</property> <property name="User Search Filter">sAMAccountName={0}</property> <property name="TLS - Truststore">./conf/truststore.p12</property> </provider>
Metriky, alerting, auditní stopa, operační postupy
| Metrika | Co měří | Interpretace |
|---|---|---|
| In / Out (FlowFiles/s) | Průtok FlowFiles za 5 min okno | Základní throughput. In >> Out = hromadění. |
| Read / Write (bytes/s) | I/O content repository | Disk bound procesory (komprese, šifrování, velké soubory). |
| Tasks/Time | Počet spuštění procesoru / celkový čas | Time/Task = průměrná latence 1 iterace. |
| Queued (FlowFiles / bytes) | Aktuálně čekající v connection | Rostoucí queue = downstream bottleneck. |
| Active Threads | Aktuálně běžící vlákna procesoru | = concurrent tasks v chodu. 0 s frontou = yieldovaný nebo čekající na resource. |
| Reporting Task | Cíl |
|---|---|
| PrometheusReportingTask | Prometheus /metrics endpoint (scrape) |
| SiteToSiteProvenanceReportingTask | Provenance events → jiný NiFi flow |
| SiteToSiteBulletinReportingTask | Bulletins → jiný NiFi / Elasticsearch |
| ElasticsearchReportingTask | Metriky processorů → Elasticsearch |
| ControllerStatusReportingTask | Metriky → log file |
| CassandraReportingTask | Metriky → Cassandra |
Pro každý FlowFile jsou zaznamenány tyto typy událostí:
# Filtry v Data Provenance UI: # FlowFile UUID – přesné dohledání konkrétního záznamu # Attribute – hledání dle hodnoty atributu (filename, path...) # Processor – všechny události pro daný processor # Event Type – filtr dle typu (RECEIVE, SEND, DROP...) # Time Range – od/do # Component Type – filtr dle typu procesoru # Lineage view: # Klikněte na event → "Show Lineage" → vizuální strom celého životního cyklu # FlowFile vidíte od RECEIVE přes všechny CLONE/FORK/JOIN až po DROP/SEND # Replay: ze záznamu lze znovu pustit FlowFile (z obsahu uloženého v provenance)
| Soubor | Obsah |
|---|---|
logs/nifi-app.log | Hlavní application log – procesory, framework, startup |
logs/nifi-bootstrap.log | Start/stop JVM procesu – bootstrap wrapper |
logs/nifi-user.log | Auditní log uživatelských akcí (login, konfigurace změny) |
logs/nifi-request.log | HTTP access log pro REST API volání |
LogAttribute – loguje všechny atributy FlowFile do nifi-app.log. Nastavte Log Level = INFO a Log Payload = true (pro obsah). V produkci ho nezapomeňte odebrat nebo nastavit na WARN.Zastavte všechny procesory před restartem NiFi. In-flight FlowFiles v paměti (Event Driven) se přesunou zpět do front díky WAL – žádná ztráta.
Pokud disk s Content Repository nebo FlowFile Repository selže nebo se zaplní, NiFi se zastaví. Využití disku sledujte jako kritický alert (>80 %).
Výchozí retention může narůst na desítky GB. Nastavit v nifi.properties: nifi.provenance.repository.max.storage.size=5 GB a max.storage.time=30 days.
Výchozí 10 000 objektů / 1 GB nemusí sedět. Pro velké soubory snížit object count, pro malé záznamy zvýšit nebo zvýšit data size threshold.
Konfigurace, dokumentace, nástroje
| Property | Výchozí / Příklad | Popis |
|---|---|---|
nifi.web.https.port | 8443 | HTTPS port UI a API |
nifi.flowcontroller.graceful.shutdown.period | 10 sec | Čekání na dokončení zpracování při shutdownu |
nifi.queue.swap.threshold | 20 000 | Nad tento počet FlowFiles v queue se přelévají na disk (swap) |
nifi.content.repository.directory.default | ./content_repository | Cesta k Content Repo. Lze mít více (default, disk2…) |
nifi.provenance.repository.max.storage.size | 1 GB | Maximální velikost Provenance Repo |
nifi.provenance.repository.max.storage.time | 24 hours | Maximální stáří provenance záznamů |
nifi.flowfile.repository.directory | ./flowfile_repository | Cesta k FlowFile Repo (WAL) |
nifi.sensitive.props.key | {master key} | Klíč pro šifrování sensitive properties ve flow.json.gz (NiFi 1.x: flow.xml.gz) |
nifi.nar.library.directory | ./lib | Adresář s NAR soubory (processor balíčky) |
nifi.variable.registry.properties | Cesta k souboru s globálními proměnnými (key=value). V NiFi 2.0 odstraněno – místo proměnných použijte Parameter Contexts. |
NiFi procesory jsou baleny jako .nar soubory (speciální JAR s class-loader izolací). Vlastní procesory lze distribuovat jako NAR. Umístění: ./lib/ nebo ./extensions/. NiFi automaticky načte NARy při startu – hot-deploy není možné bez restartu.
# Výpis nainstalovaných NARů ls -la $NIFI_HOME/lib/*.nar # Přidání vlastního NARu (pak restart NiFi) cp my-custom-processors.nar $NIFI_HOME/lib/ ./bin/nifi.sh restart
# Připojení Registry k NiFi: # Menu → Controller Settings → Registry Clients → přidat # URL: http://nifi-registry.corp.cz:18080 # Verzování Process Group: # Pravý klik na Process Group → Version → Start version control # Vybrat Registry, Bucket, Flow name → Save # Commit změn: # Pravý klik → Version → Commit local changes → popis commitu # Rollback: # Pravý klik → Version → Change version → vybrat starší verzi
| Endpoint | Metoda | Popis |
|---|---|---|
/nifi-api/system-diagnostics | GET | JVM heap, disk, thread pool stav |
/nifi-api/flow/status | GET | Celkový stav flow (active threads, queued) |
/nifi-api/processors/{id} | GET/PUT | Stav a konfigurace procesoru |
/nifi-api/processors/{id}/run-status | PUT | Start / Stop / Terminate procesoru |
/nifi-api/process-groups/{id}/processors | GET | Výpis processorů v process group |
/nifi-api/provenance | POST | Vyhledávání v Data Provenance |
/nifi-api/connections/{id}/drop-requests | POST | Vyprázdnění connection queue |
/nifi-api/counters | GET | Čítače (Counter procesory) |
# Příklad – získání Bearer tokenu (OIDC / username+password) TOKEN=$(curl -sk -X POST https://nifi.corp.cz:8443/nifi-api/access/token \ -d "username=admin&password=secret") # Zastavení procesoru přes API: curl -sk -X PUT \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{"revision":{"version":5},"component":{"id":"abc-123","state":"STOPPED"}}' \ https://nifi.corp.cz:8443/nifi-api/processors/abc-123/run-status
| Zdroj | URL |
|---|---|
| Apache NiFi docs (officální) | https://nifi.apache.org/documentation.html |
| NiFi Expression Language Guide | https://nifi.apache.org/docs/nifi-docs/html/expression-language-guide.html |
| NiFi User Guide | https://nifi.apache.org/docs/nifi-docs/html/user-guide.html |
| NiFi Administration Guide | https://nifi.apache.org/docs/nifi-docs/html/administration-guide.html |
| NiFi Developer Guide (custom NAR) | https://nifi.apache.org/docs/nifi-docs/html/developer-guide.html |
| NiFi REST API (Swagger) | https://nifi.apache.org/docs/nifi-docs/rest-api/index.html |
| NiFi Registry docs | https://nifi.apache.org/docs/nifi-registry-docs/ |
| Apache NiFi GitHub | https://github.com/apache/nifi |
| Oficiální Docker image (proměnné, tagy) | https://hub.docker.com/r/apache/nifi |
| Awesome NiFi (community) | https://github.com/jfrazee/awesome-nifi |
1× NiFi + embedded ZooKeeper. Instalace <5 min. Žádná HA. Vhodné pro vývoj flow a testování processorů.
3× NiFi + 3× ZooKeeper (embedded nebo dedicated). Minimální prod konfigurace s HA a cluster coordinator election.
Přidání NiFi Registry pro flow verzování a CI/CD. Flows nasazeny přes Registry API z pipeline (GitOps).
NiFi v K8s via Helm chart (nicholaswilkinson/nifi nebo Apache NiFi Operator). MiNiFi = lightweight agent pro edge/IoT.