A PodSpace, mint platform szolgáltatás arra való, hogy a forráskódból gyorsan és egyszerűen állítsunk össze működőképes futtatókörnyezetet. Az sem árt, ha mindezt megismételhetően és automatizálhatóan tesszük, így könnyen automatizálhatóvá válik a teljes fejlesztési folyamat. Ebben a cikkben egy Laravel alapú PHP alkalmazás példáján keresztül megnézzük, hogyan lehet forráskódból futtatható Docker image-et előállítani, és mellé rakni egy szintén Docker alapú adatbázis szervert.
A példánkban a quickstart-intermediate
Laravel minta-alkalmazás forráskódját fogjuk használni,
ami egy egyszerű feladatlista kezelő alkalmazás, felhasználói regisztrációval és
autentikációval. Az alkalmazás működéséről részletes leírás található a
Laravel dokumentációjában,
forráskódja megtalálható a GitHub-on.
Ezt az alkalmazást fogjuk telepíteni a PodSpace beépített PHP 5.6-os futtatókörnyezetébe, a
webes menedzsment konzol használatával.
A forráskód
Az alkalmazásunk forráskódja a GitHub-on van, a Laravel csoport alatti quickstart-intermediate repóban.
Ezen a repón egy apró konfigurációs változtatást kell eszközöljünk ahhoz, hogy tökéletesen
működjön PodSpace alatt: mivel a PHP alkalmazáskörnyezetben a DocumentRoot
a telepített GIT repó
gyökérkönyvtára lesz, ezért egy megfelelően kialakított .htaccess
fájlt kell elhelyezni a repóban,
ami átirányítja a kéréseket a Laravel alkalmazás belépési pontjára a public
könyvtárba.
Ha az olvasónak nincs GitHub-os accountja, vagy csak kihagyná ezt a lépést, akkor használja az alábbi,
PodSpace-es quickstart-intermediate repository-t a következő lépésekben:
https://github.com/podspace/quickstart-intermediate
Ebben a repóban már elvégeztük a szükséges beállítást.
|
Ehhez nincs más dolgunk, mint bejelentkezni a GitHub-ra, és a quickstart-intermediate
repót forkolni
a "Fork" gomb megnyomásával, majd a saját accountunk alatt lévő, forkolt repóban létrehozni egy új, .htaccess
nevű fájlt, a következő tartalommal:
<IfModule mod_rewrite.c> RewriteEngine on RewriteRule ^$ public/ [L] RewriteRule (.*) public/$1 [L] </IfModule>
Ezt is megtehetjük a GitHub webes felületén a "Create new file" gombra való kattintással, majd miután bemásoltuk a fájl tartalmát, az oldal alján lévő "Commit new file" gombbal menthetjük a változtatásokat.
Azért is célszerű saját GitHub accountról végigmenni ezen a tutorialon, mert a végén megnézzük, hogy hogyan lehet az automatikus buildelést és kihelyezést beállítani: amint módosítunk valamit a repón, a PodSpace automatikusan előállít az alkalmazásunkból egy új Docker image-et. Ez nem csak GitHub-bal működik, de a GitHub-on csak akkor tudjuk beállítani, ha regisztrált felhasználók vagyunk. |
Projekt és alkalmazás létrehozása
Miután készen áll a forráskód, hozzunk létre egy projektet a PodSpace-ben: jelentkezzünk be a webes menedzsment konzolon, és kattintsunk az "Új Projekt" gombra, majd adjunk nevet a projektünknek:

A következő lépésben az "Új alkalmazás" képernyőn válasszuk ki a php:5.6
futtatókörnyezetet, majd
adjunk egy nevet az alkalmazásnak (pl.: laravel), és adjuk meg azt a GitHub repository-t, amiben az
elvégeztük a módosításokat.

