Dockeri alused
Selles peatükis teeme praktilise sissejuhatuse konteineritesse ja Dockeri põhimõistetesse.
Loogika
Docker võimaldab käivitada tarkvara eraldatud keskkonnas nii, et sama image annaks võimalikult sarnase tulemuse eri masinates. See on seotud arenduskeskkonna, paketihalduse ja serveritööga.
Oluline on kohe alguses eristada:
venvhoiab lahus Pythoni paketid- Docker hoiab lahus terve käivituskeskkonna
See on põhjus, miks Docker ei ole lihtsalt "suurem venv".
Põhimõtted
- image on valmis ehituskihiline pakend
- container on image'ist käivitatud protsess
- registry on koht, kust image'eid alla laadida
- port ühendab konteineri teenuse sinu masina pordiga
- volume või bind mount annab püsiva või jagatud failisüsteemi osa
Image, container, port ja volume
Need mõisted tasub võimalikult vara selgeks teha:
- image
- container
- port
- volume või bind mount
retseptist ehitatud valmis pakend
selle image'i põhjal käivitatud konkreetne protsess
viis, kuidas konteineri teenus nähtavaks teha hostmasinas
viis, kuidas andmeid püsivalt või jagatult kasutada
Lihtne võrdlus:
- image on nagu retsept või valmis pakend
- container on sellest tehtud päris jooksutatud eksemplar
Sa võid ühest image'ist käivitada mitu konteinerit.
Miks Docker üldse kasulik on
Docker lahendab teistsugust probleemi kui venv.
Kõige tavalisemad põhjused Dockeri kasutamiseks on:
- sama rakendus peab töötama eri masinates ühtemoodi
- projekt vajab lisaks Pythonile või Node'ile ka süsteemipakette
- rakendus käib koos teiste teenustega nagu Postgres, Redis või Nginx
- arendus, test ja tootmine peavad olema võimalikult sarnased
Lühidalt:
venvaitab küsimusega "millised Pythoni paketid siin on"- Docker aitab küsimusega "milline terve keskkond siin üldse jookseb"
Kiirspikker
docker pulltõmbab image'idocker runkäivitab konteineridocker psnäitab jooksvaid konteinereiddocker imagesnäitab image'eiddocker exec -itsiseneb konteinerissedocker logsnäitab konteineri väljundit
Kõige tavalisemad lipud
docker run --rmdocker run -itdocker exec -itdocker ps
Praktiliselt tähendavad need enamasti:
docker run --rmkustuta konteiner pärast lõpetamistdocker run -itinteraktiivne terminaldocker exec -itsisene töötavasse konteinerissedocker psvaata jooksvaid konteinereid
Kasulikud lisad:
docker logs konteinervaata konteineri väljunditdocker run -p 8000:8000ava port hostmasinassedocker run -v "$PWD":/appjaga kohalik kaust konteineriga
venv vs Docker
Hea otsustuspuu on:
- ainult Pythoni sõltuvused lähevad segamini:
venv - vajad kindlat Linuxi keskkonda või süsteemipakette: Docker
- vajad mitut teenust koos: Docker
- tahad ainult kiiret lokaalset Pythoni arendust:
venv
Näide, kus piisab venv-st:
- väike Pythoni skript
- üks CLI-tööriist
- andmetöötlusnotebook või väike teek
Näide, kus Docker on loomulikum:
- veebirakendus koos andmebaasiga
- projekt, mis vajab
postgresql-client,ffmpegvõi muud süsteemipaketti - tiimitöö, kus keskkonnad kipuvad masinate vahel erinema
Kas konteineris on vaja veel venv-i
Tavaliselt mitte.
Hea algreegel on:
- väljaspool Dockerit: kasuta projektis
venv-i - Dockeri sees: ära lisa
venv-i ainult harjumusest
Põhjus:
- konteiner juba isoleerib keskkonna
- üks rakendus ühes konteineris on tavaliselt piisavalt eraldatud
Seega on väga tavaline ja täiesti normaalne, et Dockerfile teeb lihtsalt:
FROM python:3.13-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install -r requirements.txt
COPY . .
CMD ["python", "app.py"]
Siin ei ole eraldi venv-i vaja, sest konteiner ise ongi eralduskiht.
Praktiline soovitus sinu jaoks
Kui hakkad Dockerit aktiivselt kasutama, siis üsna hea mõtteviis on:
- kohaliku puhta Pythoni arenduse jaoks kasuta
venv-i - kui projekt peab jooksma ühtemoodi eri masinates või vajab teenuseid, tee Docker
- ära pane lisaks konteinerisse
venv-i, kui sul ei ole selleks väga selget põhjust
See hoiab süsteemi lihtsana:
- arenduse ajal tead, kas oled
venv-s või konteineris - tootmise ja tiimitöö jaoks on keskkond ühtsem
- veaotsingus on vähem kihte, mida segamini ajada
Käivita need käsud
docker pull alpine
docker run --rm alpine echo tere
docker run -it --rm ubuntu bash
docker ps
docker images
Kõige väiksem arusaadav Dockerfile
Kui tahad Dockeri mõttest päriselt aru saada, siis kõige kasulikum on teha üks väga väike rakendus ja panna see image'isse.
Näiteks fail app.py:
print("Tere konteinerist")
Ja selle kõrvale Dockerfile:
FROM python:3.13-slim
WORKDIR /app
COPY app.py .
CMD ["python", "app.py"]
Siin toimub:
FROM python:3.13-slimvalib Pythoni baaskeskkonnaWORKDIR /appmäärab töökausta konteineri seesCOPY app.py .kopeerib faili image'isseCMD ["python", "app.py"]ütleb, mis käivitub konteineri startimisel
See on hea esimene näide, sest siin ei ole veel kõrvalist keerukust.
docker build ja docker run
Kui Dockerfile ja app.py on samas kaustas, siis:
docker build -t tere-rakendus .
docker run --rm tere-rakendus
Tulemus peaks olema umbes:
Tere konteinerist
Oluline loogika:
docker buildteeb image'idocker runkäivitab selle image'i põhjal konteineri--rmkustutab konteineri pärast lõpetamist
Kui tahad konteinerisse sisse vaadata, on abiks:
docker run -it --rm python:3.13-slim bash
See on hea viis vaadata, milline keskkond konteineri sees päriselt on.
Portide avamine
Kui konteineri sees jookseb veebiserver, siis ei piisa ainult sellest, et protsess töötab. Sageli on vaja port hostmasinasse edasi anda.
Näide:
docker run --rm -p 8000:8000 python:3.13-slim python -m http.server 8000
Siin:
- konteineri sees kuulab server porti
8000 -p 8000:8000seob selle sinu masina pordiga8000
Pärast seda saad tavaliselt minna brauseris aadressile:
http://localhost:8000
Bind mount ja püsivad andmed
Kui tahad, et konteiner näeks sinu kohalikku kausta, on väga tavaline kasutada bind mount'i.
Näide:
docker run --rm -it -v "$PWD":/app -w /app python:3.13-slim bash
Siin:
-v "$PWD":/appjagab praeguse kausta konteinerisse-w /appteeb selle konteineri töökaustaks
See on arenduses väga kasulik, sest saad muuta faile hostmasinas ja näha neid kohe konteineris.
Kui räägitakse volume'itest, siis mõeldakse sageli kahte eri asja:
- bind mount: kindel hosti tee nagu
"$PWD":/app - named volume: Dockeri hallatav püsiv andmeala
Algajale on bind mount tavaliselt kõige lihtsam esimene samm.
Konteineris arendamine: mis jääb hosti ja mis jookseb konteineris
See on koht, kus Docker muutub päriselt arendustööriistaks, mitte ainult demo- või deploy-vahendiks.
Kõige olulisem loogika on:
- lähtekood ja Git ajalugu elavad tavaliselt hostmasina kaustas
- konteiner annab sellele koodile ühtse jooksutuskeskkonna
- muudatusi teed tavaliselt oma redaktoris või IDE-s
- rakendust käivitad, testid ja silud konteineri sees
Hea algreegel on:
- ära kirjuta olulist koodi "anonüümselt" ainult konteineri sees
- hoia projekt failidena oma kaustas ja jaga see kaust bind mount'iga konteinerile
Muidu võib juhtuda, et:
- konteiner kustub
- sisse kirjutatud failid kaovad
- sa ei saa hästi aru, mis on hostis ja mis oli ainult konteineri sees
Kõige lihtsam arendusvoog bind mount'iga
Kui sul on näiteks väike Pythoni projekt, siis väga praktiline esimene arendusvoog on:
docker run --rm -it -v "$PWD":/app -w /app python:3.13-slim bash
Selle loogika:
"$PWD":/appjagab sinu praeguse projekti kausta konteinerisse-w /appteeb selle konteineri töökaustaks- sa saad hostmasinas faile muuta ja konteiner näeb neid kohe
Näiteks:
python -m pip install -r requirements.txt
python app.py
pytest
See on hea siis, kui tahad:
- proovida sõltuvusi puhtas keskkonnas
- mitte solkida hostmasina Pythoni
- kontrollida, et projekt töötab ka mujal kui sinu enda masinas
Miks see erineb "docker build && docker run" töövoost
Neid kaht töövoogu tasub eristada:
docker build+docker run- bind mount'iga interaktiivne konteiner
hea siis, kui tahad kontrollida valmis image'it
hea siis, kui tahad aktiivselt arendada
Teisisõnu:
- valmis rakenduse proovimiseks ehitad image'i
- igapäevaseks arendamiseks tahad sageli, et kood oleks mount'iga kohe nähtav
Praktiline arendus docker compose abil
Kui projektis on rohkem kui üks teenus, muutub arenduses mugavaks docker compose.
Väga tüüpiline arenduskuju on:
compose.yaml
services:
app:
image: python:3.13-slim
working_dir: /app
volumes:
- .:/app
command: bash -lc "python -m pip install -r requirements.txt && python app.py"
ports:
- "8000:8000"
db:
image: postgres:16
environment:
POSTGRES_DB: opik
POSTGRES_USER: opik
POSTGRES_PASSWORD: opikpass
Selle mõte:
- kood elab hostmasinas
appteenus kasutab seda otse läbi mount'idbannab teise teenusena andmebaasi- kogu komplekti saad käivitada ühe käsuga
Tüüpilised arenduskäsud:
docker compose up
docker compose logs -f app
docker compose exec app bash
docker compose down
Need on arenduses väga tähtsad:
upkäivitab tööruumilogs -fnäitab jooksvaid logisidexeclubab töötavasse konteinerisse sisse minnadownpeatab komplekti
Mida konteineris teha ja mida mitte
Hea praktiline jaotus on:
- hostmasinas:
- konteineris:
muuda faile, tee Git commit'e, halda dokumentatsiooni
installi sõltuvusi, käivita rakendus, testi, silu keskkonda
See ei ole absoluutne reegel, aga algajale väga tervislik tööjaotus.
Eriline hoiatus:
- kui teed konteineri sees
git clone, lood uusi faile ja ei kasuta mount'i - siis töötad sisuliselt konteineri sisemises failisüsteemis
- see võib olla ajutine ja segadust tekitav
Kuidas konteineris arendust mõelda
Hea vaimne mudel on:
- hostmasin on sinu töölaud
- Git repo on päris "tõde"
- konteiner on vahetatav tööpink
Kui tööpink maha võtta ja uuesti püsti panna, peaksid olulised asjad alles olema:
- lähtekood
- konfiguratsioon
- andmed, mida tahtsid säilitada
See on põhjus, miks:
- kood pannakse tavaliselt mount'iga hostist sisse
- andmebaasi andmed pannakse volume'isse
- buildi- ja arenduskäsud kirjutatakse
Dockerfile-i võicompose.yaml-i
docker logs ja docker exec
Konteinerit ei pea alati kohe interaktiivselt käivitama, et aru saada, mis toimub.
Sageli piisab neist kahest käsust:
docker logs konteineri-nimi
docker exec -it konteineri-nimi bash
Loogika:
docker logsnäitab, mida protsess on kirjutanudstdout-i jastderr-idocker exec -itlubab sul töötavasse konteinerisse sisse minna
Need on veaotsingus ühed kõige kasulikumad käsud.
Kui rakendus vajab pakette
Siis lisandub tavaliselt requirements.txt.
Näide:
requirements.txt
requests==2.32.3
Dockerfile
FROM python:3.13-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY app.py .
CMD ["python", "app.py"]
Siin on oluline:
- Pythoni paketid lähevad image'i sisse
- konteineri sees ei ole vaja eraldi
venv-i - image ise on selle rakenduse eraldatud keskkond
Millal tuleb mängu docker compose
docker run sobib hästi ühe konteineri jaoks.
Kui aga projektis on mitu seotud teenust, näiteks:
- rakendus
- andmebaas
- vahemälu
siis muutub mugavamaks docker compose.
Hea mõtteviis on:
docker runon üksiku konteineri käivitaminedocker composeon mitme seotud teenuse kirjeldamine ühes failis
Lihtne docker compose näide: Python + Postgres
See on juba päris eluline näide, sest väga paljud rakendused ei jookse üksi, vaid koos andmebaasiga.
compose.yaml
services:
app:
build: .
command: python app.py
depends_on:
- db
environment:
POSTGRES_HOST: db
POSTGRES_DB: opik
POSTGRES_USER: opik
POSTGRES_PASSWORD: opikpass
db:
image: postgres:16
environment:
POSTGRES_DB: opik
POSTGRES_USER: opik
POSTGRES_PASSWORD: opikpass
Siin:
appon sinu Pythoni rakendusdbon Postgres- nimi
dbtoimib teenusevõrgus hostinimena depends_onütleb, et rakendus sõltub andmebaasikonteinerist
Käivitus:
docker compose up --build
Peatamine:
docker compose down
Oluline täpsustus:
depends_onaitab käivitusjärjekorraga- see ei tähenda automaatselt, et Postgres on juba päriselt valmis ühendusi vastu võtma
- päris projektis on sageli vaja ka "oota kuni DB on valmis" loogikat
Millal valida kumb
Kasuta:
docker run, kui tahad kiiresti testida üht image'it või üht käskudocker compose, kui projektis on mitu teenust
Hea rusikareegel on:
- üks konteiner:
docker run - rakendus + andmebaas + muud teenused:
docker compose
Seos arenduskonteineritega
Kui kasutad VS Code'i või mõnd muud IDE-d, võib sama loogika olla pakitud arenduskonteineri kujule.
Siis:
- Docker käivitab konteineri
- IDE ühendub sinna sisse
- sinu projektikaust mount'itakse tööruumina konteinerisse
See tähendab, et arenduskonteiner ei ole "teine asi" kui Docker. See on pigem Dockeri peal ehitatud arendusmugavuskiht.
Üks lihtne võrdlus
venv-ga töövoog:
python3 -m venv .venv
source .venv/bin/activate
python -m pip install requests
python app.py
Dockeri töövoog:
docker build -t minu-rakendus .
docker run --rm minu-rakendus
Esimesel juhul isoleerid Pythoni paketid.
Teisel juhul isoleerid kogu rakenduse käivituskeskkonna.
Praktiline soovitus alustamiseks
Kui hakkad Dockerit õppima või arendama, mine selles järjekorras:
- tee kõige väiksem
Dockerfile - õpi
docker build - õpi
docker run - alles siis mine
docker composejuurde
Nii püsib selge:
- mis on image
- mis on container
- millal vajad mitme teenuse haldust
Minitest
- Tõmba alla mõni väike image.
- Käivita konteiner, mis väljastab ühe rea.
- Selgita oma sõnadega image'i ja containeri vahet.
- Selgita ühe lausega, mis vahe on
venv-il ja Dockeril. - Kirjelda ühe lausega, millal kasutaksid
docker compose-i tavalisedocker runasemel.