Nasaď svoji aplikaci s Dockerem

authorMatyáš Caras11/3/2025 11:30

Konečně máš hotovu webovou aplikaci, tak už ji jen nasadit na server. Tak už jen nainstalovat bal- aha… Najednou zjistíš, že na serveru chybí většina nástrojů, které jsou ke spuštění potřeba. A tak strávíš pár hodin studováním, jak všechny ty věci doinstalovat. A přesně proto vznikl Docker.

Cover Image

Jednotné prostředí vždy a všude

Docker provádí tzv. kontejnerizaci vašeho kódu – celý projekt zabalí do “kontejneru”, což je v podstatě virtualizovaný operační systém, ve kterém vaše aplikace poběží izolovaně od ostatních procesů na vašem počítači.

Začínáme

Než nainstalujeme samotný Docker, je třeba nainstalovat Windows Subsystem for Linux. Jelikož Docker vznikl především pro UNIXové systémy, je podpora pro Windows dost chabá. Microsoft se to rozhodl vyřešit tak, že vytvořil zmíněný WSL, se kterým má Docker možnost pracovat tak, jak by to dělal na Linuxu.

WSL nainstaluješ jednoduše otevřením příkazové řádky v administrátorském režimu (vyhledej cmd, klikni pravým a vyber možnost “Spustit jako administrátor”). Do něj zadáš příkaz wsl --install a jen následuješ instrukce.

Jakmile dokončíš instalaci WSL, stáhni si instalátor Docker Desktop. Při instalaci nezapomeň zakliknout možnost používat WSL 2.

Okno instalátoru Dockeru; šipka ukazuje na zaškrtnutou možnost "Use WSL 2 instead of Hyper-V"
Instalátor Dockeru

Šup s aplikací do kontejneru

Nyní když máš Docker nainstalovaný, je třeba si připravit tzv. Dockerfile – soubor, který obsahuje instrukce, jak se má tvoje aplikace sestavit. Pokud se tvoje aplikace skládá z více částí, např. máš rozdělený front-end a back-end, ideálně budeš chtít vytvořit více různých Dockerfilů a pak je nasadit pomocí Docker Compose. V rámci soutěže však nepoužíváme Compose jako takový, takže pro instrukce jak nasadit aplikaci na naše servery mrkni na oficiální návod.

Pro ukázku použiju projekt napsaný s Node.js. Ve svém projektu mám jednoduchý web server, který poslouchá na portu 3000:

Ukázkový kód pro "Hello World" serverovou aplikaci napsanou v JavaScriptu
Ukázkový kód pro Node.js aplikaci

Začátkem každého Dockerfilu je definice nějakého obrazu. Tím je nějaký operační systém, avšak existuje spousta obrazů, které mají nástroje, které používáte, již předpřipravené, stačí se podívat na Docker Hub. Např. pro Node.js použiju oficiální Node.js obraz. Za klíčovým slovem FROM uvedeš název obrazu a za dvojtečkou značku – to je např. verze daného nástroje, dostupné značky najdeš na stránce Docker obrazu, který chceš použít.

FROM node:22

Nyní můžeme specifikovat nějaké proměnné, které se vloží do proměnného prostředí našeho kontejneru. V Node.js se používá proměnná NODE_ENV, která udává, jestli pracujeme ve vývojovém, nebo produkčním prostředí. Pro ukázku ho nastavím právě na produkční prostředí klíčovým slovem ENV. Proměnné se vždy zadávají ve tvaru klíč=hodnota, na nový řádek tedy vložím:

ENV NODE_ENV=production

Takto určitě nechceš vkládat soukromá data, jako např. API klíče. Jak správně vkládat takové klíče si ukážeme níže.

Pokud chceš mít možnost měnit určité hodnoty při sestavování, můžeš použít argumenty. Např. kdybys chtěl při sestavování specifikovat verzi své aplikace, do Dockerfilu vložíš:

ARG NAZEV_ARGUMENTU

