==== Docker virtualizáció ==== A következőkben megnézzük hogyan lehet használni a gyakorlatban a népszerű Docker virtualizációt. Kérem, hogy mindenki lépjen be a http://docker.iit.uni-miskolc.hu/ oldalon. Majd lépjen be ugyanitt a megjelenő start gombra kattintva. A megjelenő képen bal oldalon a "+ Add new instance" gomb megnyomása után a következő képet fogjuk látni: {{tanszek:oktatas:informatikai_rendszerek_epitese:1.png?320x200}} Hozzunk létre egy app.py nevő állományt, a követkető parancs futtatásával, és nyomjuk meg a Ctrl+d a befejezéshez: cat>app.py A delete gomb melletti Editor feliratú gomb megnyomásával egy új ablakban megjelenik a fájl editor. Ebben nyissuk meg a most létrehozott **app.py**-t. {{tanszek:oktatas:informatikai_rendszerek_epitese:2.png?320x200}} Másoljuk be az editorba az alábbi kódot: import time import redis from flask import Flask app = Flask(__name__) cache = redis.Redis(host='redis', port=6379) def get_hit_count(): retries = 5 while True: try: return cache.incr('hits') except redis.exceptions.ConnectionError as exc: if retries == 0: raise exc retries -= 1 time.sleep(0.5) @app.route('/') def hello(): count = get_hit_count() return 'Hello World! I have been seen {} times.\n'.format(count) Ez a Python program az egyik legegyszerűbb Flask elnevezésű webkiszolgálót/keretrendszert mutatja. A fenti kódrészlet egy számlálót valósít meg, ami a **redis** nevű cache rendszer segítségével számolja a látogatókat. Hozzunk létre egy **requirements.txt** nevű állományt a korábbi módon: cat>requirements.txt Majd az editor segítségével másoljuk bele az alábbi sorokat: flask redis Ezzel definiáljuk, hogy az alkalmazásunknak mik a függőségei. Ebben az esetben ezek a **flask framework** és a **redis cache**. Ez azért kell, mert a virtuális gép üres konfigurációval indul, és a requirements.txt használatával fogjuk telepíteni a függőségeket. Azaz kézzel nem telepítünk semmit, csak szabványos módon. ==== Dockerfile létrehozása ==== Hozzunk létre egy **Dockerfile** elnevezésű állományt a következő tartalommal a szokásos módon: FROM python:3.7-alpine WORKDIR /code ENV FLASK_APP=app.py ENV FLASK_RUN_HOST=0.0.0.0 RUN apk add --no-cache gcc musl-dev linux-headers COPY requirements.txt requirements.txt RUN pip install -r requirements.txt EXPOSE 5000 COPY . . CMD ["flask", "run"] Itt meg kell állnunk egy kis magyarázatra. A Dockerfile feladata az, hogy lépésről lépésre definiálja a virtuális gép létrehozását. Soronként a következőket definiáljuk: * Hozzon létre egy kiinduló virtuális gépet (image) a python 3.7-es támogatással és a **alpine** nevű linux kernellel. * a munkakönyvtárunk a /code lesz. * Állítsunk be két környezeti változót, ami a flask-nak szükséges a kiszolgáláshoz. * Telepítsük a gcc-t és más függőségeket. (ez azért kell, mert a Python sok csomagot c/c++ forrás állományokból fordít) * másoljuk be a requirements.txt-t a munkakönyvtárba (ez azért kell, mert a virtuális gépnek saját fájlrendszere van, a Dockerfile mellett lévő állományokat nem tudja közvetlenül olvasni.) * EXPOSE parancs tcp portot nyit meg kifelé (jelen esetben az 5000-est) * mindent másoljuk be a munkakönyvtárba * az utolsó sor a telepítés utáni indító parancsot definiálja, jelen esetben: "flask run" ==== Compose állomány létrehozása ==== Más leírásokban ennél a pontnál elindítják a virtuális gépet. Mi nem tesszük meg, hanem továbblépünk a **docker-compose** lehetőségeire, amivel rugalmasan tudunk több virtuális gépet egyszerre kezelni. Nem feltétlenül kell Dockerfile-t sem létrehozni, ha Interneten is elérhető szabványos konfigurációkat használunk. Hozzuk létre a docker-compose.yml állományt a szokásos módon: version: "3.3" services: web: build: . ports: - "80:5000" redis: image: "redis:alpine" Ez az állomány szolgáltatásokban gondolkodik. Minden **service** egy különálló docker image, viszont a nevükre hivatkozva belsőleg elérik egymást. A fenti konfiguráció **web** elnevezésű szolgáltatását a **build: .** miatt a Dockerfile alapján hozzuk létre, viszont a másik **redis** szolgáltatást a szabványos "redis:alpine" konfiguráció alapján használjuk. A **web** esetén a belsőleg kinyitott 5000-es portot láthatóvá tesszük a 80-as port-on. Indítsuk el a következő parancsot és várjuk meg ameddig lefut: docker-compose up A következő képernyőhöz hasonlót kell látnunk, ha mindent jól állítottunk be előzőleg. Nyomjuk meg a nyíllal jelölt gombot. {{tanszek:oktatas:informatikai_rendszerek_epitese:3.png?320x200|}} ==== Fejlesztési lehetőségek ==== Frissítsük többször a böngészőt, láthatjuk, hogy a látogatásszám dinamikusan frissül. Ctrl + c segítségével megállíthatjuk a futtatást. cseréljük le a docker-compose.yml tartalmát a következőre: version: "3.3" services: web: build: . ports: - "5000:5000" volumes: - .:/code environment: FLASK_ENV: development redis: image: "redis:alpine" A **volumes** beállítja, hogy a virtuális gépben belül levő könyvtár, jelen esetben a __working directory__ a gazda rendszerhez legyen kötve, illetve kimásolva. Ha nem a gyökérbe szeretnénk mappelni, akkor pl: ./mycode:/code is megadható, de a mycode könyvtárnak az indítás előtt léteznie kell. Indítsuk el újra a rendszert: docker-compose up Majd látható, hogy a konzolban developer módra kapcsoltunk. Módosítsuk az editor segítségével a app.py-t, mondjuk az utolsó függvényben a kiírás szövegét és frissítsük a böngészőt. ==== Docker compose parancsok ==== Futó virtuális gépek listázása: docker-compose ps Egy adott instance milyen környezeti változókat használ? docker-compose run web env Hogyan állíthatjuk le a szolgáltatásokat? docker-compose stop Hogyan tudunk teljesen letörölni mindent leállítás után? docker-compose down --volumes Hogyan tudunk shellbe belépni egy konténeren belül? docker-compose exec sh Honnan tudok előre elkészített minta container-eket letölteni? https://github.com/docker/awesome-compose