Kattintsunk a "Létrehozás" gombra, majd menjünk tovább az áttekintő képernyőhöz. Ezen a ponton a rendszer
megkezdi az alkalmazás forráskódjából egy futtatható Docker image előállítását - ez első alkalommal 2-3 percig
is eltarthat, a Napló megjelenítése
linkre kattintva nyomon követhetjük a haladást.

Ezen a ponton az ún. S2I eljárással készül el a forráskódból a futtatható Docker image. Azt, hogy ez pontosan hogyan történik, azt a futtatókörnyezetet is tartalmazó ún. builder image (esetünkben az alkalmazás létrehozásakor kiválasztott _php:5.6) határozza meg, ami maga is egy Docker image, és mint ilyen, a felhasználó által tetszőlegesen testreszabható. Ha egy alapból nem támogatott programozási nyelvet, vagy futtatókörnyezetet akarunk használni, akkor mi magunk is viszonylag egyszerűen összeállíthatunk egy ilyen builder image-et. Tulajdonképpen a PodSpace-ben a futtatókörnyezeteket is ugyanúgy tudjuk buildelni, mint az alkalmazásokat. |
Miután a build lefutott, az alkalmazás automatikusan elindul egy példányban. Az apps.podspace.hu
végződésű
linkre kattintva meg is jelenik a kezdőképernyő.

Közben körbenézhetünk a menedzsment felületen: kilistázhatjuk a futó podokat (a pod a PodSpace-ben a Docker konténert jelenti), megnézhetjük a naplóit, beléphetünk a konténer parancssori felületére, stb. Illetve skálázhatjuk az alkalmazásunkat: az Áttekintés képernyőn a fel / le nyilakra való kattintással további példányokat indíthatunk az alkalmazásból. A PodSpace terheléselosztói automatikusan elosztják az alkalmazásra érkező forgalmat a különböző példányok között.
Adatbázis létrehozása
Az alkalmazásunkat tehát lefordítottuk, és telepítettük. De nincs hozzá adatbázis szerverünk, és ha megpróbálunk valamilyen értelmes műveletet az alkalmazáson (pl. regisztrálás vagy bejelentkezés), akkor látni is fogjuk hogy nem működik az adatbázis hiánya miatt.
Telepítsünk hozzá egy adatbázist! Kattintsunk az Új alkalmazás gombra a menedzsment felületen, és válasszuk ki az oldal aljáról a mysql-ephemeral adatbázist. Az adatbázis létrehozásakor a felhasználónevet, a jelszót és az adatbázis nevet töltsük ki az itt láthatóhoz hasonlóan:

Majd kattintsunk a Létrehozás gombra. Az áttekintő képernyőn láthatjuk, hogy megjelent egy újabb alkalmazás:

De honnan fogja tudni a PHP-s alkalmazásunk, hogy ehhez az adatbázishoz csatlakozzon. A válasz egyszerű: a PodSpace a mysql alkalmazáshoz létrehozott egy mysql nevű szolgáltatást, amitől a projekten belül futó összes másik pod eléri a mysql szervert a mysql hosztnéven keresztül. Vagyis csak azt kell beállítani a Laravel-ben, hogy a mysql hoszton futó adatbázishoz csatlakozzon, azzal a felhasználónév és jelszó párossal amit a mysql létrehozásakor megadtunk.
Ha az alkalmazás forráskódjában megvizsgáljuk a config/database.php
fájl tartalmát, akkor látni fogjuk, hogy
az adatbázis elérhetősége környezeti változók definiálásával megadható:

Annyi a dolgunk tehát, hogy beállítsuk a DB_HOST
, DB_DATABASE
, DB_USERNAME
és DB_PASSWORD
környezeti változók értékét a laravel alkalmazásban. A környezeti változókat definiálhatjuk build
szinten, illetve deployment szinten is. Mi most build szinten fogjuk definiálni - ez azt jelenti, hogy
a létrejött Docker image-ben már beállításra kerülnek.
Ehhez navigáljunk a laravel build config kezdőképernyőjére a menedzsment konzolon (Tallózás / Buildek / laravel), és a Műveletek gomb alatt válasszuk ki a Szerkesztés opciót. A megjelenő űrlap alján vegyük fel a négy környezeti változónkat azzal az értékkel, amiket a mysql alkalmazás létrehozásakor is megadtunk, valahogy így:

