4. týždeň

Použitie Docker kontajnerov

Ciele

  1. Nainštalovať si Docker na vlastnom počítači.
  2. Naučiť sa používať Docker na spustenie programov v kontajneroch.
  3. Naučiť sa pracovať s dátami, sieťou, premennými prostredia v rámci Dockeru.
  4. Naučiť sa pracovať s viacerými kontajnermi pomocou Docker Compose.

Úvod

Docker je jedným z najpodstatnejších nástrojov pri vývoji a prevádzke softvéru. Umožňuje ľahko vytvoriť izolované prostredie pre beh programu, a tiež automatizovať jeho vytvorenie a distribúciu. Vďaka tomu môžeme presne kontrolovať prostredie, v ktorom vyvíjame softvér, testujeme ho a prevádzkujeme.

Na dnešnom cvičení si vyskúšate spúšťanie a základnú konfiguráciu Docker kontajnerov. Vyskúšate si tiež prepájanie skupiny kontajnerov pomocou Docker Compose.

Postup

Krok 1: Inštalácia

Pretým ako budete Docker používať, musíte si ho nainštalovať.

Úloha 1.1

Nainštalujte Docker na svoj počítač. Odporúčame použiť návod z predmetu IoT, kde sú detailné inštrukcie pre jednotlivé operačné systémy.

Krok 2: Hello, Docker!

Na spustenie kontajnera slúži príkaz docker run.

Úloha 2.1

Spustite jednoduchý Docker kontajner:

$ docker run hello-world

Tento príkaz zabezpečí, že Docker stiahne obraz hello-world (ak nebol stiahnutý skôr), vytvori na základe neho kontajner a spustí v ňom štandardný príkaz definovaný obrazom (hello). Tento príkaz len vypíše hlášku na štandardný výstup.

Úloha 2.2

Skontrolujte, že kontajner stále existuje, aj keď bol po vykonaní príkazy zastavený:

$ docker ps -a
$ docker ps -a  
CONTAINER ID   IMAGE         COMMAND    CREATED         STATUS                     PORTS   NAMES
6ed3b5658147   hello-world   "/hello"   8 seconds ago   Exited (0) 7 seconds ago           cranky_swirles

Poznámka

docker ps vypíše všetky aktuálne spustené kontajnery. Prepínač -a (all) pridá aj zastavené.

Pokiaľ kontajner nepomenujete pomocou prepínača --name, Docker mu priradí náhodný názov, ktorý vidíte v stĺpci NAMES.

Úloha 2.3

Odstráňte vytvorený kontajner pomocou príkazu docker rm, za ktorým uveďte ID alebo názov kontajnera z výpisu. Napríklad

$ docker rm 6ed3b5658147

alebo

$ docker rm cranky_swirles

Overte, či kontajner zmizol z výpisu docker ps -a

Pri spúšťaní kontajnera tiež môžete použiť prepínač --rm, ktorý zabezpečí jeho automatické odstránenie po tom, ako sa zastaví.

Úloha 2.4

Overte, že obraz hello-world je stále k dispozícii na vašom počítači pomocou príkazu docker images.

Jeho výstup bude vyzerať približne takto:

$ docker images                      
IMAGE                ID             DISK USAGE   CONTENT SIZE   EXTRA
hello-world:latest   1b44b5a3e06a       10.1kB             0B        

Obrazu používané v existujúcich kontajneroch sú označené písmenom U v stĺpci EXTRA.

Krok 3: Interaktívny kontajner

Ak chceme v kontajnere spustiť interaktívny príkaz, musíme použiť prepínač -it, ktorý je vlastne kombináciou prepínačov -i (interactive) a -t (tty).

Úloha 3.1

Vytvorte kontajner s minimálnou verziu linuxovej distribúcie Ubuntu a spustite interpretátor príkazov v nej:

$ docker run --rm -it ubuntu:24.04 bash

Vyskúšajte spúšťať príkazy v kontajnere a vytvárať súbory. Potom ukončite prácu pomocou príkazu exit.

Úloha 3.2

Skontrolujte, že súbory, ktoré ste vytvorili, neexistujú mimo kontajnera. Keď znovu použijete docker run, vytvorí sa nový kontajner, v ktorom tiež nebudú žiadne zmeny, ktoré ste robili v pôvodom kontajnere.

Kontajnery sú len dočasné prostredia určené pre beh jedného programu. Preto vo väčšine prípadov nemá zmysel ponechávať zastavené kontajnery a s nimi spojené dáta.

Poznámka

Kým je kontajner spustený, môžete v inom okne terminála skontrolovať výstup docker ps. Mali by ste vidieť informáciu o bežiacom kontajnere (stav Up).

$ docker ps
CONTAINER ID   IMAGE          COMMAND   CREATED              STATUS              PORTS     NAMES
afe320fa9d8a   ubuntu:24.04   "bash"    About a minute ago   Up About a minute             vigilant_hodgkin

Krok 4: Mapovanie portov

