„EDU::GAMF::Felhőalapú-szolgáltatások::Docker” változatai közötti eltérés

Innen: Farkas Attila Wiki
Ugrás a navigációhoz Ugrás a kereséshez
195. sor: 195. sor:
docker run -d --expose 80 -p 80:80  ubuntu:apache2 apache2ctl -D FOREGROUND
docker run -d --expose 80 -p 80:80  ubuntu:apache2 apache2ctl -D FOREGROUND
</syntaxhighlight>
</syntaxhighlight>
  Az --expose üzeni a ''docker daemon'' felé, hogy ez a konténer kommunikálhat a 80-as porton keresztül a HOST OS felé.<br><br>
  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é.<br><br>
  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.<br><br>
  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.<br><br>
  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.
  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:
<syntaxhighlight lang="bash">
docker run -d --expose 80 --expose 443 -p 80:80  ubuntu:apache2 apache2ctl -D FOREGROUND
</syntaxhighlight>
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 ====
=== Build ====

A lap 2022. október 25., 23:45-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):

  1. 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)
  2. A Virtualizált OS szintje, saját kernellel és driverekkel
  3. 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

  1. 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
  2. Az operációs rendszeren telepítünk egy konténerizációs alkalmazást (esetünkben docker daemon-t)
  3. 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 előfordulásai

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.

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 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 =

Saját image feltöltése registrybe

Docker hálózatok

Saját docker registry létrehozása

Docker containerek csoportosítása (compose)