Majd kattintsunk a Mentés gombra, és a következő képernyőn a Build indítás gombra. Ezzel elindítunk egy új buildet ami 1-2 perc alatt végrehajtódik, és a végén az előállt Docker image alapján létre is jönnek az új podok (ezt a folyamatot a PodSpace-ben deployment-nek nevezik).
Ha most újra megnyitjuk az alkalmazást, és megpróbálunk regisztrálni, akkor továbbra is hibát fogunk kapni. De már nem azért, mert nem tud csatlakozni az adatbázis szerverhez, hanem azért, mert nem léteznek azok az adatbázis táblák, amiket használna.
Ez várható is volt, hiszen jelenleg üres az adatbázis: végre kell hajtsunk egy adatbázis migrációt ahhoz,
hogy a Laravel inicializálja az adatbázist. Ehhez az áttekintő képernyőn kattintsunk a laravel alkalmazás
kék karikájába a podok listájához, majd kattintsunk egy tetszőleges podra (valószínűleg csak egy futó podunk lesz,
hacsak nem skáláztuk az alkalmazást a nyilakkal). A pod kezdőlapján pedig válasszuk ki a Konzol fület,
és adjuk ki a php artisan migrate
parancsot:

Ha ez sikeresen lefutott, az azt jelenti, hogy tudott csatlakozni az adatbázishoz, és létre is hozta a szükséges táblákat. Ettől kezdve már ténylegesen használható az alkalmazás. Próbáljuk ki!

Automatikus adatbázis migrációk
Azt láttuk, hogy a konténerből manuálisan végre tudjuk hajtani a migrációt, de ez nem túl elegáns: nem szeretjük a manuális folyamatokat. A PodSpace-ben - ha csak egy logikai környezettel dolgozunk, mint ebben a példában - a verziókihelyezés folyamata az alábbi módon történik:

A fejlesztő módosítja a forráskódot, majd bepusholja a GIT repóba, aminek hatására elindul egy Build. A build végén előáll egy Docker image, ami bekerül a registry-be, és ekkor elindul egy új deployment. A deployment során a régi verziójú image-et futtató podok leállnak, és elindulnak az új verziójú image-ek.
A deployment egy intelligens folyamat. Például, ha felskáláztuk több példányra az alkalmazást, akkor beállíthatjuk, hogy egyesével állítsa le és indítsa újra az egyes példányokat, így leállás nélkül végrehajtva a verziókihelyezést. De ha olyan a változtatás, hogy csak leállással lehetséges, akkor azt is megadhatjuk, hogy állítsa le egyszerre az összes példányt. |
Mi azt szeretnénk, ha az adatbázis migráció automatikusan megtörténne akkor, amikor lefordult az új alkalmazás, és folyamatban van az új verzió kihelyezése. Ezt a DeploymentConfig módosításával tehetjük meg. Az admin felületen válasszuk ki a Tallózás / Deploymentek menüpontot, majd a laravel deploymentet kiválasztva kattintsunk a jobb felső sarokban a Műveletek / Yaml szerkesztése opcióra.
A megjelenő ablakban YAML formátumban szerkeszthetjük a DeploymentConfig-ot. Írjunk be egy pre blokkot a rollingParams attríbutum alá, az alábbi tartalommal:
strategy: type: Rolling rollingParams: pre: failurePolicy: Retry execNewPod: containerName: laravel command: [ "php", "artisan", "migrate" ]
Figyeljünk az indentációra! A végeredmény valahogy így nézzen ki:

