Kötetek kezelése

A Docker kötetei lehetővé teszik a konténerekben előállított adatok tárolását vagy megosztását az egyes konténerek között. A Docker több, különböző típusú kötet kezelésére képes, amelyek függetlenek is lehetnek a konténerek életciklusától is. A fő cél a konténer adatainak megőrzése abban az esetben is, ha a konténert újraindítják vagy törlik. A kötetek használata különösen fontos adatbázisok, konfigurációs fájlok és egyéb perzisztens adatok kezelésekor. Ebben a fejezetben megismerkedünk a Docker kötetek létrehozásának, csatolásának és kezelésének módjaival, valamint alkalmazzuk azt a módszert, mellyel a konténer és a host rendszer közös adatkönyvtárakat használhat. A fejezet tartalma:

  • Docker kötetek fogalma, létrehozásuk és törlésük.

  • Kötetek csatolása konténerekhez.

  • Kötetek használata az az adatok megőrzésére.

  • Egy kötet jellemzőinek lekérdezése.

  • Nevesített és névtelen kötetek.

  • Megosztott mappák.

  • Gyakorlati példák és jógyakorlatok megismerése.

Szükséges eszközök:

Windows, MacOS vagy Linux operációs rendszerű számítógép, telepített Docker szoftverrel.

Feldolgozási idő:

kb. 2 óra, a gyakorlati feladatok megoldására további 2 óra.

Az eddig látott példákban talán nem hangsúlyoztuk ki eléggé, hogy a konténer példányok egy „felépített egészet” alkotnak, azaz minden tartalmi változás, amely a működésük során a belső fájlrendszerükben történik, az a host rendszerben nem látható, és a konténer példány törlésével (és újraépítésével is) elvész. Többek közt ezért szokás egy már felépített konténert annak újraépítése helyett a docker start paranccsal újra használni, nem pedig egy újabb példányt építeni a docker run-nal.

Ez a működési mód egyaránt lehet előny és hátrány is. Kifejezetten hasznos pl. akkor, ha a konténer egy komponense, pl. a benne futó webszerver valamilyen sérülékenységben érintett. Egy ilyen esetben a sikeres támadás után a helyreállításhoz elég a konténert újraépíteni, és abban minden újra egy sikeres támadás előtti (igaz, továbbra is sérülékeny) állapotában lesz, így el lehet végezni a sérülékenység elhárítását úgy, hogy a konténert a sérülékenységet már nem tartalmazó, javított változattal építjük újra. Hangsúlyozom: a sérülékenység megszüntetése a konténer újraépítésével történik, amely annak belső fájlrendszerére is vonatkozik, a folyamat során az is újraépül, így az abban esetleg tárolt adatokat nem fogja tartalmazni.

Ez a működési mód viszont súlyos adatvesztés forrása is lehet: ha pl. egy konténerben egy olyan webalkalmazás fut, amelybe a felhasználók fájlokat töltenek fel, abban adatokat rögzítenek, azok az adott konténer példány fájlrendszerében vannak, így annak újraépítése után elvesznek. A Docker e probléma megoldására a köteteket és a megosztott mappákat kínálja, ezeket viszont a konténer indítás során specifikálni kell.

A kötetek (pontosabban az ún. névvel ellátott kötetek) a Docker saját kezelésű, egy erre szolgáló könyvtárban elhelyezett fájljai, melyekre azok logikai nevével lehet hivatkozni. Működésük leginkább a virtualizáció során megismert virtuális merevlemezhez hasonlít.

Egy másik megoldás a megosztott mappa használata. Ez a konténer példány és az azt futtató operációs rendszer által közösen használt könyvtárat jelent – a működésük szinte teljes egészében megegyezik a virtualizáció során használt megosztott mappákéval. Ezek a mappák közvetlenül elérhetők a konténer és a host operációs rendszere számára is, ezért velük jelentősen egyszerűsíthető a konténerre alapozott fejlesztés és az adatcsere folyamata is.

A kötetek

