Ciele
- Naučiť sa vytvárať vlastný Docker obraz.
- Pochopiť význam vrstiev v Docker obrazoch.
- Vyskúšať využitie nástrojov na správu závislostí.
- Naučiť sa optimalizovať zostavovanie obrazov pomocou viacfázového zostavovania.
Úvod
Na dnešnom cvičení si vyskúšame vytváranie vlastných Docker obrazov. Ako príklady použijeme aplikácie z minulých cvičení.
Postup
Krok 1: Náš prvý obraz
Náš prvý obraz pripravíme pre webovú stránku z cvičenia 3.
Úloha 1.1
Stiahnite si projekt git-branch z GitLabu.
Obsahom tohto projektu je jednoduchá webová stránka. Našim cieľom je vytvoriť kontajner, ktorý bude po spustení počúvať na porte 80 na požiadavky prehliadača a odošle mu túto stránku. Preto ako základný obraz použijeme obraz s webovým serverom nginx.
Úloha 1.2
Preštudujte si dokumentáciu obrazu, konkrétne sekciu Hosting some simple static content. Vytvorte podľa nej súbor Dockerfile v adresári projektu. Namiesto static-html-directory vo vašom prípade môže byť aktuálny adresár .
Riešenie
FROM nginx
COPY . /usr/share/nginx/html
Úloha 1.3
Zostavte obraz:
$ docker build -t simple-web-page .
Spustite kontajner na základe neho vytvoreného obrazu a namapujte port 8000 na vašom počítači na port 80 v kontajneri. presný príkaz vytvorte podľa minulého cvičenia.
Úloha 1.4
Zadajte v prehliadači adresu http://localhost:8000/ a skontrolujte, či sa stránka zobrazila správne.
Gratulujeme! Práve ste vytvorili svoj prvý Docker obraz a spustili kontajner, ktorý z neho vznikol!
Krok 2: Zložitejší obraz
Skúsme vytvoriť obraz pre webovú aplikáciu pre poznámky z minulého cvičenia.
Úloha 2.1
Stiahnite si zdrojové kódy aplikácie a rozbaľte v adresári notes-app.
Aplikácia používa jazyk Python. Potrebujeme teda použiť základný obraz, ktorý obsahuje všetko potrebné pre beh aplikácií v tomto jazyku. V našom prípade to môže byť obraz python:3.14-slim. Ten obsahuje Python 3.14 a minimálnu (slim) verziu distribúcie Debian.
Úloha 2.2
Vytvorte jednoduchý Dockerfile:
FROM python:3.14-slim
WORKDIR /app
COPY . .
RUN pip install --no-cache-dir -r requirements.txt
EXPOSE 5000
CMD ["python", "app.py"]
Deklarácia FROM špecifikuje základný obraz, WORKDIR – pracovný adresár, COPY kopíruje súbory z vášho počítača do obrazu.
Deklarácia RUN spúšťa príkaz v dočasnom kontajnere a všetky zmeny, ktoré vykoná, pridá ako ďalšiu vrstvu do obrazu. V tomto prípade je to spustenie príkazu pip (package installer for Python), ktorý nainštaluje všetky Python knižnice, ktoré náš program potrebuje. Ich zoznam je v súbor requirements.txt.
Deklarácia EXPOSE len dokumentuje, ktorý port používa kontajner a je možné ho teda mapovať. CMD špecifikuje, ktorý príkaz sa má spustiť, keď sa z obrazu vytvorí a spustí kontajner.
Úloha 2.3
Zostavte obraz a spustite kontajner:
$ docker build -t notes-app .
$ docker run --rm -p -p 5000:5000 -v notes-data:/data notes-app
Zadajte adresu http://localhost:5000 v prehliadači a uistite sa, že aplikácia pracuje správne.
Ak všetko funguje, tak práve ste vytvorili ďalší vlastný kontajner, spustili ste obraz založený na ňom, v ktorom beží jednoduchá webová aplikácia!
Krok 3: Optimalizácia zostavenia obrazu
Zostavovanie komplexných obrazov môže byť časovo dosť náročné. Je potrebné sťahovať závislosti z internetu, inštalovať ich, kompilovať program, atď. Preto sa Docker snaží optimalizovať tento proces pomocou vrstiev. Každý príkaz v Dockerfile vytvára novú vrstvu, ktorá sa môže znovu použiť, ak sa nezmenia dáta, z ktorých bola vytvorená alebo predchádzajúce vrstvy.
Napríklad príkaz COPY sa vykoná znovu len vtedy, ak sa zmení niektorý zo súborov, ktoré kopíruje, alebo niektoré z predchádzajúcich vrstiev. Príkaz RUN sa tiež vykoná znovu len vtedy, ak sa zmení niektorá z vrstiev, na ktorých závisí.
Úloha 3.1
Skúste urobiť zmenu v súbor app.py, napríklad zmeniť nadpis <h1>📝 Notes</h1> na <h1>📝 Poznámky</h1> na riadku 159. Keď znovu spustite docker build, všimnite si, že sa znovu spúšťa aj príkaz pip, aj keď závislosti sa nezmenili.
Je to spôsobené tým, že príkaz RUN závisí na vrstve vytvorenej príkazom COPY a tá závisí od všetkých súborov projektu.
To môžeme optimalizovať tak, že najprv skopírujeme len súbor requirements.txt a spustíme príkaz RUN na inštaláciu závislostí. Až potom skopírujeme zvyšok súborov. Vrstva so závislosťami sa tak bude znovu používať, pokiaľ sa nezmení súbor requirements.txt.
Úloha 3.2
Upravte Dockerfile nasledovne:
FROM python:3.14-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY app.py .
EXPOSE 5000
CMD ["python", "app.py"]
Úloha 3.3
Znovu zostavte obraz a všimnite si, že sa vytvára viac vrstiev. Urobte zmenu v app.py a znovu zostavte obraz. Všimnite si, že príkaz RUN sa už nespúšťa, pretože závislosti sa nezmenili.
Krok 4: Vytvorenie obrazu s programom v jazyku C
Skúsme niečo zložitejšie. Pripravme obraz s programom v jazyku C. Použijeme modifikovaný príklad z cvičenia 2 – „jednorozmerné piškvorky“.
Úloha 4.1
Stiahnite si zdrojový kód hry a rozbaľte ho v adresári piskvorky.
Úloha 4.2
Vytvorte súbor Dockerfile. Ako základný obraz použijeme gcc, ktorý obsahuje prekladač GCC a iné nástroje pre preklad programov v jazyku C.
Nastavte pracovný adresár v obraze na /src pomocou príkazu WORKDIR.
Pridajte príkaz pre kopírovanie (COPY) zdrojových súborov do adresára /src v obraze.
Spustite preklad pomocou príkazu RUN.
Nastavte príkaz po spustení kontajnera (CMD) na ./piskvorky.
Úloha 4.3
Zostavte obraz a spustite kontajner. Nezabudnite pridať prepínač -it pre interaktívny režim, aby ste mohli hrať hru v termináli.
$ docker build -t piskvorky .
$ docker run --rm -it piskvorky
Krok 5: Viacfázové zostavovanie
V niektorých prípadoch môže príprava a kompilácia programu vyžadovať viac závislostí a nástrojov, ktoré nie sú potrebné pre samotný beh programu. Napríklad preklad programu v jazyku C vyžaduje prekladač, vývojové nástroje, knižnice a hlavičkové súbory, ale výsledný spustiteľný súbor je často veľmi malý a nevyžaduje žiadne z týchto nástrojov. Preto by bolo zbytočné, aby ich obsahoval aj výsledný obraz.
Úloha 5.1
Pozrite si aký veľký je obraz piskvorky pomocou príkazu docker images:
$ docker images piskvorky
IMAGE ID DISK USAGE CONTENT SIZE EXTRA
piskvorky:latest e9a4a55676b1 1.54GB 0B
Na spustenie piškvoriek v príkazovom riadku určite nepotrebujeme Docker obraz s veľkosťou 1.5 GB.
Pre riešenie tohto problému slúži viacfázové zostavovanie. Umožňuje nám použiť jeden obraz pre fázu zostavovania, v ktorej máme všetky nástroje a závislosti potrebné pre prípravu programu, a druhý obraz pre fázu behu, ktorý obsahuje len to, čo je potrebné pre spustenie programu.
Úloha 5.2
Upravte Dockerfile pre hru „piškvorky“ nasledovne:
# Fáza zostavovania
FROM gcc AS builder
# ... zostávajúce príkazy pre zostavovanie programu ...
# Fáza behu
FROM debian:stable-slim
WORKDIR /app
COPY --from=builder /src/piskvorky .
CMD ["./piskvorky"]
Úloha 5.3
Spustite kontajner a uistite sa, že hra stále funguje správne.
Úloha 5.4
Znovu zostavte obraz a skontrolujte jeho veľkosť. O koľko je menší ako predtým?
Poznámka
Obraz sa dá ešte viac zmenšiť, ak by sme použili ešte menší základný obraz pre fázu behu, napríklad alpine, ktorý je založený na Alpine Linuxu a má veľkosť len 5 MB, alebo dokonca scratch, ktorý je úplne prázdny a neobsahuje žiadne súbory ani nástroje.
Nie každá aplikácia však bude fungovať v takto obmedzenom prostredí. V prípade našej hry „piškvorky“ by to fungoval ak by sme ju kompilovali staticky, teda bez závislosti na zdieľaných knižniciach. To by sme mohli dosiahnuť pridaním prepínača -static pri kompilácii.