A legegyszerűbb HTTPD Docker image elkészítése

LEGO keret kép felhasználásával a pixabay.com-ról AnnaliseArt felhasználótól docker image build felirat.

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

[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"

FROM 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:

FROM httpd:2.4

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:

docker build -t localhost/httpd-vhosts .

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ó:

Sending build context to Docker daemon  43.62MB
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:

Docker conttext útja

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:

httpd-vhosts-env

Ha most újrabuildelek, egy kicsit más lesz a kimenet:

Sending build context to Docker daemon    107kB
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:

docker run --rm -it localhost/httpd-vhosts bash

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:

cat conf/httpd.conf | grep "httpd-vhosts"

Kimenet:

Include conf/extra/httpd-vhosts.conf

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:

version: "3.9"

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:

version: "3.9"

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:

source httpd-vhosts-env/bin/activate

Majd indítás:

docker-compose up -d

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:

version: "3.9"

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:

docker-compose up -d

A kimenet a build más ismert kimenetén kívül még az alábbi:

WARNING: Image for service httpd was built because it did not already exist. To rebuild this image you must use `docker-compose build` or `docker-compose up --build`.
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:

docker-compose up -d --build

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.

Kategóriák: 
Megosztás/Mentés