A kötetek a gyakorlatban tehát olyan speciális fájlok, amelyeket a konténer belső fájlrendszerének egy könyvtárába csatolunk fel. A kötet tehát a konténer meghatározott belső könyvtárához kapcsolódik, azon keresztül, abba belépve érhető el. A csatolási pontként megadott könyvtár tartalma (fájlok, könyvtárak stb.) már a kötetben kerül tárolásra. A mechanizmus szinte pontosan úgy működik, ahogyan azt a Unix mount mechanizmusánál már láttuk.

Az alábbi példában egy konténerben futó alkalmazás az adatait a /data könyvtárban tárolja. A bal oldali szerkezetben ezek az adatok a konténer saját, belső fájlrendszerében helyezkednek el, így a konténer „eldobásakor” az abban tárolt tartalom is elvész. A jobb oldali felépítésben a dataVolume nevű, külső, statikus kötetet a /data könyvtárhoz csatoltuk, eltakarva ezzel a könyvtár eredeti tartalmát. Ezzel minden, a /data könyvtárban végzett fájlművelet ebben a külső kötetben történik. Maga a konténer ezzel eldobhatóvá válik, hiszen annak adattartalmát a kötet őrzi, ha pedig azt újra kell építeni, a konténer a kötet tartalmát ugyanúgy el tudja majd érni.

Kötet csatolása a konténerhez

Kötet csatolása a konténerhez

Megjegyzés

Egy konténer-edukált :-) fejlesztőnek tehát gondolnia kell arra, hogy az alkalmazásában keletkező adatokat lehetőleg egy könyvtárból kiindulva strukturálja. Ha az alkalmazás az adatait szétszórva, más-más könyvtárban tárolja, a „konténeresítése” nehézkes lesz, mert a megőrzésükhöz megannyi kötetre lesz szükség. Ha azonban a fenti példában látható könyvtárrendszert tovább gondoljuk, és a tárolandó adatokat a /data könyvtáron belül, esetleg további könyvtárakba szervezve tároljuk, akkor egyetlen külső kötet elég lesz az alkalmazás működtetéséhez.

Hogyan működik ez a gyakorlatban? A kötetetek kezelésére néhány egyszerű parancs szolgál, melyek szintaxisa jól illeszkedik az eddig látott logikához.

Egy kötet létrehozása a docker volume create paranccsal történik, amelynek paraméterként meg kell adni a létrehozandó kötet nevét (ez példánkban dataVolume). A kötetek listázását a docker volume ls parancs végzi, amely kimenetében nem csak a rendszerben levő kötetek nevei, hanem a DRIVER oszlopban az azokat kezelő driverek is láthatók (ez példáinkban mindig local lesz).

root@columbo.uni-eszterhazy.hu:~#  docker volume create dataVolume
data

root@columbo.uni-eszterhazy.hu:~#  docker volume ls
DRIVER    VOLUME NAME
local     dataVolume

Egy kötet konténerhez rendelését a konténer indításakor lehet elvégezni, amelyhez egy további paramétert kell megadni. A -v (volume) kapcsolót követően kettősponttal elválasztva kell megadni a kötet nevét és a konténer belsejében levő csatolási könyvtárat. Amennyiben a célkönyvtár nem létezne a konténerben, a csatoláskor azt a Docker automatikusan létrehozza.

Az alábbi példában egy ubuntu:16.04 image-t töltünk le, és interaktív terminál módban készítünk belőle egy konténer példányt. A létrejövő konténer neve ubuntu-16.04 lesz, ennek indulását követően a /bin/bash programname kell elindulnia. A konténer /data könyvtárához hozzákapcsoljuk az imént létrehozott dataVolume kötetet. (Egy alap Ubuntu Linuxban ugyan nincs /data könyvtár, de ahogyan már említettem, a Docker automatikusan létrehozza azt.)

Az indítást követően a konténerben levő shell indul el, és a parancsaink a konténeren belül hajtódnak végre. Amikor az mkdir paranccsal létrehozunk egy hello nevű könyvtárat a /data könyvtárban, az már nem a konténerben, hanem az ahhoz csatolt dataVolume kötetben helyezkedik el.

root@columbo.uni-eszterhazy.hu:~#  docker run -it --name ubuntu-16.04 -v dataVolume:/data ubuntu:16.04 /bin/bash
root@7a464f5947ba:/# ls /data
root@7a464f5947ba:/# mkdir /data/hello
root@7a464f5947ba:/# ls -l /data
total 4
drwxr-xr-x 2 root root 4096 Jan 26 07:12 hello
root@7a464f5947ba:/# exit
exit

