„EDU::GAMF::Felhőalapú-szolgáltatások::Docker” változatai közötti eltérés
| (11 közbenső módosítás ugyanattól a szerkesztőtől nincs mutatva) | |||
| 30. sor: | 30. sor: | ||
Érdemes tájékozódni, mielőtt egy technológiát ténylegesen ajánlatba adunk, gyorsan fejlődik az iparág, így könnyedén jelenhetnek meg újabb szereplők is, akik lesöprik a megszokott dolgokat! | Érdemes tájékozódni, mielőtt egy technológiát ténylegesen ajánlatba adunk, gyorsan fejlődik az iparág, így könnyedén jelenhetnek meg újabb szereplők is, akik lesöprik a megszokott dolgokat! | ||
=== Docker | === Docker felhasználási területei === | ||
A docker mára annyira kinőtte magát, hogy a legtöbb cég az alkalmazásait ilyen környezetben telepíti, ezzel ténylegesen időt spórolva magának. | A docker mára annyira kinőtte magát, hogy a legtöbb cég az alkalmazásait ilyen környezetben telepíti, ezzel ténylegesen időt spórolva magának. | ||
| 45. sor: | 45. sor: | ||
'''Nem csak az üzemeltetést könnyíti meg vagy javítja a rendelkezésreállást, hanem a fejlesztési időn is javít'''. | '''Nem csak az üzemeltetést könnyíti meg vagy javítja a rendelkezésreállást, hanem a fejlesztési időn is javít'''. | ||
Természetesen ne gondoljunk olyanokra, hogy a programot helyettünk lefejleszti egy konténer, de azzal nagyon sokat nyerünk, hogy ha egy konténerben lefejlesztünk valamit és működik, akkor a konténert egy másik gépre másolva is működni fog, függetlenül attól, hogy esetleg platformot váltottunk (windwos->linux vagy fordítva), hogy verziót váltottunk vagy hogy milyen csomagok érhetők el a cél szerveren. Ezek a kérdések sok esetben plusz fejlesztési időt jelentenek, hogy valamelyest dinamikus legyen. | Természetesen ne gondoljunk olyanokra, hogy a programot helyettünk lefejleszti egy konténer, de azzal nagyon sokat nyerünk, hogy ha egy konténerben lefejlesztünk valamit és működik, akkor a konténert egy másik gépre másolva is működni fog, függetlenül attól, hogy esetleg platformot váltottunk (windwos->linux vagy fordítva), hogy verziót váltottunk vagy hogy milyen csomagok érhetők el a cél szerveren. Ezek a kérdések sok esetben plusz fejlesztési időt jelentenek, hogy valamelyest dinamikus legyen. | ||
''Sandboxing'' megoldások körében is előkerül a docker. Ez azt jelenti, hogy egy alkalmazást először egy konténerben próbálnak ki és ha úgy gondolják, akkor telepítik az éles rendszerbe is. Ha úgy alakul, hogy nincs rá szükség, akkor a konténerrel együtt elveszik minden módosítás is, tehát a tárhely 100%-ban visszanyerhető. Legyünk azért ezzel is óvatosak, egy virtuális gép alkalmazás tesztelésre sokkal jobb lehetőséget biztosít, sokkal mélyebben szétválik a két rendszer egymástól. Docker esetében például egy kernel sebezhetőséggel konténeren belülről is vissza lehet élni és ne feledkezzünk meg a ''docker daemon'' hibáiról sem. | |||
=== Docker registry === | === Docker registry === | ||
| 210. sor: | 212. sor: | ||
=== Build === | === Build === | ||
==== Dockerfile tartalma ==== | |||
Képfájlt hozhatunk létre anélkül is, hogy elindítanánk egyet kézzel és be konfigurálnánk azt, ahogy az előbb tettük. Ehhez egy ''Dockerfile'' nevű állományt kell létrehoznunk. | Képfájlt hozhatunk létre anélkül is, hogy elindítanánk egyet kézzel és be konfigurálnánk azt, ahogy az előbb tettük. Ehhez egy ''Dockerfile'' nevű állományt kell létrehoznunk. | ||
Érdemes ezt a saját könyvtárunkban megtenni, esetleg egy külön mappában, ahogy a következő kód is mutatja: | Érdemes ezt a saját könyvtárunkban megtenni, esetleg egy külön mappában, ahogy a következő kód is mutatja: | ||
| 220. sor: | 223. sor: | ||
FROM ubuntu | FROM ubuntu | ||
RUN apt update && apt install apache2 -y | RUN apt update && apt install apache2 -y | ||
EXPOSE 80 443 | |||
ENTRYPOINT apache2ctl -D FOREGROUND | ENTRYPOINT apache2ctl -D FOREGROUND | ||
</syntaxhighlight> | </syntaxhighlight> | ||
| 226. sor: | 230. sor: | ||
A ''„FROM”''-mal adjuk meg, hogy melyik képfájlból akarunk kiindulni | A ''„FROM”''-mal adjuk meg, hogy melyik képfájlból akarunk kiindulni | ||
A ''„RUN”'' kulcsszót olyan parancsok követik, amelyet a kiválasztott képfájlban végre akarunk hajtani. | A ''„RUN”'' kulcsszót olyan parancsok követik, amelyet a kiválasztott képfájlban végre akarunk hajtani. | ||
Az ''„ENTRYPOINT”'' kulcsszót követi a docker elindítását követően (''docker run'') automatikusan induló | Az ''„EXPOSE”'' kulcsszó után megadhatjuk szóközzel elválasztva, hogy mely portokon képes kommunikálni a konténer. | ||
Az ''„ENTRYPOINT”'' kulcsszót követi a docker elindítását követően (''docker run'') automatikusan induló program (a ''docker daemon'' ennek a programnak a kilépésére fog várni, amikor ez a program megszakad, akkor a konténer is leáll, tehát csak olyat írjunk ide, ami a végtelenségig képes futni). | |||
Az ENTRYPOINT helyett írhatunk CMD-t is, azonban jó, ha tudjuk, hogy a ''docker run'' parancs végén a ''CMD'' utasítást adhatjuk meg: | |||
<syntaxhighlight lang="bash"> | |||
docker run -ti ubuntu bash | |||
</syntaxhighlight> | |||
Ebben az esetben a ''„bash”'' kulcsszó a CMD-nek felel meg, így ha a felhasználó ezt a paramétert is megadja, akkor felül fogja írni a képfájlban definiáltat, ami az alkalmazás helyi összeomlását is jelentheti egyes esetekben (természetesen az újbóli futtatása jelen esetben ''bash'' paraméter nélkül meg fogja oldani a problémát). | |||
Az ENTRYPOINT érétke azonban csak külön kapcsolóval változtatható meg, így kisebb az esélye, hogy egy hozzá nem értő ezzel működésképtelenné teszi a konténerben az alkalmazást. | |||
A program futtatása úgy épül fel, hogy ''${ENTRYPOINT} ${CMD}'', tehát az ''ENTRYPOINT''-ban megadhatjuk, hogy melyik programot szeretnénk, hogy mindenképp lefusson és ''CMD''-vel megadhatjuk, hogy alapértelmezetten milyen paraméterekkel induljon, de a felhasználó ha szeretné, akkor a paramétereket megváltoztathatja. Ehhez a következő formában kell megadnunk ezeket az értékeket: | |||
<syntaxhighlight lang="dockerfile"> | |||
FROM ubuntu | |||
RUN apt update && apt install apache2 -y | |||
EXPOSE 80 | |||
ENTRYPOINT ["apache2ctl"] | |||
CMD ["-D FOREGROUND"] | |||
</syntaxhighlight> | |||
'''Csak ebben a megadási módban működik, „[” „]” párok nélkül nem cserélődik le a ''CMD'' tartalma!''' | |||
Lehetséges konfiguráció lehet jelen esetben a következő is: | |||
<syntaxhighlight lang="dockerfile"> | |||
FROM ubuntu | |||
RUN apt update && apt install apache2 -y | |||
EXPOSE 80 | |||
ENTRYPOINT ["apache2ctl", "-D"] | |||
CMD ["FOREGROUND"] | |||
</syntaxhighlight> | |||
Ez esetben a '-D' kapcsoló mindenképp az ''apache2ctl'' parancs után kerül, a felhasználó a docker indításakor azt választhatja meg, hogy a defualt ''FOREGROUND'' vagy egy explicit megadott ''BACKGROUND'' paraméterrel szeretné-e futtatni ('''utóbbi esetben a konténer egyből kilépne, így ennek a nyitva hagyása jelen esetben nem ésszerű'''). | |||
Adhatunk meg továbbá ''USER'' és ''WORKDIR'' kulcsszavakat: előbbivel azt állíthatjuk be, hogy a docker milyen felhasználónévvel fusson, utóbbi a kezdőkönyvtárat változtatja meg. | |||
'''A USER paraméter NAGYON fontos, soha ne készítsünk olyan image-t, amely root joggal fut! A biztonsági kockázata nagyon magas.''' | |||
<syntaxhighlight lang="dockerfile"> | |||
FROM ubuntu | |||
RUN apt update && apt install apache2 -y | |||
# ez egy pillanatra elindítja az apache2-t, így kialakítja root joggal a működéshez szükséges mappákat | |||
RUN apache2ctl start | |||
# admin felhasználó létrehozása | |||
RUN useradd admin | |||
# apache logfájlokon legyen admin csoport a szerző | |||
RUN chgrp admin /var/log/apache2 -R | |||
# apache2 log fájlokon root és admin csoport bármit tehet, mindenki más olvashat | |||
RUN chmod 2774 /var/log/apache2 -R | |||
# admin el tudja indítani az apache2 szolgáltatást | |||
RUN chgrp admin /var/run/apache2 -R | |||
# admin el tudja indítani az apache2 szolgáltatást, tudjon ide írni | |||
RUN chmod 2775 /var/run/apache2 -R | |||
# admin-ként fogja inicializálni a konténert indításkor (docker run) | |||
USER admin | |||
# a kezdőkönyvtár legyen az app könyvtára (nem muszáj, de így nem kell keresni később) | |||
WORKDIR /var/www/html | |||
EXPOSE 80 | |||
ENTRYPOINT apache2ctl -D FOREGROUND | |||
</syntaxhighlight> | |||
==== Képfájl mentése Dockerfile-ból ==== | |||
A következő paranccsal létrehozhatjuk a képfájlt, ha a Dockerfile az aktuális mappában van: | |||
<syntaxhighlight lang="bash"> | |||
# docker build --tag <server>/<namespace>/<name>:<tags> <context> | |||
# ne feledkezzünk meg a kontextus paraméterről a sor végén, mivel a Dockerfile mellettünk van, '.' van a parancs végén. | |||
docker build --tag ubuntu:apache2 . | |||
</syntaxhighlight> | |||
=== Saját image feltöltése registrybe === | === Saját image feltöltése registrybe === | ||
== Docker hálózatok == | == Docker hálózatok == | ||
== Docker containerek csoportosítása (compose) == | == Docker containerek csoportosítása (compose) == | ||
== Apache2 ubuntu - biztonságos == | |||
<syntaxhighlight lang="dockerfile"> | |||
FROM ubuntu | |||
RUN apt update && apt install -y \ | |||
apache2 | |||
EXPOSE 80/tcp | |||
RUN useradd app | |||
RUN mkdir /environment -m 777 | |||
RUN sed -i \ | |||
"s/\/var\/run\/apache2\$SUFFIX\/apache2.pid/\/environment\/apache2.pid/" \ | |||
/etc/apache2/envvars | |||
RUN sed -i \ | |||
"s/\/var\/run\/apache2\$SUFFIX/\/environment/" \ | |||
/etc/apache2/envvars | |||
RUN sed -i \ | |||
"s/\/var\/lock\/apache2\$SUFFIX/\/environment/" \ | |||
/etc/apache2/envvars | |||
RUN sed -i \ | |||
"s/\/var\/log\/apache2\$SUFFIX/\/environment/" \ | |||
/etc/apache2/envvars | |||
USER app | |||
ENTRYPOINT ["/sbin/apache2ctl", "-D", "FOREGROUND"] | |||
# docker build --tag test:apache2 . | |||
</syntaxhighlight> | |||
A lap jelenlegi, 2023. november 9., 13:01-kori változata
Mi az a Docker?
A Docker a konténer technológiák egyike. A konténerek és a virtuális gépek rokonságban állnak egymással, de mégis nagy különbség van közöttük: a konténerek pehelykönnyűek.
De hogyan válik egy virtuális gép pehelykönnyűvé? A válasz az, hogy Docker esetében nincs hardvervirtualizáció, így kisebb az erőforrásigénye - nem kell az eszközökre "memory map"-ot létrehozni a felmerülő biztonsági problémák kezelésére és nem kell minden hozzáférésnél azokat forwardolni - és a benne futó operációs rendszerek is a lehető legminimálisabb konfigurációval rendelkeznek.
Tekintsük meg egy virtuális gép szintjeit (lásd: VM szintek):
- A fizikai vas szintje fölé telepítünk valamilyen hypervisort, azaz virtualizációs környezetet
- itt jön létre az említett "memory map"
- a virtuális gépek az itt beállított hardverkörnyezetet fogják látni, ami akár fals információ is lehet, eltérhet a valóságtól (kompatibilitások miatt szokás átverni a felsőbb szinteket)
- A Virtualizált OS szintje, saját kernellel és driverekkel
- A virtuális gépben telepített alkalmazások szintje
Ezzel szemben tekintsük meg a Docker szintjeit (lásd: Docker szintek vagy VM vs Docker
- A fizikai vas szintje fölé telepítjük a HOST operációs rendszert, ami többnyire valamilyen linux alapú operációs rendszer
- Az operációs rendszeren telepítünk egy konténerizációs alkalmazást (esetünkben docker daemon-t)
- Az elindított konténerek a telepített konténerizációs alkalmazással kommunikálnak számukra ez az API a HOST operációs rendszere felé.
Végső soron a nagy különbséget az jelenti, hogy a konténerek esetén a kernelt nem virtualizáljuk, hanem felhasználjuk a HOST operációs rendszerét, így mindent, ami az alatti szinten található ki vehetjük a virtuális környezet menedzseléséből.
Egyéb konténer technológiák
Szerencsés megjegyezni, hogy bár a piac nagy részét jelenleg a Docker birtokolja a konténerek világában, azért nem nevezhetjük egyeduralkodónak. Vannak egyéb fejlesztések is, amelyek bizonyos esetekben célravezetőbbek lehetnek, bár ezek felhasználási területei jóval szegényesebbek.
A teljesség igénye nélkül egy pár nevesebb (a többit lásd: Docker alternatívák 2022-ben):
- LXC / LXD, azaz Linux Container, amelyet többet között a Proxmox is támogat (a proxmox egy ESXi-hez hasonló virtuális gép vezérlő operációs rendszer, amelyet a VPS szolgáltatók (is) használnak).
- Podman
- RunC
- Containerd
Érdemes tájékozódni, mielőtt egy technológiát ténylegesen ajánlatba adunk, gyorsan fejlődik az iparág, így könnyedén jelenhetnek meg újabb szereplők is, akik lesöprik a megszokott dolgokat!
Docker felhasználási területei
A docker mára annyira kinőtte magát, hogy a legtöbb cég az alkalmazásait ilyen környezetben telepíti, ezzel ténylegesen időt spórolva magának.
Hogyan spórolhat időt egy olyan technológia, ami újabb üzemeltetési kérdéseket vet fel? Képzeljünk el egy olyan szervert, amely 5db weboldalt futtat, azaz 5 különböző virtual host létezik rajta. Az egyik nginx alatt fut, a másik nodejs, a harmadik php7-es verzióval, a negyedik php8-as verzióval fut és még nem is említettük, hogy adatokat is szeretnénk tárolni mssql, mysql, postgresql esetleg sqlite adatbázisokban, akármilyen kombinációban. Érezzük, hogy ennek a szervernek az üzemeltetése nem kis feladat, de ha csak a különböző verziót igénylő PHP-s weboldalakat szeretnénk egy szerveren elhelyezni, azzal is rendkívül érdekes feladatokba ütközhetünk (természetesen lehetséges és meg van rá a bejáratott módszer, hiszen ez a docker előtt is probléma volt). Ha ezt tekintjük és ezzel állítjuk szembe azt a többlet feladatot, hogy a docker daemon-t is üzemeltetni, frissíteni kell, akkor már nem is tűnik rossz ötletnek: ha egy-egy alkalmazás külön-külön konténerekbe kerülne, akkor nem kellene sem az egy szerveren futtatott többféle verzió problémájával, sem a különböző adatbázis szükségletekkel, sem a különböző webszerver szükségletekkel foglalkoznunk, gyakorlatilag mindenki olyan technológiát használ, amilyet szeretne és úgy frissíti a konténeren belül azokat, amilyen ütemben szeretné, a többire nem lesz hatással.
Mi a helyzet a konténerek okozta többlet teljesítmény szükséglettel? A korábbi fejezetben tárgyaltak alapján a konténer nem fogyaszt sokat, így az overhead rendkívül kicsi. Természetesen van némi többlet CPU idő, memória és tárhely felhasználás - ha csak azt vesszük, hogy egyetlen SQL szerver helyett minden konténerbe külön fel lesz telepítve, így töbszörösen tároljuk a szerver konfigurációs állományait stb.), de mindez manapság bőven ellensúlyozható viszonylag alacsony költségen: nem okoz akkora költség többletet, mint amekkora veszteséget okozna egy frissítést követően összeomlott vegyes rendszer, tehát mondhatjuk, hogy bár teljesítmény vesztés jelentkezik, azt mégis megéri bevállalni az előnyei miatt (a virtuális gépet ugyanerre a célra például nem érte meg bevetni).
Az üzemeltetés gyorsításán túl használják felhő kialakítására is, hiszen a daemon-ba épített swarm-nak köszönhetően automatikusan skálázhatunk dockereket akár több szerveren is, amik ráadásul pár másodperc alatt elérhetővé válnak, így a bootolási időt is megspóroljuk. Hozzá kell tenni, hogy a swarm-nál manapság létezik jobb és barátságosabb orchestrator is, pl.: Kubernetes.
Nem csak az üzemeltetést könnyíti meg vagy javítja a rendelkezésreállást, hanem a fejlesztési időn is javít. Természetesen ne gondoljunk olyanokra, hogy a programot helyettünk lefejleszti egy konténer, de azzal nagyon sokat nyerünk, hogy ha egy konténerben lefejlesztünk valamit és működik, akkor a konténert egy másik gépre másolva is működni fog, függetlenül attól, hogy esetleg platformot váltottunk (windwos->linux vagy fordítva), hogy verziót váltottunk vagy hogy milyen csomagok érhetők el a cél szerveren. Ezek a kérdések sok esetben plusz fejlesztési időt jelentenek, hogy valamelyest dinamikus legyen.
Sandboxing megoldások körében is előkerül a docker. Ez azt jelenti, hogy egy alkalmazást először egy konténerben próbálnak ki és ha úgy gondolják, akkor telepítik az éles rendszerbe is. Ha úgy alakul, hogy nincs rá szükség, akkor a konténerrel együtt elveszik minden módosítás is, tehát a tárhely 100%-ban visszanyerhető. Legyünk azért ezzel is óvatosak, egy virtuális gép alkalmazás tesztelésre sokkal jobb lehetőséget biztosít, sokkal mélyebben szétválik a két rendszer egymástól. Docker esetében például egy kernel sebezhetőséggel konténeren belülről is vissza lehet élni és ne feledkezzünk meg a docker daemon hibáiról sem.
Docker registry
Ez a szolgáltatás tárolja az elérhető képfájlokat. A docker egyéb információ hiányában a docker.com webhelyre feltöltött fájlok között keres és innen tölti le a találatokat, de telepíthetünk sajátot is (erről később lesz szó).
A docker.com-ra a regisztráció ingyenes, egy privát projektet hozhatunk létre és bármennyit publikusan. Ez magában foglalja a veszélyt is: bárki feltölthet például egy webszervert, amelyben kiskapuk vannak stb. Minidg ügyeljünk rá, hogy megbízható helyről származzon, amit letöltünk!
Docker Telepítése
A futáshoz telepítenünk kell a docker daemon-t, amit a következő paranccsal tehetünk meg:
apt update && apt install docker.io docker
Docker conatainerek indítása
Az elérhető konténerek között kereshetünk az ubuntu karakterláncra a következő paranccsal:
docker search ubuntu
A kimeneten láthatjuk, hogy mely csomagnak milyen a megítélése, biztonságos forrásból származik-e stb.
A képfájlok neve a következőképp épül fel: [registry_server]/namespace/name[:tags]
- A registry_server a docker search kimenetében nem látszik, mivel ebben az esetben fixen a docker.com oldalon keresünk.
- A namespace-re láthatunk példát
- Amennyiben nincs benne /-jel, akkor csak a nevét adtuk meg namespace és szerver nélkül
- Kettőspont után adhatunk hozzá tag-et (egyet, de általában kötőjellel választjuk el, ha többet is szeretnénk mégis). Ha nem írunk tag-et egy image után, akkor a docker úgy veszi, hogy a latest nevűt akarjuk használni, tehát ezt nem kell kiírni. Minden más esetben igen.
Mivel az ubuntu-ra volt találat, így indítsunk el egy konténert belőle:
docker run ubuntu
Ha a fenti parancsot lefuttatjuk, akkor nem fogunk tapasztalni semmit, igazán csak azt látjuk, hogy a daemon úgy döntött, hogy ez az image nálunk nem elérhető, így letöltötte és egyébként futtatta is, de a végén ugyanúgy a HOST OS-ben találjuk magunkat. Ez nem hiba, rosszul paramétereztük a rendszerünket.
Most indítsuk el a következő paranccsal:
docker run -ti ubuntu
-t => pseudo-tty hozzárendelése -i => interaktív, tehát tudunk kommunikálni a dockerrel Ebben az esetben kapunk egy újszerű PROMPT-ot, tehát most tényleg a konténerben vagyunk, azt tudjuk konfigurálni. exit paranccsal be tudjuk ezt a terminált zárni.
Miután vissza kaptuk a HOST OS terminálját futtassuk le az alábbi parancsot, ahol azt tapasztaljuk, hogy egyetlen konténer sem fut:
docker ps
A ps kilistázza a futó konténereket és azok főbb tulajdonságait - pl. mi a neve, milyen portokat engedélyeztünk rajta, melyik image-ből indult ki stb.
A konténer leállását az okozza, hogy az exit parancsra a bash program kilép és az ubuntu ennek a leállását várja: addig fut a konténer, amíg a bash is fut. Amikor az leállt, akkor a docker-nek már nem volt egyéb feladata, így leállt. Erre mindig oda kell majd figyelnünk, hogy amivel elindítjuk a konténert, az folyamatosan fusson benne, hogy a konténerünk működésben maradjon.
A fenti problémát feloldhatjuk azzal, ha daemonizáljuk a konténert - azaz a háttérben indítjuk el:
docker run -d ubuntu
Ez esetben azonban nem kaptunk PROMPT-ot sem, bár a docker ps parancs mutatja, hogy fut. Szerezzünk terminált a futó konténerhez:
docker exec -ti <a ''docker ps'' által kiírt container_id> bash
Az exec segítségével új feladatot adhatunk a konténernek, ami természetesen az előző mellett, párhuzamosan fog futni. Ha a program, amit futtatunk egy SHELL, pl. bash, akkor kapunk egy konzolt a konténerben. (-ti jelentése ugyanaz, mint korábban).
Docker konténerek leállítása
- A docker ps parancsot futtatva kinyerhetjük a futó konténer ID-ját
- Futtassuk a docker kill <container_id> <container_id2> <container_id3> parancsot a kívánt konténerek erőszakos kilövéséhez vagy a docker stop <container_id> <container_id2> <container_id3> parancsot a normál leállításhoz.
Docker konténerek menedzselése
A rendszerben futó konténereket kilistázhatjuk a következő paranccsal:
docker container ls
A rendszerben egyszer elindított (nem feltétlen futó) konténereket listázhatjuk a következő paranccsal:
docker container ls -a
A nem futó konténereket letörölhetjük egyesével megnevezve a következő paranccsal:
docker container rm <container_id> <container_id2> <container_idN>
A nem futó konténereket letörölhetjük egy paranccsal:
docker container prune
Docker képfájlok menedzselése
A helyi gyűjtőbe mentett képfájlokat a következő paranccsal listázhatjuk:
docker image ls
A nem használt képfájlokat letörölhetjük egyesével megnevezve a következő paranccsal:
docker image rm <image_id> <image_id> <image_id>
A nem használt képfájlokat letörölhetjük egy paranccsal:
docker image prune
Docker image készítése
Konténerből
Először is indítsunk el egy konténert a kiválasztott képfájlból (pl. ubuntu)!
docker run -ti ubuntu
Ezzel kapnunk kell egy terminált, aminek a PROMPT-ja nem hasonlít a HOST OS-ére, legyünk körültekintőek, hogy hol futtatjuk a következő parancsokat: a konténeren belül legyünk!
Frissítsük le a csomaglistát és telepítsük fel az apache2 programot, hogy legyen webes alkalmazásunk!
apt update && apt install apache2 -y
exit
Miután feltelepült, ki is lépünk az exit paranccsal. Emlékezzünk, hogy ezzel a konténerünk leállt!
Keressük ki az előbb létrehozott konténer ID-ját (a docker ps csak a futó konténereket listázza)
docker container ls -a
A leállítás óta eltelt időnél a legkisebb értéket jegyző konténer lesz az, amit most állítottunk le, amennyiben többet is listázott és nem ismerjük fel.
Mentsük a konténeren történt változásokat egy új képfájlba:
# docker commit <container_id> <name>:<tag>
docker commit <container_id> ubuntu:apache2
Ellenőrizzük, hogy létrejött-e az új képfájl:
docker image ls
Itt látszódnia kell egy ubuntu:apache2 sornak. Ügyeljünk rá, hogy a név és a tag ez esetben tabulátorral vannak elválasztva, nem kettősponttal, hiszen táblázatos formában jelenik meg.
Végül próbáljuk ki, hogy ténylegesen a mentett állapot fogad-e minket, ha az új konténer indítjuk el:
docker run -ti ubuntu:apache2 bash
A konténer terminálját megnyitva teszteljük le, hogy létezik-e például az apache2ctl nevű parancs:
which apache2ctl
Ha ezutóbbi parancs ír ki valamit, akkor jó eséllyel telepítve van a konténerben.
Ahhoz, hogy ténylegesen működjön az alkalmazásunk, ahhoz jelezni kell, hogy a konténerben a 80-as porton van egy szolgáltatásunk. Ez a docker daemon felé nyújtott információ, így lesz lehetőségünk rá forgalmat küldeni, ha szeretnénk. Természetesen amíg nem engedélyezzük, addig nem fogja elérni senki. A következő paranccsal futtathatjuk úgy, hogy a HOST gép IP-jével hivatkozva (saját gépen localhost, egyébként a szerver IP-je) betöltsön a konténeren belüli alkalmazás:
docker run -d --expose 80 -p 80:80 ubuntu:apache2 apache2ctl -D FOREGROUND
Az --expose 80 üzeni a docker daemon felé, hogy ez a konténer kommunikálhat a 80-as porton keresztül a HOST OS felé.
A -p 80:80 jelzi, hogy a HOST OS 80-as portját át irányítjuk az ubuntu:apache2 képfájlból készített konténer 80-as portjára. Sablon: "<host_ip>:<host_port>:<container_port>", ahol a host_ip lehet 127.0.0.1 => csak a localhostról érhető el a portforward (proxy esetén javasolt, hogy kívülről ne lehessen elérni a konténert direktben), lehet a szerver IP címei közül bármelyik megadva (pl. 192.168.1.100, amennyiben ez a belsőhálózati IP címe) és lehet 0.0.0.0 (ez az alapértelmezett), ami minden a géphez köthető IP címen hallgatózni fog.
Az „apache2ctl -D FOREGROUND” előtérben futtatja az apache2 szervert, így nem áll le a konténer sem, futásban marad és várja a csatlakozó klienseket.
Érdemes a parancs lefuttatása után megnézni a docker ps kimenetét, a port átirányítások és lehetőségek ott is látszódnak. Ha pl. az előző parancsot megismételjük a következő bővítéssel:
docker run -d --expose 80 --expose 443 -p 80:80 ubuntu:apache2 apache2ctl -D FOREGROUND
A docker ps kimenetében azt fogjuk látni, hogy a 80:80-as portforward szabály él erre a konténerre, de mindeközben lenne lehetőség a 443-as porton is kommunikálni, ha ezt is felkonfigurálnánk egy '-p 443:443' kapcsolóval.
Build
Dockerfile tartalma
Képfájlt hozhatunk létre anélkül is, hogy elindítanánk egyet kézzel és be konfigurálnánk azt, ahogy az előbb tettük. Ehhez egy Dockerfile nevű állományt kell létrehoznunk. Érdemes ezt a saját könyvtárunkban megtenni, esetleg egy külön mappában, ahogy a következő kód is mutatja:
cd ~ && mkdir web && cd web && nano Dockerfile
A fájl tartalma legyen ez:
FROM ubuntu
RUN apt update && apt install apache2 -y
EXPOSE 80 443
ENTRYPOINT apache2ctl -D FOREGROUND
Jól látható, hogy ugyanazok a parancsok vannak benne, amit az előbb is lefuttatunk, csupán ezt most egy fájlban foglaltuk össze. A „FROM”-mal adjuk meg, hogy melyik képfájlból akarunk kiindulni A „RUN” kulcsszót olyan parancsok követik, amelyet a kiválasztott képfájlban végre akarunk hajtani. Az „EXPOSE” kulcsszó után megadhatjuk szóközzel elválasztva, hogy mely portokon képes kommunikálni a konténer. Az „ENTRYPOINT” kulcsszót követi a docker elindítását követően (docker run) automatikusan induló program (a docker daemon ennek a programnak a kilépésére fog várni, amikor ez a program megszakad, akkor a konténer is leáll, tehát csak olyat írjunk ide, ami a végtelenségig képes futni).
Az ENTRYPOINT helyett írhatunk CMD-t is, azonban jó, ha tudjuk, hogy a docker run parancs végén a CMD utasítást adhatjuk meg:
docker run -ti ubuntu bash
Ebben az esetben a „bash” kulcsszó a CMD-nek felel meg, így ha a felhasználó ezt a paramétert is megadja, akkor felül fogja írni a képfájlban definiáltat, ami az alkalmazás helyi összeomlását is jelentheti egyes esetekben (természetesen az újbóli futtatása jelen esetben bash paraméter nélkül meg fogja oldani a problémát). Az ENTRYPOINT érétke azonban csak külön kapcsolóval változtatható meg, így kisebb az esélye, hogy egy hozzá nem értő ezzel működésképtelenné teszi a konténerben az alkalmazást.
A program futtatása úgy épül fel, hogy ${ENTRYPOINT} ${CMD}, tehát az ENTRYPOINT-ban megadhatjuk, hogy melyik programot szeretnénk, hogy mindenképp lefusson és CMD-vel megadhatjuk, hogy alapértelmezetten milyen paraméterekkel induljon, de a felhasználó ha szeretné, akkor a paramétereket megváltoztathatja. Ehhez a következő formában kell megadnunk ezeket az értékeket:
FROM ubuntu
RUN apt update && apt install apache2 -y
EXPOSE 80
ENTRYPOINT ["apache2ctl"]
CMD ["-D FOREGROUND"]
Csak ebben a megadási módban működik, „[” „]” párok nélkül nem cserélődik le a CMD tartalma!
Lehetséges konfiguráció lehet jelen esetben a következő is:
FROM ubuntu
RUN apt update && apt install apache2 -y
EXPOSE 80
ENTRYPOINT ["apache2ctl", "-D"]
CMD ["FOREGROUND"]
Ez esetben a '-D' kapcsoló mindenképp az apache2ctl parancs után kerül, a felhasználó a docker indításakor azt választhatja meg, hogy a defualt FOREGROUND vagy egy explicit megadott BACKGROUND paraméterrel szeretné-e futtatni (utóbbi esetben a konténer egyből kilépne, így ennek a nyitva hagyása jelen esetben nem ésszerű).
Adhatunk meg továbbá USER és WORKDIR kulcsszavakat: előbbivel azt állíthatjuk be, hogy a docker milyen felhasználónévvel fusson, utóbbi a kezdőkönyvtárat változtatja meg. A USER paraméter NAGYON fontos, soha ne készítsünk olyan image-t, amely root joggal fut! A biztonsági kockázata nagyon magas.
FROM ubuntu
RUN apt update && apt install apache2 -y
# ez egy pillanatra elindítja az apache2-t, így kialakítja root joggal a működéshez szükséges mappákat
RUN apache2ctl start
# admin felhasználó létrehozása
RUN useradd admin
# apache logfájlokon legyen admin csoport a szerző
RUN chgrp admin /var/log/apache2 -R
# apache2 log fájlokon root és admin csoport bármit tehet, mindenki más olvashat
RUN chmod 2774 /var/log/apache2 -R
# admin el tudja indítani az apache2 szolgáltatást
RUN chgrp admin /var/run/apache2 -R
# admin el tudja indítani az apache2 szolgáltatást, tudjon ide írni
RUN chmod 2775 /var/run/apache2 -R
# admin-ként fogja inicializálni a konténert indításkor (docker run)
USER admin
# a kezdőkönyvtár legyen az app könyvtára (nem muszáj, de így nem kell keresni később)
WORKDIR /var/www/html
EXPOSE 80
ENTRYPOINT apache2ctl -D FOREGROUND
Képfájl mentése Dockerfile-ból
A következő paranccsal létrehozhatjuk a képfájlt, ha a Dockerfile az aktuális mappában van:
# docker build --tag <server>/<namespace>/<name>:<tags> <context>
# ne feledkezzünk meg a kontextus paraméterről a sor végén, mivel a Dockerfile mellettünk van, '.' van a parancs végén.
docker build --tag ubuntu:apache2 .
Saját image feltöltése registrybe
Docker hálózatok
Docker containerek csoportosítása (compose)
Apache2 ubuntu - biztonságos
FROM ubuntu
RUN apt update && apt install -y \
apache2
EXPOSE 80/tcp
RUN useradd app
RUN mkdir /environment -m 777
RUN sed -i \
"s/\/var\/run\/apache2\$SUFFIX\/apache2.pid/\/environment\/apache2.pid/" \
/etc/apache2/envvars
RUN sed -i \
"s/\/var\/run\/apache2\$SUFFIX/\/environment/" \
/etc/apache2/envvars
RUN sed -i \
"s/\/var\/lock\/apache2\$SUFFIX/\/environment/" \
/etc/apache2/envvars
RUN sed -i \
"s/\/var\/log\/apache2\$SUFFIX/\/environment/" \
/etc/apache2/envvars
USER app
ENTRYPOINT ["/sbin/apache2ctl", "-D", "FOREGROUND"]
# docker build --tag test:apache2 .