V rámci Dockerfilu pak na něj můžeš odkazovat s $, zde bys tedy použili $NAZEV_ARGUMENTU.

Ve výchozím stavu Docker pracuje v kořenové složce systému, tedy složce, kde jsou všechny systémové soubory. Abychom si pro svůj projekt udělali vlastní složku, použij klíčové slovo WORKDIR. To složku samo vytvoří, pokud chybí, a hned se tam přesune.

WORKDIR /app

Klíčovým slovem COPY řekneš Dockeru, jaké soubory a složky má do kontejneru zkopírovat. Docker může kopírovat složky jen v rámci aktuálního kontextu – ve výchozím je to složka, ve které se Dockerfile nachází, to se dá ale případně změnit při sestavování. Na jeden řádek můžeš napsat všechny soubory, které chceš zkopírovat, jako poslední uveď cestu, kam se soubory mají umístit v kontejneru:

COPY index.js package.json package-lock.json /app

Případně pokud chceš zkopírovat rovnou všechny soubory, stačí použít .

COPY . /app

Nejdůležitější je klíčové slovo RUN. S ním spustíš příkazy, které potřebuješ k připravení svého projektu na spuštění. Schválně píšu “připravení”, protože na samotné spuštění aplikace se používá jiné klíčové slovo. Například v Node.js je potřeba nainstalovat použité knihovny pomocí správce balíků:

RUN npm install

Pozn.: V závislosti na obrazu, který použiješ, můžou některé nástroje chybět. Vždycky je však můžeš doinstalovat přes správce balíků systému, který tvůj obraz používá. To vždy zjistíš v dokumentaci daného obrazu na Docker Hubu.

Pro samotné spuštění procesu tvé aplikace slouží klíčová slova ENTRYPOINT a CMD. ENTRYPOINT se používá hlavně když chceš kontejner používat jako spustitelný nástroj, což my nepotřebujeme, takže si vystačíme s CMD. Případný rozdíl mezi těmito klíčovými slovy najdeš zde.

Kvůli kompatibilitě se systémem je doporučeno příkaz nezadávat jako text, ale jako seznam. Moje aplikace se spouští příkazem node index.js, takže do Dockerfilu napíšu:

CMD ["node","index.js"]

Jako poslední musíme říct Dockeru, aby zveřejnil port, kde aplikace běží. Moje aplikace, jak lze vidět v kódu, běží na portu 3000. Použiju tedy klíčové slovo EXPOSE, aby ho Docker zveřejnil.

Tip: toto je ideální místo, kde použít proměnné a argumenty.

EXPOSE 3000

A Dockerfile je hotový, teď už jen celý projekt sestavit.

FROM node:22

ARG VERSION
ENV VERSION=${VERSION}

WORKDIR /app
COPY index.js package.json package-lock.json ./

RUN npm install

CMD ["node","index.js"]
EXPOSE 3000

Sestavení

Sestavení se provede jednoduše příkazem docker build.

docker build . -t tda-aplikace --build-arg VERSION=1.0

Ta tečka říka Dockeru, že Dockerfile najde tady, argument -t umožňuje výsledný obraz pojmenovat. V případě, že používáš argumenty (ARG), jejich hodnotu teď můžeš nastavit možností --build-arg, kde uvedeš argument ve tvaru NÁZEV=hodnota, kde názevmusí odpovídat argumentu, který jste si nadefinovali.

Abychom si otestovali, že sestavená aplikace funguje, jak má, spustíme aplikaci příkazem

docker run -p 3000:3000 tda-aplikace:latest

Možnost -p vezme port z aplikace (ten za dvojtečkou) a napojí ho na port na tvém počítači (před dvojtečkou). Na konec už jen uvedeš název obrazu, který jsme uvedli při sestavování, a za něj :latest, což Dockeru říká, aby použil nejnovější verzi tohoto obrazu. Teď si můžeš otevřít http://localhost:3000 v tvém prohlížeči a zjistit, jestli aplikace běží.