Skúsme spustiť populárny webový server Nginx. Webový server dokáže reagovať na HTTP požiadavky prehliadača a posielať mu webové stránky, ktoré prehliadač zobrazí.

Nginx štandardne počúva na porte 80. Ak spustíme Nginx v Docker kontajneri, bude tento port dostupný len v rámci kontajnera. Aby sme mohli pristupovať k Nginx z nášho počítača, musíme namapovať port 80 z kontajnera na nejaký port na našom počítači. To sa robí pomocou prepínača -p (publish) pri spúšťaní kontajnera.

Úloha 4.1

Spustite kontajner s Nginxom a namapujte port 80 z kontajnera na port 8080 na vašom počítači:

$ docker run --rm -p 8080:80 nginx:latest

Otvorte webový prehliadač a zadejte adresu http://localhost:8080. Mali by ste vidieť uvítaciu stránku Nginxu.

Uvítacia stránka Nginxu v prehliadači
Obr. 1: Uvítacia stránka Nginxu v prehliadači

Poznámka

Časť za dvojbodkou v názve obrazu (napr. nginx:latest) sa nazýva tag a slúži na označenie konkrétnej verzie obrazu. Ak tag neuvediete, Docker použije predvolený tag latest. V tomto prípade použijeme najnovšiu verziu Nginxu, ktorá je dostupná v Docker Hubu.

Ak by ste chceli použiť konkrétnu verziu Nginxu, môžete zadať napríklad nginx:1.25.3. Dostupné tagy a ich význam môžete nájsť v dokumentácii daného obrazu na Docker Hube.

Úloha 4.2

Zastavte kontajner pomocou klávesovej skratky Ctrl+C v terminále, kde je spustený. Teraz môžete znovu načítať stránku http://localhost:8080 a skontrolovať, že už nie je dostupná.

Krok 5: Zväzky (volumes)

Keďže kontajner je dočasné prostredie, všetky zmeny, ktoré v ňom urobíte, sa po jeho odstránení stratia. Ak chceme uchovávať dáta trvale, musíme použiť tzv. zväzky (volumes).

V tomto kroku použijeme obraz s jednoduchou webovou aplikáciou pre písanie poznámok, ktorá je dostupná na Docker Hube pod názvom kpituke/notes-app-example. Táto aplikácia umožňuje vytvárať, zobrazovať a mazať poznámky. Je napísaná v jazyky Python. Na ukladania dát môže používať súbor /data/notes.json, alebo databázový server PostgreSQL.

Úloha 5.1

Spustite kontajner s touto aplikáciou a namapujte port 5000 z kontajnera na port 5000 na vašom počítači. Použite príkaz docker run podobne ako v predchádzajúcom kroku, ale obrazom kpituke/notes-app-example:latest a portami 5000:5000.

Otvorte webový prehliadač a zadajte adresu http://localhost:5000. Mali by ste vidieť jednoduché rozhranie pre písanie poznámok. Skúste pridať niekoľko poznámok a potom znovu načítať stránku. Poznámky by mali byť stále zobrazené, pretože sú uložené v rámci kontajnera.

Riešenie

$ docker run --rm -p 5000:5000 kpituke/notes-app-example:latest

Úloha 5.2

Zastavte kontajner pomocou Ctrl+C a potom ho znovu spustite pomocou rovnakého príkazu docker run. Skontrolujte, že poznámky, ktoré ste vytvorili, zmizli.

Na to, aby sa poznámky uchovali aj po zastavení a odstránení kontajnera, musíme použít zväzok, ktorý namapuje adresár /data z kontajnera na trvalé úložisko na vašom počítači.

Úloha 5.3

Vytvorte adresár ./notes-data v aktuálnom adresári, kde budete spúšťať kontajner. Tento adresár bude slúžiť ako trvalé úložisko pre poznámky.

Spustite znovu kontajner s aplikáciou na poznámky, ale tentokrát použite prepínač -v (volume) na namapovanie adresára /data z kontajnera na adresár ./notes-data vo vašom počítači. Parameter pre zväzok bude vyzerať takto: -v $(pwd)/notes-data:/data.

Vytvorte poznámky v aplikácii a potom zastavte kontajner. Skontrolujte, že v adresári ./notes-data sa nachádza súbor notes.json, ktorý obsahuje vaše poznámky. Skontrolujte, že poznámky sú stále zobrazené, keď znovu spustíte kontajner s týmto zväzkom.

Riešenie

$ mkdir notes-data
$ docker run --rm -p 5000:5000 -v $(pwd)/notes-data:/data kpituke/notes-app-example:latest

Krok 6: Sieť

V predchádzajúcom kroku sme spustili aplikáciu, ktorá používa súborový systém na uchovávanie dát. Môžeme však použiť aj databázový server, ktorý bude bežať v inom kontajneri.

