Naučíte sa:
- Vytvoriť vlastný obraz pomocou
docker build
- Určiť príkaz na vykonanie
- Určiť systém na konfigurovanie
Vytvorte jednoduchú webovú aplikáciu pomocou skriptovacieho jazyka Python a frameworku Flask. V aplikácii definujeme niekoľko funkcií ktoré vedia spracovať HTTP požiadavky a vrátiť odpoveď vo forme HTML.
V našom prípade si vytvoríme aplikáciu, ktorá vie pozdraviť a vie povedať aktuálny čas:
Zdrojový text aplikácie: app.py
from datetime import date
from flask import Flask
app = Flask(__name__)
@app.route("/")
def hello():
return "<h1 style='color:blue'>Hello There!</h1><a href='/date'>Dátum a čas</a>"
@app.route("/date")
def today():
today = date.today()
return "<p>{}</p>".format(today.strftime("%d.%m.%Y"))
if __name__ == "__main__":
app.run()
Ak by sme takúto aplikáciu chceli spustiť klasickým spôsobom, potrebujeme:
- mať nainštalovaný interpret jazyka Python3
- nainštalovať framework Flask
- spustiť aplikáciu z príkazového riadka tak aby počúvala na určenom porte.
- pomocou webového prehliadača vykonať požiadavku a zobraziť výsledok.
To si vyžaduje vykonanie viacerých príkazov aby sa aplikácia dostala do požadovaného stavu. Napr. ak máme k dispozícii OS Linux typu Debian alebo Ubuntu:
Tento postup funguje len na Ununtu 20.04
sudo apt-get update
# Ak treba, nainštalujeme balíček virtualenv
sudo apt-get install python3-virtualenv
# Vytvorime si virtualne prostredie
python3 -m virtualenv ./venv
# Aktivujeme si virtualne prostredie
source ./venv/bin/activate
# Nainstalujeme do virtualneho prostredia
pip install flask
# Nakonfigurujeme aplikaciu
export FLASK_APP=app.py
# Spustime aplikaciu
flask run --host=0.0.0.0
Príprava Docker obrazu
Ak chceme takúto aplikáciu distribuovať, musíme sa pripraviť na rôzne situácie a zabezpečiť aby boli splnené všetky závislosti - nainštalovaný Python a nainštalované potrebné knižnice. Postup na splnenie závislostí sa odlišuje podľa toho aké prostredie používame - bude iný na prostredí Windows, iný na rôznych prostrediach Linux.
Aby sme si to uľahčili, pripravíme si Docker obraz s aplikáciou aj všetkými závislosťami.
Docker obraz sa skladá z viacerých vrstiev. Na najnižšej úrovni sa nachádzajú súbory operačného systému a nad tým sú aplikácie. Nová vrstva vždy prekryje starú. Vrstvenie obrazov nám umožní ľahko modifikovať už existujúce obrazy bez toho aby sme museli robiť všetko nanovo.
Nový Docker obraz vytvoríme pomocou príkazov docker
. Podľa inštrukcií v špeciálnom súbore Dockerfile
zoberieme existujúci obraz, modifikujeme ho, zostavíme a uložíme v lokálnom registri.
Dockerfile
Výsledný obraz s aplikáciou je opísaný v súbore Dockerfile
. Skladá sa zo sady inštrukcií pre zostavenie obrazu. Inštrukcie v Dockerfile
nám umožňujú ľahko opakovať a modifikovať proces zostavenia aplikácie.
Výhodnou je, že pri vytváraní nových obrazov môžme využiť už existujúce obrazy. Obraz bude obsahovať operačný systém, potrebné knižnice a iné závislosti. Nemusíme začať úplne od začiatku, ale využijeme existujúci obraz s nainštalovaným interpreterom Python.
Do Dockerfile
zapíšeme tieto inštrukcie:
# Základný obraz z Docker Hub
# Fungujúca inštalácia Alpine Linux s nainštalovaným interpreterom Python
# Výhodou je malá veľkosť
FROM python:3.8-alpine
# Nastavenie pracovného adresára kontajnera
WORKDIR /app
# Virtuálne prostredie nie je potrebné
# Inštalácia závislostí aplikácie priamo do systému
RUN pip install flask
# Kopírovanie súborov aplikácie do obrazu
COPY ./app.py /app
# Nastavenie premennej prostredia
ENV FLASK_APP app.py
# Program na spustenie
ENTRYPOINT ["flask"]
# Argumenty
CMD ["run", "--host", "0.0.0.0"]
# V kontajneri sa spustí flask vo vývojovom režime takto:
# flask run --host 0.0.0.0
Príkaz ENTRYPOINT
je meno príkazu ktorý sa má vykonať. CMD
je zoznam východiskových argumentov pre príkaz.
Zostavenie obrazu
V aktuálnom adresári by sa mali nachádzať dva súbory:
app.py
Dockerfile
Keď máme hotové inštrukcie Dockerfile
, pokúsme sa zostaviť obraz:
docker build -t flaskapp:dev .
Bodka na konci znamená miesto kde sa má hľadať Dockerfile, teda aktuálny adresár.
Argument -t
(tag) určuje meno obrazu v registri. Časť pred dvojbodkou je názov obrazu. Časť za dvojbodkou je verzia obrazu.
Overme si, že nový obraz je v zozname lokálne dostupných obrazov:
docker images ls
Spustenie vlastného kontajnera
Ak je obraz pripravený v zozname dostupných obrazov, môžeme vytvoriť nový kontajner:
docker run -it --rm flaskapp:dev
Docker zoberie obraz a podľa inštrukcií v ENTRYPOINT
a CMD
spustí aplikáciu.
Podmienky spustenia (názov program, argumenty, premenné prostredia a iné) definované v obraze je možné meniť počas spustenia
docker run
zadaním ďalších argumentov.
ENV ENTRYPOINT CMD
| | |
v v v
docker run -it --rm -e PREMENNA=ahoj -p 8081:5000 --entrypoint echo flaskapp:dev ahoj svet
Poznámka:
v niektorých obrazoch je ako ENTRYPOINT
uvedený takýto shell skript:
#!/bin/bash
set -e
# Ak je prvý argument meno aplikácie
if [ "$1" = 'postgres' ]; then
# Urobím nejakú konfiguráciu
exec gosu postgres "$@"
fi
# Inak vykonám argumenty ako shell príkaz
exec "$@"
V tom prípade pri spustení pomocou docker run
nemusíme meniť parameter--entrypoint
, lebo celý príkaz na spustenie sa načíta z argumentov CMD
.
Viac o tom aký je rozdiel medzi CMD
, ENTRYPOINT
a RUN
.
Konfigurácia aplikácie pomocou premenných prostredia
Upravte zdrojový text aplikácie tak, aby bral do úvahy Vami definovanú premennú prostredia.
Ak je definovaná premenná MY_NAME
, tak aplikácia pekne pozdraví podľa nakonfigurovaného mena.
Inak pozdraví nášho kamaráta Ferka.
Zdrojový text aplikácie: app.py
import os
from flask import Flask
from datetime import date
app = Flask(__name__)
@app.route("/")
def hello():
name = "Ferko"
if "MY_NAME" in os.environ:
name = os.environ["MY_NAME"]
return "<h1 style='color:blue'>Hello There {}!</h1>".format(name)
@app.route("/date")
def date():
today = date.today()
return "<p>{}</p>".format(today.strftime("%d.%m.%Y"))
if __name__ == "__main__":
app.run()
Vytvorte nový obraz s vylepšenou aplikáciou.
Premennú prostredia je možné nastaviť tesne pred spustením kontajnera:
docker run -it --rm -e MY_NAME=Daniel flaskapp:dev
Beh aplikácie pripravenej v obraze je možné modifikovať aj argumentmi príkazového riadka.
Ak chceme získať pomoc v klasickom príkazovom riadku, napíšeme:
flask --help
V našom obraze to bude:
docker run -it --rm -e MY_NAME=Daniel flaskapp:dev --help
Argumenty na poslednom mieste nahradia argumenty zadané pomocou CMD
.
Na to aby sme namiesto aplikácie flask
spustili príkazový riadok, použite parameter --entrypoint
,
ktorým prekryjete inštrukcie v Dockerfile
.
docker run -it --rm --entrypoint /bin/sh flaskapp:dev
Domáca úloha
Vymyslite aplikáciu ktorá bude obsahovať počítadlo prístupov.
Podarí sa Vám zistiť a zaznamenať aj typ prehliadača?