Az eredményről meggyőződhetünk, ha a konténer leállítása és eldobása után ugyanezzel a paranccsal létrehozunk egy új, másik példányt, majd ellenőrizzük a /data könyvtár tartalmát: abban ott szerepel majd a hello könyvtár.

Egy kötettel kapcsolatos további információk a docker volume inspect paranccsal kérdezhetők le, amelynek kötelező paramétere a vizsgálandó kötet neve. A parancs kimenetében többek közt leolvasható a kötet létrehozásának dátuma és ideje, valamint a kötetfájl pontos helye (ez Linuxon általában a /var/lib/docker/volumes). Utóbbi értékes információ lehet akkor, amikor a rendszerben tárolt kötetetek biztonsági mentését szeretnénk elvégezni – ugyanakkor érdemes tudni, hogy túl azon, hogy a Docker dokumentációja nem garantálja az ilyen típusú mentések teljességét, nem mellesleg egy ilyen mentés konzisztenciája erősen megkérdőjelezhető, ha a mentést egy működő rendszer során végzik.

root@columbo.uni-eszterhazy.hu:~#  docker volume inspect dataVolume
 [
     {
         "CreatedAt": "2024-01-26T07:02:25Z",
         "Driver": "local",
         "Labels": null,
         "Mountpoint": "/var/lib/docker/volumes/dataVolume/_data",
         "Name": "dataVolume",
         "Options": null,
         "Scope": "local"
     }
 ]

Végül, egy szükségtelenné vált kötetet törölni a docker volume rm paranccsal lehet, amelynek szintén kötelező paramétere a törlendő kötet neve.

root@columbo.uni-eszterhazy.hu:~#  docker volume rm dataVolume
dataVolume
root@columbo.uni-eszterhazy.hu:~#  docker volume ls
DRIVER    VOLUME NAME

Megjegyzés

  • A teljesség kedvéért érdemes megemlíteni a fizikai partíciók csatolhatóságát is, ehhez a -v eszközfile:csatolási_pont formát kell alkalmazni pl. így: -v /dev/sdc1:/data. Fizikai partíciók csatolása azonban a konténerek gyakorlatában nem igazán jellemző.

Névtelen kötetek

A konténerek működésének biztosítására egy másik kötet típus, az ún. névtelen kötetek is alkalmazhatók. Ha egy kötet létrehozásakor name adjuk meg a használni kívánt kötet fájl nevét pl. így: docker run -v /mnt ubuntu, azaz csak a belső csatolási pontot határozzuk meg, akkor a Docker automatikusan létrehoz egy új kötetet, de annak neve ismeretlen marad. A docker volume ls parancs szerencsére ezeket is felsorolja, a docker volume prune pedig törli azokat, amelyeket nem használ egyetlen konténer sem. Az alábbi folyamat egy névtelen kötet alkalmazására mutat példát:

root@columbo.uni-eszterhazy.hu:~#  docker run --name ubnt -v /mnt ubuntu
Unable to find image 'ubuntu:latest' locally
latest: Pulling from library/ubuntu
29202e855b20: Pull complete
Digest: sha256:e6173d4dc55e76b87c4af8db8821b1feae4146dd47341e4d431118c7dd060a74
Status: Downloaded newer image for ubuntu:latest
root@columbo.uni-eszterhazy.hu:~#  docker volume ls
DRIVER    VOLUME NAME
local     afd316ee6cfec4a726373731e825bdf21a1126bb074724cac79482cb9e310e70
root@columbo.uni-eszterhazy.hu:~#  docker rm ubnt
ubnt
root@columbo.uni-eszterhazy.hu:~#  docker volume prune
WARNING! This will remove anonymous local volumes not used by at least one container.
Are you sure you want to continue? [y/N] y
Deleted Volumes:
afd316ee6cfec4a726373731e825bdf21a1126bb074724cac79482cb9e310e70

A névtelen kötetek azonosítása nehézkes, a használhatóságuk korlátozott, emellett nem túl sok olyan esetet sorolhatnánk fel, amikor a névvel hivatkozható köteteteket célszerű lenne ezzel helyettesíteni.