Ellenőrzésképpen nyomjuk meg a Deploy gombot - ha minden jól csináltunk, akkor a deployment sikerülni fog. Mivel az adatbázis szerverünk alatt nincs perzisztens tárhely, ezért ha leállítjuk és újraindítjuk azt, akkor az adattáblák is törlődni fognak. Egy új deployment végrehajtására azonban a migráció újra-inicializálja az adatbázist.
Az egyszerűség kedvéért ebben a leírásban nem raktunk perzisztens tárhelyet az adatbázis alá. A perzisztens tárhely használatát a Redmine telepítéséről szóló leírásban bemutattuk, annak beállítását - szükség esetén - az olvasóra bízzuk. Jelenleg nincs szükségünk perzisztens tárhelyre az adatbázis szerver alatt. |
Automatikus fordítás és kihelyezés
Végezetül még egy dolog van hátra ahhoz hogy igazán automatizálttá tegyük ezt az egyszerű fejlesztői környezetünket: beállíthatjuk, hogy a PodSpace Git repóban történő változás esetén automatikusan fordítsa le és deployolja az alkalmazást.
Ehhez nincs más dolgunk, mint a GitHub-on beállítani egy ún. webhook-ot. Ehhez nyissuk meg a repository
oldalát a GitHub-on (ez az a lépés, amit csak akkor tudunk elvégezni, ha Fork-oltuk a quickstart-intermediate
repót a cikk elején leírt módon), navigáljunk a Settings / Webhooks & services lapra, és ott kattintsunk
az Add webhook gombra.
Az egyszerűség kedvéért a GitHub-ot használva mutatjuk be ezt a funkcionalitást, de természetesen bármilyen más Git repository használható, sőt, a PodSpace-en mi magunk is telepíthetünk egy saját Git repository-t és dolgozhatunk abban is. |
A webhook beállításakor meg kell adnunk egy Payload URL-t. Ezt a PodSpace előállította számunkra, csak annyi a dolgunk, hogy az admin konzolon a Tallózás opció alatt megkeressük a laravel buildet, és ott a Beállítások lapon megjelenik a webhook URL:

Ezt az URL-t másoljuk ki és adjuk meg a GitHub webhook létrehozásakor, mint Payload URL. A többi mezőt hagyjuk üresen, és kattintsunk az Add webhook gombra.
Meg is vagyunk! Próbáljuk ki: módosítsunk valamit a repóban, és git push
után autmatikusan elindul
a PodSpace-ben egy új build, végrehajtódik az adatbázis migráció és elindul az új verzió.
Konklúzió
Ezen tutorial során létrehoztunk egy olyan alkalmazáskörnyezetet, amiben:
-
Forráskódból automatikusan futtatható Docker image-et állítottunk elő a felhőben
-
A létrejött image-eket deployoltuk a felhőben
-
Új verzió kihelyezésekor automatikus adatbázis migrációt hajtottunk végre
Mindezt úgy, hogy a forráskód módosítása esetén a fenti folyamat automatikusan végrehajtódik. Tulajdonképpen ez még csak egy nagyon rövid ízelítő a PodSpace képességeiből - de már nagyjából láthatjuk, hogy milyen építőelemeink vannak az alkalmazáskörnyezetek összeállítására, és ezek hogyan működnek együtt.
A való életben persze ennél jóval összetetteb folyamatokra van szükség: egy igazi continuous delivery stratégia megvalósításához az itt bemutatott elveket ki kell terjeszteni úgy, hogy több logikai alkalmazáskörnyezetet (úgy mint: fejlesztői, teszt, éles, stb.) lefedve, és azok közt automatikus átmeneteket végrehajtva képes legyen a rendszer arra, hogy bármelyik változtatást automatikusan és leállásmentesen kihelyezze az éles környezetre, ha az átment az automatizált teszteken.
A PodSpace erre mind képes, ráadásul egy olyan Docker alapú platform fölött valósítja ezt meg, amiben a futtatókörnyezeteink fölött teljes kontrollunk van, vagy akár mi magunk is létrehozhatunk tetszőleges futtatókörnyezetet az alkalmazásaink számára.