Keďže každý kontajner je izolované prostredie, nemôžu sa navzájom vidieť a komunikovať pomocou štandardných sieťových rozhraní. Nepomôže nám ani mapovanie portov, ktoré sme použili v predchádzajúcich krokoch, pretože to umožňuje komunikáciu len medzi kontajnerom a vonkajším svetom (našim počítačom), ale nie medzi kontajnermi navzájom.

Preto musíme na komunikáciu medzi kontajnermi vytvoriť Docker sieť.

Úloha 6.1

Vytvorte novú Docker sieť s názvom notes-network pomocou príkazu:

$ docker network create notes-network

Úloha 6.2

Spustite kontajner s PostgreSQL databázou a pripojte ho k sieti notes-network. Použite obraz postgres:17. Nastavenia serveru (názov databázy, používateľ, heslo) sa definujú pomocou premenných prostredia, ktoré zadáte pomocou prepínača -e. Celý príkaz bude vyzerať takto:

$ docker run -d --name notes-db --network notes-network -e POSTGRES_DB=notes -e POSTGRES_USER=notes_user -e POSTGRES_PASSWORD=notes_pass postgres:17

Prepínač -d (detached) zabezpečí, že kontajner bude spustený na pozadí a neblokuje váš terminál.

Prepínač --name zas umožňuje pomenovať kontajner. Toto meno využijeme na komunikáciu s ním z iných kontajnerov v tej istej sieti.

Úloha 6.3

Spustite kontajner s aplikáciou na poznámky a pripojte ho tiež k sieti notes-network. Použite obraz a mapovanie portov ako v predchádzajúcich krokoch. Navyše potrebujeme tiež nastaviť premenné prostredia, ktoré aplikácia používa na pripojenie k databáze. Celý príkaz bude vyzerať takto:

$ docker run -d --name notes-app -p 5000:5000 --network notes-network -e STORAGE_BACKEND=postgres -e DB_HOST=notes-db -e DB_NAME=notes -e DB_USER=notes_user -e DB_PASSWORD=notes_pass kpituke/notes-app-example:latest

Premennú DB_HOST sme nastavili na názov kontajnera s databázou (notes-db), pretože v rámci tej istej Docker siete môžeme komunikovať s inými kontajnermi pomocou ich názvov.

Úloha 6.4

Otvorte webový prehliadač a zadajte adresu http://localhost:5000. Skontrolujte, že aplikácia funguje správne. Všimnite si tiež nadpis „Storage: postgres“, ktorý indikuje, že aplikácia používa databázu namiesto súboru.

Úloha 6.5

Skontrolujte výstup docker ps, že oba kontajnery (aplikácia a databáza) sú spustené.

Poznámka

Keďže kontajnery nebežia na pozadí, nevidíte v terminále ich výstup. Môžete ho zobraziť pomocou príkazu docker logs za ktorým uveďte ID alebo názov kontajnera. Napríklad:

$ docker logs notes-app

Úloha 6.6

Odstráňte oba kontajnery pomocou príkazu docker rm -f za ktorým uveďte názvy kontajnerov:

$ docker rm -f notes-app notes-db

Odstrániť môžete aj sieť pomocou

$ docker network rm notes-network

Krok 7: Docker Compose

Ako vidíte, spúšťanie viacerých kontajnerov a ich konfigurácia pomocou príkazu docker run môže byť dosť komplikovaná a neprehľadná. Na jej zjednodušenie výborne slúži nástroj Docker Compose, ktorý umožňuje definovať a spúšťať skupinu kontajnerov pomocou jedného konfiguračného súboru compose.yaml.

Úloha 7.1

Vytvorte súbor compose.yaml s nasledujúcim obsahom (nahraďte ??? správnymi hodnotami z predchádzajúceho kroku):

services:
  notes-db:
    image: postgres:17
    environment:
      POSTGRES_DB: notes
      POSTGRES_USER: notes_user
      POSTGRES_PASSWORD: notes_pass
    volumes:
      - db-data:/var/lib/postgresql/data
  notes-app:
    image: ???
    ports:
      - "5000:5000"
    environment:
      STORAGE_BACKEND: postgres
      DB_HOST: notes-db
      ???
    depends_on:
      - notes-db
volumes:
  db-data:

Úloha 7.2

Spustite oba kontajnery pomocou príkazu docker compose up v adresári, kde sa nachádza súbor compose.yaml. Tento príkaz načíta konfiguráciu z compose.yaml, vytvorí potrebné siete a spustí oba kontajnery.

Úloha 7.3

Otvorte webový prehliadač a zadajte adresu http://localhost:5000. Skontrolujte, že aplikácia funguje správne.

Úloha 7.4

Zastavte oba kontajnery pomocou Ctrl+C v terminále, kde je spustený docker compose up. Keď znovu spustíte docker compose up, všimnite si, že kontajnery sa spustia rýchlejšie, pretože už existujú a Docker ich znovu spustí. Na odstránenie kontajnerov, sietí a zväzkov vytvorených pomocou Docker Compose použite príkaz docker compose down.