Megosztott mappák

Egy megosztott mappa csatolása a kötetekkel ellentétben egy olyan mappa csatolását jelenti, amely a host fájlrendszerében helyezkedik el. Ez a Unixok esetében gyakran bind mount-nak is nevezik. Egy ilyen összerendelés során a meghatározott könyvtár tartalma tehát a konténeren kívül, a valódi fájlrendszerben helyezkedik el, annak tárolása a konténertől függetlenül történik, így az „túléli” a teljes újraépítés folyamatát is.

A megosztott mappák alkalmazása kifejezetten ideális a fejlesztési folyamat során, egy webalkalmazás fejlesztésekor a futtatási környezet (pl. az Apache-Php) a konténerbe zárva folyamatosan működik, míg a web forráskódja azon kívül található, és a megszokott fájlműveletekkel módosítható.

Egy megosztott mappa hozzárendelésekor szükséges parancs tulajdonképpen alig különbözik az eddig látottaktól, ugyanúgy a -v kapcsolót kell megadni, a különbség csupán annyi, hogy az összerendeléshez most a host és a konténer belsejében levő könyvtár párt kell meghatározni, pl. így: -v webroot:/var/www/html. Ebből következően nem lehet olyan könyvtárat bind mountolni, amellyel megegyező volume már létezik a rendszerben – ezt érdemes szem előtt tartani mind a könyvtár nevek, mint a kötet nevek megválasztásakor.

A megosztott mappák alkalmazását két, a gyakorlatban is jól hasznosítható példán keresztül nézzük meg. Az első egy olyan webszerver lesz, amit statikus weboldalak fejlesztési környezeteként használhatsz, a második pedig egy konténerben futó mySQL adatbáziskezelő rendszer.

Gyakorlat: webszerver

Feladat. Készítsünk egy olyan konténert, amely egy webszervert biztosít statikus website-ok készítéséhez!

Számos webszerver létezik, ebben a példában az egyik „kult” változatot, az nginx (ejtsd: endzsinex) fogjuk használni. (A szerver üzemeltetők közt nem ritkák az érzelmekkel tarkított kocsmai viták arról, hogy az Apache vagy az Nginx a jobb.) Első lépésben ismerkedjünk meg az nginx-szel, hozzunk létre egy konténer példányt belőle, majd második lépésben módosítsuk úgy, hogy az fejlesztési környezetként is használható legyen! A konténer indítását az alábbi módon végezzük:

macbook:~$ docker run --name webserver -p 5001:80 nginx
Unable to find image 'nginx:latest' locally
latest: Pulling from library/nginx
a5573528b1f0: Pull complete
8897d65c8417: Pull complete
fbc138d1d206: Pull complete
06f386eb9182: Pull complete
aeb2f3db77c3: Pull complete
64fb762834ec: Pull complete
e5a7e61f6ff4: Pull complete
Digest: sha256:4c0fdaa8b6341bfdeca5f18f7837462c80cff90527ee35ef185571e1c327beac
Status: Downloaded newer image for nginx:latest
.
.
.
2024/01/27 06:22:30 [notice] 1#1: start worker process 33
2024/01/27 06:22:30 [notice] 1#1: start worker process 34
2024/01/27 06:22:30 [notice] 1#1: start worker process 35
2024/01/27 06:22:30 [notice] 1#1: start worker process 36

A konténerben levő webszerver a 80-as belső tcp porton kommunikál, amit a gazdagép 5001-es, feltehetően még nem használt portjával kapcsolunk össze. Így a webszerverünk eléréséhez a böngésző címsorába a saját gépünk IP címét, vagy a localhost nevet és az 5001-es portot kell begépelni: http://localhost:5001. Ha mindent jól csináltunk, megjelenik az nginx alap weboldala.

Az Nginx

Az Nginx alapoldala a konténerből

