Folytatjuk az utunk az előző részben indított HTTPD Docker konténer után, de már saját Docker image-et is készítünk. Ez az image még egy nagyon egyszerű megoldás lesz a koncepció megértéséhez, ami még nem a végleges, éles környezetre szánt verzió, de innentől nagyon jó úton fogunk haladni afelé. Ez nem jelenti azt, hogy ne lehetne élesben is alkalmazni a leírtakat, de a legtöbb esetben ez még nem elég. Ha viszont egy statikus oldalad van, vagy egy állapotmentes alkalmazásod (pl. webes számológép, konvertáló alkalmazás), esetleg egy demo alkalmazásod, ami nem igényel konfigurációt sem, akkor már ezzel is el tudod készíteni.
Tartalomjegyzék
- Dockerfile
- Image készítése
- Konfiguráció ellenőrzése
- Konténer saját image-ből Docker Compose-zal
- Image build Docker Compose-zal
- Végszó
Dockerfile
[Tartalom]
Ahhoz, hogy Docker image-ünk legyen, először is egy "Dockerfile" nevű fájlt kell létrehozni, aminek a tartalma leírja majd a készítendő Docker image felépítését. Ebben a fájlban a legfontosabb, kötelező elem a "FROM" kulcsszó használata. Ez után adjuk meg, hogy mi az az image, amire a saját image-ünket alapozzuk, tehát ez lesz az ős vagy szülő image. Minden változtatásunk ehhez képest értendő majd. A mi szülő image-ünk a "httpd:2.4"
Már ezt is lehetne buildelni, de ennek még nincs sok értelme, mivel ez még csak egy álnevet rendelne változattás nélkül az eredet image-hez. A konfigurációs fájlokat szeretném bemásolni, amit a COPY utasítással lehet megtenni. Első paraméter a hoszt rendszerről bemásolandó fájl útvonala, a második pedig, hogy a konténerben hova szeretnénk másolni a fájlt vagy mappát.
Minden esetben a felmásolt útvonal automatikusan létrejön, ha még nem létezett a konténerben.
Mappa másolása esetén ez azt jelenti, hogy a célkönyvtár már az a mappa, ami a felmásolandó mappa tartalmát kell, hogy átvegye, tehát nem a megadott útvonalon belül fog létrejönni a felmásolt mappa.
Fájl esetén viszont, ha létező fájl útvonalát adjuk meg célként, akkor egyszerűen csak felülírja a fájlt. Ha viszont a konténerben nem létező útvonalat adunk meg, akkor létrejön egy új fájl, de ekkor nem mindegy, hogy a cél útonal per jellel végződik-e vagy sem. Amennyiben per jellel végződik, az egy mappa útvonalaként lesz értelmezve, és ebben a mappában jön létre a felmásolandó fájl olyan néven, ahogyan a hoszton el lett nevezve. Ha nem per jellel végződik, akkor az fájl útvonalaként lesz értelmezve, és így tetszőleges néven is be lehet másolni a konténerbe fájlokat.
A COPY-val a konfigurációs fájlok és virtuális hosztok forráskódjának felmásolása így néz ki:
COPY ./httpd.conf /usr/local/apache2/conf
COPY ./httpd-vhosts.conf /usr/local/apache2/conf/extra
COPY ./vhosts /var/vhosts
Image készítése
[Tartalom]
Most már lehet készíteni a buildet az alábbi paranccsal:
A -t
után a létrehozandó Docker image neve áll, majd pedig a kontextus, amire hamarosan kitérek. A kimenet pedig a következőhöz hasonló:
Step 1/4 : FROM httpd:2.4
---> 464fdc577ef4
Step 2/4 : COPY ./httpd.conf /usr/local/apache2/conf
---> a4f931d31b9e
Step 3/4 : COPY ./httpd-vhosts.conf /usr/local/apache2/conf/extra
---> d044ffa2537c
Step 4/4 : COPY vhosts /var/vhosts
---> 8f83cbf6af41
Successfully built 8f83cbf6af41
Successfully tagged localhost/httpd-vhosts:latest
Itt az első sor szerint a Docker elküldött a Docker démonnak 43.62MB adatot, mint "build context". A helyzet az, hogy a Docker kliens és a szerver nem feltétlenül kell, hogy ugyanazon a gépen legyen. Még ha egy gépen is van mindkettő, a Docker build folyamata az, hogy
- A kliens feltérképezi a kontextusként megjelölt mappát,
- annak tartalmát egy TAR archívumba helyezi,
- amit elküld a szervernek, ahol a démon van,
- majd a szerveren megtörténik a build.
Az alábbi ábra bemutatja a kontextus útját a kliens és a szerver között:
Emiatt fontos figyelni arra, hogy ne legyen a kontextusban olyan, felesleges, nagy méretű, vagy érzékeny adatokat tartalmazó fájl, amire nincs szükség a build-hez. Ha nem lehet a projekt könyvtárból ezeket eltávolítani, akkor a .dockerignore
nevű fájlban fel kell sorolni azokat a fájlokat, mappákat, amiket nem szeretnénk, ha a kontextusba belekerülne. A .dockerignore
részletes magyarázata már nem fér bele a cikkbe, de több módon is meg lehet adni a kivételeket, ezért érdemes kicsit jobban is utánanézni, ha még nem annyira ismerős. Én a Docker Compose-t pythonnal telepítettem egy Python virtual environmentben, aminek a mappája teszi ki a 43 megabájt nagy részét, így én ezt adom meg kivételként:
Ha most újrabuildelek, egy kicsit más lesz a kimenet:
Step 1/4 : FROM httpd:2.4
---> 464fdc577ef4
Step 2/4 : COPY ./httpd.conf /usr/local/apache2/conf
---> Using cache
---> a4f931d31b9e
Step 3/4 : COPY ./httpd-vhosts.conf /usr/local/apache2/conf/extra
---> Using cache
---> d044ffa2537c
Step 4/4 : COPY vhosts /var/vhosts
---> Using cache
---> 8f83cbf6af41
Successfully built 8f83cbf6af41
Successfully tagged localhost/httpd-vhosts:latest
Először is a kontextus már csak 107 kilobájt, más részt a 2. lépéstől minden lépésben megjelenik a "Using cache" felirat. Az image-ek rétegekből épülnek fel és minden COPY utasítás hatására egy újabb réteg jön létre, ami külön elmenthető cache-be, megosztható Docker image-ek között (helytakarékosság), és gyorsítható a build azáltal, hogy ami utasítás ugyanazt a réteget hozná létre, azt nem futtatja le ismét, csak a már elkészült eredményt használja újra a Docker. Márpedig az előző build alkalmával ezek a rétegek elkészültek.
Konfiguráció ellenőrzése
[Tartalom]
Használat előtt, főleg, amíg csak ismerkedsz a Dockerrel és nagyobb eséllyel csúszik be egy-egy hiba, érdemes manuálisan is leellenőrizni, hogy a build után tényleg minden fájl bekerült-e a konténerbe. Ehhez nem feltétlenül kell belépni a konténerbe, de néha kényelmesebb lehet, ezért indítsunk egy teszt konténert az alábbi módon egy interaktív bash parancs indításával:
A --rm
miatt a konténer törlődik is, amint a kilépés után leáll, a -it
miatt pedig egy interaktív terminálunk is lesz, ami a bash miatt szükséges most.
FIGYELEM: a -it
elején szándékos az egy darab kötőjel. Ez ugyanis a "-i
" és "-t
" flagek összevonása.
Miután a fájlok nevei létező fájlok felülírásánál nem bizonyítékok, megnézhetjük a létrehozás idejét vagy a fájl tartalmát. A httpd.conf
esetén azt tudjuk, hogy a httpd-vhosts.conf
fájlt betöltő sor elején nem lehet kettőskereszt, mivel azt kivettük már a saját konfigurációs fájlban. Ezt a sort pedig az alábbi parancs megmutatja:
Kimenet:
Ha minden oké, akkor exit
-tel kilépek, és már csak az indítás módján kell változtatni a docker-compose.yml
fájlban.
Konténer saját image-ből Docker Compose-zal
[Tartalom]
Emlékeztetőül a jelenlegi docker-compose.yml
így néz ki:
services:
httpd:
image: httpd:2.4
network_mode: host
volumes:
- type: bind
source: ./vhosts
target: /var/vhosts
- type: bind
source: ./httpd.conf
target: /usr/local/apache2/conf/httpd.conf
- type: bind
source: ./httpd-vhosts.conf
target: /usr/local/apache2/conf/extra/httpd-vhosts.conf
Ebben már nem kellenek a volume-ok, és az image neve is változik. Az új fájl tartalma tehát már csak ennyi lesz:
services:
httpd:
image: localhost/httpd-vhosts
network_mode: host
A network_mode: host
sorra még szükség van. Ezt nem adhatjuk meg az Dockerfile-ban. Ezután pedig már lehet indítani a Docker Compose-zal a konténert és az sem számít, hogy fut-e még az előző verzió vagy sem, mert a Docker Compose gondoskodik a régi verzió törléséről és az új elindításáról. Ezen a ponton viszont, aki velem telepítette az előző részben a Docker Compose-t, most aktiválni kell a python virtuális environmentet:
Majd indítás:
Image build Docker Compose-zal
[Tartalom]
Hogy ne kelljen minden alkalommal fejlesztés közben is külön build parancsokat futtatni, rábízhatjuk a Docker Compose-ra az image készítését. Ekkor nem kell image nevet átadnunk, mert a Docker Compose a konténerek elnevezéséhez hasonló módon az image-hez is rendel egy, a projekt nevétől függő image nevet, ami a "httpd-vhosts" nevű projekt mappa esetén alapértelmezetten "httpd-vhosts_httpd". A buildhez az új docker-compose.yml
így néz ki:
services:
httpd:
build:
context: .
dockerfile: Dockerfile
network_mode: host
A build
blokkon belül a context
a már ismert kontextus útvonalát adja, míg a dockerfile
segítségével tetszőleges leíró fájlt is megadhatnánk a Docker image-hez. Ezt a docker parancsnak is megadhattuk volna a -f
paraméterrel, de elhagyása esetén úgyis ezt a nevet fogja keresni a docker
és a docker-compose
parancs is. A YAML fájlban viszont kicsit lehetünk bőbeszédűbbek, ha szükséges, mert talán jobban áttekinthető, mint egy shell szkript a rövidített paraméternevekkel. A build pedig most ugyanazzal a paranccsal történik, amivel az indítás is történt:
A kimenet a build más ismert kimenetén kívül még az alábbi:
Creating httpd-vhosts_httpd_1 ... done
A warning csak első alkalommal lesz kiírva, hogy értesítsen arról, hogyan lehet később a builden módosítani, ugyanis nem fogja minden alkalommal lefuttatni, amennyiben létezik már olyan nevű image, amit létrehozna. Még akkor sem, ha a Dockerfile tartalma változott, ezért lehetne újra buildelni. Ha ezen a működésen változtatni szeretnél, akkor az alábbi paranccsal futtasd a konténert, ami a cache használata miatt csak kis mértékben fogja lassítani a konténer indítását:
Végszó
[Tartalom]
Mindez tehát még nem a végleges megoldásnak szánt verzió, de ahogy a bevezetőben írtam, így is vannak olyan egyszerűbb esetek, amikor teljesen nyugodtan alkalmazhatók a leírtak élesben is. Virtuális hosztok teljes tartalmát viszont általában nem szokás egy image-be bemásolni. Időről-időre egyre több virtuális hosztra lehet szükség, az image mérete nagyon megnőhet, a build idő lelassul és az alkalmazások Dockeren keresztül paraméterezése egyre kezelhetetlenebb lesz. Paraméterezésről nem volt szó, ezért egyelőre csak bízz bennem, hogy így van, és kövesd az oldalt Facebookon és/vagy Youtube-on, hogy ne maradj le a folytatásról.
Ha tetszett a cikk, kérlek, kattints a "like" gombra és továbbra is várom a kommenteket, észrevételeket bármilyen felületen.