Ebben a részben megnézzük, hogy hogyan lehet konténereket futtatni és mik azok a fontos kapcsolók amiket mindenképpen ismernünk kell.
Most indítsunk el egy ubuntu rendszert.
docker run -it ubuntu
Ha mindent jól csináltunk, akkor kaptunk is egy terminált, amibe linuxos parancsokat gépelhetünk. Először is nézzük meg, hogy milyen folyamatok futnak. Adjuk ki a ps
parancsot. Nem túl meglepő módon azt látjuk, hogy fut egy bash és a ps parancs.
Itt nem látunk minden futó process-t, úgyhogy futtassuk most le a ps -A
parancsot. Ez most minden futó processzt meg fog mutatni:
UPS… le is buktam, ugyanis a ps
és ps -A
parancs ugyanazt a két futó processzt mutatja, hisz nem egy virtuális gépünk van, hanem egy konténerünk. Amikor azt mondtam, hogy indítsunk el “egy ubuntu rendszert”, jó nagyot lódítottam, hisz itt csak egy bash shell-t indítottunk el, és azért látunk csak két processzt, mert csak ez a kettő fut. Egy bash shell és a benne elindított ps parancs.
Ok, de mi is az az -it
kapcsoló? Ezt a paramétert azért kellett megadni, hogy a docker kliens az alapértelmezett bemenetet (jelen esetben ez a billentyűzet) hozzákapcsolja a konténerben futó alkalmazáshoz. Amennyiben ezt nem tennénk meg, úgy nem tudnánk egy parancsot se begépelni.
Erre persze a legtöbb konténernél nem lesz szükségünk, hisz az vagy az interneten keresztül kommunikál, vagy a gépen található fájlokkal dolgozik. Nézzünk egy hasznos példát és indítsunk el egy Jupyter Notebook-ot. (Ez az eszköz egy webes Python tanuló, tanító és bemutató fejlesztői környezet, ha eddig nem ismerted érdemes megismerned, főleg, ha oktatásban dolgozol. Több image közül is választhatsz!)
docker run -p 8888:8888 -v jupyter/minimal-notebook
A -p
kapcsoló a host gép egy adott portját hozzáköti a konténer egy adott portjához. Az első 8888
-as értéket nyugodtan írd át, hisz ez mondja meg, hogy mely portot kell kinyitni a host gépen. Azért praktikus a 8888
érték használata, mert akkor a Jupyter Notebook által kiírt url kattintható és nem kell a benti és kinti portok fordításával bajlódni. A Jupyter ugyanis nem fogja tudni, hogy ő hol érhető el a hoston, csak azt tudja, hogy a konténeren belül a 8888
-as portra ül rá.
A linket a konténer által kiírt kiment végén láthatod és tartalmaz egy tokent, ami nélkül nem fogod tudni elérni a webes felületet.
A -p
kapcsolóval nem csak portot, hanem ip címet is megadhatunk. Amennyiben nem adunk meg, úgy a konténer a gépünk összes csatolójának ipcímén elérhető lesz. Amennyiben Docker Desktop-ot, vagy a WSL2-t használjuk, úgy a Docker motort futtató virtuális gép és a host gép portjai össze lesznek kötve, tehát pont ugyan olyan lesz, mintha Linuxon dolgoznánk. Amennyiben csak tesztelési, fejlesztési célból futtatjuk a konténert úgy érdemes még a helyi visszahurkolt (loopback) ip címet megadni: -p 127.0.0.1:8888:8888
. Ekkor csak a fejlesztői gépről lehet elérni a Notebook-ot, máshonnan nem. Amennyiben mindent jól csináltunk, akkor a böngészőben a következőt kell látnunk:
Ne feledjük el, hogy amíg fut a konténer meglesznek az adataink, azonban abban a pillanatban, hogy ez a konténer megáll, a fenti paranccsal egy új konténert fogunk elindítani, így az adatok elvesznek. Próbáljuk ki! Hozzunk létre egy teszt notebookot. A terminálba nyomjuk le a CTRL+C
billentyűkombinációt, majd a fenti paranccsal indítsunk el egy új konténert. A teszt netbook volt, nincs, eltűnt.
Ahhoz, hogy megőrizzük az adatokat el kell azokat menteni. Erre jó megoldás a Dockerben a Volume. A dockerben többfajta lehetőségünk van volume-okat csatolni egy konténerbe, mi most a “Bind mount” megoldást használjuk. Első körben hozzunk létre egy “work” nevű mappát:
mkdir work
Ezután adjuk ki a következő parancsot:
docker run -p 8888:8888 -v ${PWD}/work:/home/jovyan/work jupyter/minimal-notebook
Ekkor a Jupiter Notebook felületen lesz egy work nevű mappa. Minden itt létrehozott workbook elérhető lesz a következő futtatáskor is és ott lesznek a most létrehozott work könyvtárban. A -v
kapcsolónak relatív útvonalat nem lehet megadni, lévén nem a cli fogja elindítani a konténert, hanem a daemon. Ezért kell a ${PWD}
, mely az aktuális könyvtár teljes elérési útvonalát fogja behelyettesíteni az útvonalba. A kettőspont után a konténeren belüli útvonal szerepel, melyet a Jupyter dokumentációjában található meg.
Most már nyugodtan megállíthatjuk a konténert és indíthatunk helyett egy újat. Vagyis nem teljesen. Az adataink ugyan meglesznek, de a sok-sok futó, majd leállított konténer nem semmisül meg, azok foglalják a helyet a merevlemezen. Nézzük meg! Adjuk ki a docker ps -a|grep jupyter
parancsot. Itt láthatjuk az eddig futtatott összes konténert. Ezeket a docker rm [azonosító]
paranccsal tudjuk törölni, de csak akkor, ha nem fut. Ahhoz, hogy ne legyen ebből probléma adjuk hozzá a --rm
kapcsolót a fenti parancshoz:
docker run --rm -p 8888:8888 -v ${PWD}/work:/home/jovyan/work jupyter/minimal-notebook
Ettől fogva nem kell félnünk, hogy teleszemeteljük a merevlemezünket, mivel amint megáll a konténer a Docker le fogja azt törölni.
Most már csak azt kell megoldanunk, hogy a Jupyter a háttérben fusson. Adjuk hozzá a -d
kapcsolót, mely leválasztja (detach) a konténerünket a shell-ről, így az képes lesz a háttérben futni. A -d
kapcsolót én mindig együtt használom a –name kapcsolóval, ami elnevezi a konténert és ezen túl ezzel a névvel fogok tudni rá hivatkozni, nem kell az azonosítóját keresgetnem. Adjuk ki a következő parancsot:
docker run -d --name jupyter --rm -p 8888:8888 -v ${PWD}/work:/home/jovyan/work jupyter/minimal-notebook
A docker ilyenkor csak a konténer azonosítóját írja ki, a konténer kimenetét nem. Ez most probléma, hisz nekünk szükségünk lesz az azonosító tokent tartalmazó linkre, különben nem fogjuk tudni használni a Jupytert. Nézzük meg, hogy hogyan tudjuk kiíratni a logokat. Adjuk ki a következő parancsot:
docker logs --tail 1 jupyter
A fenti parancsa a legutolsó logüzenetet írja ki, mely a szükséges linket tartalmazza. Vagy nem. Amennyiben nyitva van a böngészőben a korábbi Notebook, akkor csak egy hibaüzenetet látunk, mert ugye az a böngésző nem fog hozzáférni a régi tokennel. Ne essünk kétségbe. Zárjuk be a böngészőben a tabokat amelyeken nyitva van a Jupyter. Állítsuk meg a konténert a docker stop jupyter
paranccsal, majd indítsuk egy újat. Figyeljünk oda, hogy ha nem használtuk a --rm
kapcsolót - ami letörli a konténert, ha leállítjuk -, akkor ugyanolyan névvel nem fogunk tudni indítani konténert addig, amíg le nem töröltük azt.
Aki elég jól ismeri a jupytert, vagy elolvassa a dokumentációt az tudja, hogy a token értéket a JUPYTER_TOKEN nevű környezeti változóban is megadhatjuk. A docker run parancsnál a -e
kapcsoló szolgál arra, hogy környezeti változókat tudjunk megadni. Ekkor nem lesz szükségünk nézni logot a generált token kiderítése miatt, viszont ilyenkor érdemes csak a loopback 127.0.0.1 ip címre kiengedni az alkalmazásunkat. A végső parancs valahogy így fog kinézni:
docker run -d -e JUPYTER_TOKEN=jupyter --name jupyter --rm -p 127.0.0.1:8888:8888 -v ${PWD}/work:/home/jovyan/work jupyter/minimal-notebook
Ekkor a http://127.0.0.1:8888/?token=jupyter url-en érhetjük el a Notebook-ot.
Ne feledd! Amennyiben szeretnél fejlődni keress meg nyugodtan. Csoportos és személyes Docker oktatással és tanácsadással tudlak téged vagy csapatodat, cégedet támogatni.
A Docker gyorstalpaló cikksorozat részei
- Bevezetés - Docker gyorstalpaló
- Telepítés - Docker gyorstalpaló
- CLI avagy a parancssori értelmező - Docker gyorstalpaló
- Konténer futtatása - Docker gyorstalpaló
- Compose - Docker gyorstalpaló
- Stack futtatása - Docker gyorstalpaló
- Image készítése, Dockerfile - Docker gyorstalpaló
Borító Дмитрий Бирюков képe a Pixabay-en.