A webszerver telepítése ennyi munkát igényelt, de ez ebben a formájában nem felel meg az igényeinknek, mert a weboldalak „gyökérkönyvtára” most még a konténer belsejében, az /usr/share/nginx/html könyvtárban van, a webszerver minden esetben az itt található index.html fájl tartalmát jeleníti meg. (Hogy honnan tudtam ezt? A DockerHubon, a nginx leírásából derítettem ki itt: https://hub.docker.com/_/nginx), de ezt az nginx adminisztrátorai egyébként hamar megtanulják.

A konténer akkor lenne számunkra igazán hasznos, ha ezt a fejlesztői könyvtárunkkal tudnánk összekötni, amit egy megosztott mappa tehetne lehetővé. Ahhoz, hogy kipróbálhassuk, először állítsuk le ezt a konténer példányt a Ctrl-C megnyomásával, majd dobjuk el a docker rm webserver paranccsal.

macbook:~$ docker rm webserver
ae

Most hozzunk létre egy fejlesztési könyvtárat a web projektünk számára, majd kapcsoljuk össze azt a konténerünk /usr/share/nginx/html könyvtárával! Így a webszerver mindig az ott található webtartalmat jeleníti meg! Sajnos egy megkötéssel is szembesülnünk kell: itt mindig a könyvtárak abszolút elérési útját kell megadni, ami a gyakorlatban okoz némi kellemetlenséget, leginkább azért, mert a fejlesztéskor használt könyvtár helye minden bizonnyal eltér a végső, a szolgáltató szerverén levőétől. Vigaszul szolgáljon, hogy mivel kifejezetten szerencsétlen megoldás lenne a forrás könyvtár helyének abszolút megadása, segítségül hívhatjuk az operációs rendszer beépített változóit. Azt használjuk ki, hogy Unixok esetében az $PWD, Windowsban a %CD% nevű környezeti változók tartalmazzák az aktuális könyvtár elérési útját – a megadáshoz ezeket így fogjuk felhasználni:

macbook:~$ mkdir dev
macbook:~$ docker run --name webserver -p 5001:80 -v $PWD/dev:/usr/share/nginx/html nginx

Az eredmény ellenőrzéséhez a kedvenc text editorunkkal nyissuk meg a dev könyvtár tartalmát, és készítsünk ott egy rövid index.html fájlt:

<!DOCTYPE html>
<html lang="hu">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Web project</title>
</head>
<body>
    <h1>Lorem, ipsum.</h1>
    <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ducimus, debitis!</p>
</body>
</html>

A böngésző tartalmát az F5 billentyűvel frissítve meg is jelenik az új tartalom:

Statikus weboldal a konténerből.

Statikus weboldal a konténerből.

Azt, hogy az oldalakat valóban a konténerünk szolgálja ki, a konténer ablakában megjelenő, az oldalak lekéréseit tartalmazó log üzenetek bizonyítják (a logokról még részletesen lesz szó az A konténerek üzeneteinek naplózása c. fejezetben). Az alábbi példában olvashatók a http kérés részletei:

172.17.0.1 - - [28/Jan/2024:07:05:48 +0000] "GET / HTTP/1.1" 200 375 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.2.1 Safari/605.1.15" "-"

Mit is kínál ez az igazán egyszerű környezet? Az így kifejlesztett website-odat a munka végeztével becsomagolhatod a konténerbe (hogy miként, arról hamarosan, a Saját konténer készítése c. fejezetben lesz szó) és az futásképes lesz akár a nagy felhőszolgáltatók, akár egy kis konténerszolgáltató szerverén abban a formában, ahogyan azt összeraktad. Az így létrehozott csomag pedig a kiszolgáló operációs rendszerétől vagy beállításaitól függetlenül működik pontosan úgy, ahogyan azt a gépeden tette. A csomag elküldésekor csak annyit kell mondanod: „itt ez a konténer a webszerverrel és a weblapokkal, a 80-as belső porton fogadja a kéréseket, üzemeld be.”, és minden működni fog. A technológiát alkalmazva nincs szükség arra, hogy a fejlesztői gépen egy webszervert tarts, csupán projektenként, a fejlesztés idejére kell majd létrehoznod egyet-egyet, amit a munka befejeztével egyszerűen eldobhatsz.

Megjegyzés

Az elkészített webszerverünk nem php-képes, csak statikus html fájlokat tud kiszolgálni. A php-hoz a konténert módosítani kell, nem beszélve arról, hogy később valószínűleg valamilyen adatbáziskezelő-rendszerre is szükséged lesz. A végső fejlesztői környezetet, amely több konténer együtteséből áll majd, a Több konténer együttese c. fejezetben alakítjuk ki. Jelenlegi példáink olyan részfeladatok, amelyeket majd ott még használni fogunk.

Gyakorlat: adatbázis szerver

Feladat: Készítsük el egy mySQL szerver helyi gépen, konténerben futó változatát!

A megoldás gondolatmenete azonos lesz az nginx-nél már látottal, az adatbázis fájlokat itt sem a konténer belsejében, hanem attól függetlenül, a fizikai fájlrendszerben fogjuk tárolni. Ehhez tudnunk kell, hogy a mySQL esetében ez a /var/lib/mysql könyvtár lesz. A webszerverhez hasonlóan, ezt az információt vagy a mySQL dokumentációjából, vagy a DockerHubon, a mySql leírásából lehet megszerezni.

macbook:~$ docker run --name mydbserver -p 3306:3306 -v $PWD/mysqldata:/var/lib/mysql mysql
Unable to find image 'mysql:latest' locally
latest: Pulling from library/mysql
6988ac25ab22: Pull complete
...
2024-01-27 07:05:37+00:00 [ERROR] [Entrypoint]: Database is uninitialized and password option is not specified
    You need to specify one of the following as an environment variable:
    - MYSQL_ROOT_PASSWORD
    - MYSQL_ALLOW_EMPTY_PASSWORD
    - MYSQL_RANDOM_ROOT_PASSWORD

Ha a konténert a szokásos módon indítjuk, sajnos hibaüzenetet kaptunk, ami (ha jobban belegondolunk) természetes, hiszen az új adatbáziskezelőnk számára valahogyan meg kellett volna határoznunk a kezelt adatbázis nevét és hozzáférési paramétereit is. Ezeket az operációs rendszer környezeti változóival lehet megtenni, a példában a szükséges változók neveit a hibaüzenet végén fel is sorolta a program. A paraméter átadás itt elvárt módszerét érdemes megjegyezni, mert ez általánosan alkalmazott megoldás a konténerek paraméterezéséhez.

Ezen a ponton két megoldás közül választhatunk. Az elsőben az adatbáziskezelőhöz tartozó root jelszót adjuk meg, amellyel bejelentkezve további felhasználók és adatbázisok hozhatók létre. A másikban, mivel a gyakorlatban általában egy konkrét adatbázisra van szükségünk, melynek eléréséhez egy felhasználó név és jelszó páros szükséges, konkrétan ezeket adjuk meg.

A környezeti változókat a -e paraméterrel lehet megadni az alábbi parancsban látható formában. Indítsunk most egy mySql konténert úgy, hogy az a szokásos 3306-os porton legyen elérhető, a root felhasználó jelszava pedig legyen nai7Iej7!

macbook:~$ docker run --name mydbserver -p 3306:3306 -v $PWD/mysqldata:/var/lib/mysql -e MYSQL_ROOT_PASSWORD="nai7Iej7" mysql
(Hosszas kimenet)

Megjegyzés

A mySql indításakor használhatók lettek volna a MYSQL_ALLOW_EMPTY_PASSWORD és a MYSQL_RANDOM_ROOT_PASSWORD környezeti változók is. Az előbbi „yes” (igazából bármilyen nem üres) értéke esetén az adatbáziskezelő root felhasználójának üres jelszava van (ezt soha ne tegyük), utóbbi pedig a konténer indulásakor generál egy kellően biztonságos jelszót, amit egy alkalommal, az indításkor jelenít meg, ekkor lesz alkalmunk azt memorizálni.

Ehhez a mySql szerverhez már kapcsolódhatunk pl. a DBeaver vagy mySQL Workbench programmal pl. az alábbi ábrán látható beállításokkal:

Kapcsolódás a mySQL szerverhez

Kapcsolódás a mySQL szerverhez

Lássuk azt a megoldást, amelyben rögtön létrehozunk egy fejlesztéshez szükséges adatbázist és beállítjuk a hozzáférését is! Először állítsuk le és dobjuk el a jelenlegi konténert:

macbook:~$ docker stop mydbserver
mydbserver
macbook:~$ docker rm mydbserver
mydbserver

Most állítsuk be a hozzáférési adatokat! Ha ezt az adatbázis létrehozásával felépítés során akarjuk megadni, további környezeti változóknak kell értéket adni. A MYSQL_DATABASE a létrehozandó új, üres adatbázis nevét, a MYSQL_USER az ehhez szükséges hozzáférés felhasználói nevét, a MYSQL_PASSWORD pedig a jelszót specifikálja. A root jelszavára most igazából nem lesz szükségünk, ezért azt véletlen értékre állítjuk be, így a MYSQL_RANDOM_ROOT_PASSWORD értéke "yes" lesz.

macbook:~$ docker run --name mydbserver -p 3306:3306 -v $PWD/mysqldata:/var/lib/mysql -e MYSQL_RANDOM_ROOT_PASSWORD="yes" -e MYSQL_DATABASE="webdb" -e MYSQL_USER="dbuser" -e MYSQL_PASSWORD="naih23thah" mysql
(Hosszas kimenet)

Mivel az adatbázis fájlok a konténeren kívül, a mysqldata könyvtárban jöttek létre, a konténert bármikor leállíthatjuk és eldobhatjuk, az adatbázis fájljaira ez már nincs hatással:

 macbook:~$ ls mysqldata/
 total 177128
 -rw-r-----    1 koczka.ferenc  staff    196608 Jan 27 18:36 #ib_16384_0.dblwr
 -rw-r-----    1 koczka.ferenc  staff   8585216 Jan 27 18:33 #ib_16384_1.dblwr
 drwxr-x---   34 koczka.ferenc  staff      1088 Jan 27 18:34 #innodb_redo
 drwxr-x---    2 koczka.ferenc  staff        64 Jan 27 18:57 #innodb_temp
 -rw-r-----    1 koczka.ferenc  staff        56 Jan 27 18:33 auto.cnf
 -rw-r-----    1 koczka.ferenc  staff   3040246 Jan 27 18:33 binlog.000001
 -rw-r-----    1 koczka.ferenc  staff       181 Jan 27 18:57 binlog.000002
 -rw-r-----    1 koczka.ferenc  staff        32 Jan 27 18:34 binlog.index
 -rw-------    1 koczka.ferenc  staff      1680 Jan 27 18:33 ca-key.pem
 -rw-r--r--    1 koczka.ferenc  staff      1108 Jan 27 18:33 ca.pem
 ...

Összefoglalás

Ebben a fejezetben a konténerek kötetkezelését ismertük meg, – ezek olyan adatterületek, amelyeket a konténeren kívül, az azt futtató operációs rendszerben helyezkednek el. A kötetek elsődleges célja azoknak az adatoknak a megőrzése, amelyek a konténer működése során keletkeznek, és amelyeket a konténer eldobása és újraépítése után is meg kell őrizni. Tipikus példáink a webalkalmazásba feltöltött fájlokról, és egy adatbáziskezelő-rendszer nyers adatfájljainak elhelyezéséről szóltak. A Docker számos, különböző típusú kötet kezelésére képes, a két legfontosabb a közös használatú mappa és a névtelen kötetek voltak. Míg az utóbbi egy olyan speciális, felmountolt virtuális diszkként működő fájl, amit csak a Dockeren belül lehet egyszerűen kezelni, a megosztott mappák tartalma a konténeren kívül is elérhető, így alkalmazása egyszerűbb, és ezért a gyakorlatban talán könnyebben is kezelhető.

Feladatok

  1. Készíts egy mySql konténert úgy, hogy az indulásakor létrehozott adatbázisban készítsen egy táblát és töltse fel azt néhány rekorddal! (Segítség: a mySql konténer az első indításakor automatikusan lefuttatja az konténer belsejében levő /docker-entrypoint-initdb.d/init.sql fájlt.)

  2. Készíts egy konténert, amely a ugyanezt a feladatot egy PostgreSql adatbáziskezelő-rendszerrel oldja meg!

  3. Készíts egy konténert, melyben egy PHP webalkalmazás egy SQLite3 adatbázissal működik. Gondoskodj róla, hogy az adatbázis a konténer újraépítésekor is épségben megmaradjon!