Screenshot prohlížeče nasměrovaný na "localhost:3000". Aplikace vrátila text "Ahoj, nastavil jsi mi build argument VERSION na 1.0"
A je nasazeno!

Bezpečnost především

Ve výchozím stavu používá Docker uvnitř kontejneru root uživatele, tedy systémového administrátora. Přestože se jedná jen o virtuální kontejner, který nemůže zasahovat do systému (pokud nepropojíš složky skrz svazky). Proto je dobrý zvyk nastavit jiného, nesprácvovského uživatele hned poté, co se dokončí všechny administrátorské operace (např. instalace softwaru). K tomu slouží klíčové slovo USER, kterému stačí specifikovat název nového uživatele. Toho však musíme nejdřív vytvořit, proto náš existující Dockerfile upravíme takto:


FROM node:22

ARG VERSION
ENV VERSION=${VERSION}

RUN useradd -ms /bin/bash myuser
RUN mkdir /app && chown myuser:myuser /app
USER myuser

WORKDIR /app
COPY --chown=myuser:myuser index.js package.json package-lock.json ./

RUN npm install

CMD ["node","index.js"]
EXPOSE 3000
  • Příkaz useradd vytvoří nového uživatele, kterého budeme používat ke spuštění aplikace.
     
  • Příkazem mkdir vytvoříme složku aplikace, abychom ji pak příkazem chown mohli přidělit našemu uživateli. Bez tohoto by složku vlastnil root a náš uživatel by s ní nemohl pracovat.
     
  • Klíčovým slovem USER se přepneme na našeho uživatele.
     
  • Za COPY přidáme --chown=..., čímž se vlastnictví zkopírovaných souborů automaticky nastaví na našeho uživatele, aby s nimi mohl dál pracovat.

Pokud pak chceme přidávat tajné klíče, můžeme je do kontejneru přidat při spuštění přes docker run použitím parametru --env, pokud chceme nastavit jednu proměnnou, nebo --env-file, pokud chceme, aby Docker proměnné načetl ze souboru.

docker run --env VERSION=1 -p 3000:3000 tda-aplikace:latest

# NEBO, pokud máme env soubor:

docker run --env-file .env -p 3000:3000 tda-aplikace:latest

Takto máme alespoň základní zabezpečení v rámci našeho Docker obrazu.

Přehled klíčových slov

V tabulce níže nalezneš přehled výše použitých klíčových slov v rámci Dockerfile. Určitě mrkni i na oficiální dokumentaci, která ti toho řekne ještě více.

Klíčové slovoPopisUkázka použitíPopis použití
FROMDefinuje, jaký obraz se má použítFROM node:22Použije Node.js obraz z Docker Hubu se značkou 22
ARGUmožňuje nastavit argument, který lze měnit při sestaveníARG AHOJ_SVETEDefinuje argument s názvem AHOJ_SVETE
ENVNadefinuje proměnnou, která se vloží do prostředí kontejneruENV AHOJ=sveteNastaví proměnnou v prostředí s názvem AHOJ na hodnotu svete
WORKDIRZmění pracovní adresář; v případě, že cesta neexistuje, vytvoří jiWORKDIR /appZmění pracovní adresář na /app
COPYZkopíruje soubory ze systému do kontejneruCOPY index.js kod /appZkopíruje soubor index.js a složku kod ze systému do složky /app v kontejneru
RUNSpustí příkaz v kontejneruRUN echo “Ahoj světe”Pustí daný příkaz při sestavení
CMDNastaví příkaz, který se spustí při vytvoření kontejneruCMD [“node”, “index.js”]Pustí daný příkaz při zapnutí kontejneru
EXPOSEZveřejní kontejnerový portEXPOSE 3000Zveřejní port číslo 3000
USERZmění aktivního uživateleUSER myuserPřepne se na uživatele myuser. Tento uživatel již musí existovat!

© 2025 Student Cyber Games, z.s. – Vydáno pod licencí CC BY-NC-SA 4.0.