Legyünk őszinték: a konténerek komoly imázs-problémával küzdenek. A világkereskedelem nélkülözhetetlen kellékei, ám hasznos mivoltuk helyett mégis a kopott-rozsdás fém jut eszünkbe róluk, a pályaudvarok mellékvágányain rostokoló vasúti szerelvények, az autópályán 90-nel egymást előző kamionok, távol-keleti szállítmányozó cégek, esetleg bátran fölpakolt óriási teherszállító hajók. Schrödinger, a Nobel-díjas osztrák fizikus egyszer megpróbálkozott intellektuálisan izgalmassá varázsolni a konténereket, de a Princeton Egyetem szűkös büdzséjéből végül csak dobozra futotta, ezért elefánt helyett macskával illusztrálta a kvantumelmélet egyik leghíresebb (gondolat)kísérletét.

Az IT-alkalmazások fejlesztői és üzemeltetői számára mégis egyre szebben cseng a “konténer” szó az utóbbi években, és igyekszem közérthetően bemutatni, ez miért lehet.

Alkalmazást fejleszteni rengeteg nyűggel jár, üzemeltetni szintúgy. Szó sincs a fejlesztők szellemi restségéről, vagy lustaságáról, csak éppen ez egy folyamat, aminek során gondoskodni kell például többféle környezetről (fejlesztői környezet, tesztkörnyezet, éles környezet), különböző verziók kezeléséről, az alkalmazásunk által használt egyéb szoftverek (“függőségek”) meglétéről és korrekt verzióiról, az egymásra épülő modulok közötti hatékony hibakeresésről, skálázódásról, stb.

Mivel a virtuális gépek már elterjedtek, onnan már csak egy ugrás volt gondolatban, hogy az alkalmazásokat is lehetne virtualizálni. Ekkor nem egy operációs rendszert zárunk elkülönített konténerbe, hanem csak egy (vagy több) alkalmazást választunk le, és “dobozolunk be”.

Először egy konténeres futtatókörnyezetre van szükségünk, amit az operációs rendszer és az alkalmazásunk közé teszünk. Közismert és elterjed megoldás például a Docker.

Másodszor elkezdjük megépíteni az alkalmazást: egy “konténerbe pakoljuk” az első komponensét, továbbá az összes függőségét (beállításokat és modulokat, amikre szüksége van). Itt jön az első trükk: a Docker biztosít egy piacteret, ahol alkalmazás-lemezképeket lehet gyorsan, egyszerűen, és ingyenesen letölteni, majd pedig konténerben futtatni, mindössze néhány parancs begépelésével. (Fizetős megoldás is van, de ettől most tekintsünk el). Megvan a standardizált módja, hogy a szükséges beállításokat is elvégezzük, és paramétereket adjunk át. Nagyon gyorsan kiadható tehát, hogy “kérek egy Gunicorn webszervert, rajta X verziójú Python környezetet és Y verziójú Django keretrendszert, Z beállításokkal”. A Docker futtatókörnyezet fölmegy a lemezkép-piactérre, letölti a megfelelő alkalmazás-képet, és igény esetén rögtön el is indítja egy zárt konténerben. Figyelembe veszi a kért beállításokat, például, hogy a konténer melyik porton figyeljen a külvilág felé, hogyan lehet kapcsolódni hozzá.

Harmadszor: eljátsszuk ezt a folyamatot az alkalmazás összes komponensével, mindegyiket egy külön konténerbe rakjuk. A második konténer lehet például egy adatbázis, és ismét elég egy parancs: “kérek egy X verziójú PostgreSQL adatbázist, Y és Z paraméterekkel”. A Docker gondoskodik róla. Az alkalmazásunk különféle konténerei közös virtuális alhálózatot kapnak, tehát látják egymást, ám a külvilág csak azokon a portokon keresztül tud kapcsolódni hozzájuk, amiket kimondottan engedélyeztünk.

Negyedszer: finomhangoljuk az alkalmazást és a beállításokat. Rugalmasan be tudjuk állítani, milyen mértékig válasszuk szét a konténereket a valós környezettől; például az első konténerben futó Django alkalmazás forráskódját ne égessük bele a konténerbe, mert sűrűn változhat, ezért az adott mappa helyén a konténer inkább csak tekintsen ki a valós fájlrendszerre. Az adatbázis fájljait (adatok, logok, beállítások, stb.) is inkább a valós fájlrendszeren tároljuk, hogy egy verzióváltás esetén a konténert törölve és újra elkészítve az adataink mindenképp megmaradjanak.

A moduláris felépítésnek több előnye is van:

  • Minden konténer egyetlen célfeladatot lát el, teljesen áttekinthető a struktúra.
  • Igen egyszerű verziót váltani, hiszen minden konténer önálló építőkocka, és egyesével lehet cserélgetni.
  • A különböző komponensek beállításai nem akadnak össze, mindenki a sajátját látja.
  • A valós környezet annyit lát a futtatókörnyezet által menedzselt konténerből, amit előre beállítottunk, néhány portot mindössze.
  • Evidens módon teremthető meg a szinkron a fejlesztői rendszer, a tesztrendszer, és az éles rendszer között: ugyanazokat a konténereket futtatjuk majd, ezért a futó programok azonos környezetet látnak.
  • A futtatókörnyezet kezeli helyettünk a konténerek által generált logokat, egyszerű és átlátható módon.
  • Nem vagyunk annyira infrastruktúrához kötve, hiszen konténereinket szabadon (de a telepített szoftvereknél mindenképp szabadabban) költöztethetjük saját szervereinkről felhőbe, egyik felhő-szolgáltatótól pedig a másikhoz.
  • Az egész működést áthatja az a szemlélet, hogy...
    • a konténerek statikusak: sűrűn változó adatot nem égetünk beléjük, azt inkább a valós fájlrendszeren tároljuk, s összekötjük a konténerrel
    • és a konténerek rövid életűek: bármikor lelkifurdalás nélkül eldobjuk őket, és újraépítjük, pl. egy kisebb verzióváltás esetén, hiszen azonos beállításokkal úgyis hamar újra előállíthatjuk a korábban elmentett definíciós fájlok, és persze a remek piactér segítségével

Komplex és magas rendelkezésre állású alkalmazásoknál kihasználjuk, hogy skálázhatunk, ugyanaz az alkalmazás-lemezkép több példányban is futtatható, s így egyszerűbb a terheléselosztás, extra beállítások pedig nem szükségesek. A futtatókörnyezet akár a menedzsment-feladatokat is átveszi: a leállt konténereket újraindítja, a hibás konténerekre nem irányít forgalmat, vagy tartósabb hiba esetén törli és újra fölépíti őket. Nagyvállalati környezetben saját piacteret is építhetünk, ami zárt, elkülönül a publikustól, és cégünk munkatársai onnét tudják beszerezni a hivatalos, engedélyezett alkalmazás-lemezképeket, amit azután futtatnak.

Sok sikert!