Kihagyás

Dockerfile és docker-compose

Cél

A labor célja megismerni a Docker-alap fejlesztés módjait, a Dockerfile és docker-compose alapú megközelítéseket, valamint a Microsoft Visual Studio fejlesztőkörnyezet konténerfejlesztést támogató szolgáltatásait.

Előkövetelmények

  • Docker Desktop
  • Docker-compose
  • Microsoft Visual Studio Code
  • Microsoft Visual Studio 2017/2019
    • 2017 esetén legalább 15.6 verzió
    • A .NET Core cross-platform development nevű workload szükséges

Feladatok

Dockerfile készítése

Előző laboron készítettünk már egy saját image-et. Az image elkészítésére azonban nem az a módszer a javasolt megoldás, hanem a Dockerfile alapú "recept készítés".

  1. Készíts egy munkakönytárat, pl. c:\work\<neptun>\dockerlab\pythonweb
  2. Nyisd meg a mappát Visual Studio Code-ban.
  3. Készíts egy Dockerfile nevű fájt (kiterjesztés nélkül!) az alábbi tartalommal.

    FROM python:3.8-slim
    WORKDIR /app
    COPY . /app
    RUN pip install --trusted-host pypi.python.org -r requirements.txt
    EXPOSE 80
    ENV NAME NEPTUN # Ide a saját Neptun kódodat írd
    CMD ["python", "app.py"]
    
  4. Készíts egy requirements.txt fájlt az alábbi tartalommal

    Flask
    Redis
    
  5. Készíts egy app.py fájlt az alábbi tartalommal

    from flask import Flask
    from redis import Redis, RedisError
    import os
    import socket
    
    # Connect to Redis
    redis = Redis(host="redis", db=0, socket_connect_timeout=2, socket_timeout=2)
    
    app = Flask(__name__)
    
    @app.route("/")
    def hello():
        try:
            visits = redis.incr("counter")
        except RedisError:
            visits = "<i>cannot connect to Redis, counter disabled</i>"
    
        html = "<h3>Hello {name}!</h3><b>Visits:</b> {visits}"
        return html.format(name=os.getenv("NAME", "world"), visits=visits)
    
    if __name__ == "__main__":
        app.run(host='0.0.0.0', port=80)
    
  6. Készítsd el a fenti fájlokból az image-et. Konzolból a munkakönyvtárban add ki a következő parancsot: docker build -t hellopython:v1 . (a végén egy pont van, az is a parancs része!)

  7. Ellenőrizd, hogy tényleg létrejött-e az image.
  8. Indíts el egy új konténert ebből az image-ből: docker run -it --rm -p 8085:80 hellopython:v1
  9. Nyisd meg böngészőben a http://localhost:8085 oldalt.

A weboldal ki kell írja a neptun kódodat, és egy hibaüzenetet a Redis-szel kapcsolatban.

Dockerignore és build kontextus

A Dockerfile-ban hivatkoztunk az aktuális könyvtárra a .-tal. Vizsgáljuk meg, hogy ez mit is jelent.

  1. Készítsünk az aktuális könyvtárunkba, az app.py mellé egy nagy fájlt. PowerShell-ben addjuk ki a következő parancsot.

    $out = new-object byte[] 134217728; (new-object Random).NextBytes($out); [IO.File]::WriteAllBytes("$pwd\file.bin", $out)
    
  2. Buildeljük le ismét a fenti image-et: docker build -t hellopython:v1 .

    Menet közben látni fogjuk a következő sort a build logban: Sending build context to Docker daemon 111.4MB, és azt is tapasztalni fogjuk, hogy ez el tart egy kis ideig.

    A docker build parancs végén a . az aktuális könyvtár. Ezzel tudatjuk a Docker-rel, hogy a buildeléshez ezt a kontextust használja, azon fájlok legyenek elérhetőek a build során, amelyek ebben a kontextusban vannak. A Dockerfile-ban a COPY így relatív útvonallal hivatkozik a kontextusban levő fájlokra.

    Elérhető fájlok

    Ennek következménye az is, hogy csak a build kontextusban levő fájlokra tudunk hivatkozni. Tehát nem lehet pl. COPY ..\..\file használatával tetszőleges fájlt felmásolni a build közben.

  3. Ha a build kontextusból szeretnénk kihagyni fájlokat, hogy a build ne tartson sokáig, akkor egy .dockerignore fájlra lesz szükségünk (a .gitignore mintájára). Ide szokás például a build környezet saját könyvtárait (obj, bin, .vs, node_modules, stb.) is felvenni.

    Készítsünk egy .dockerignore-t az alábbi tartalommal

    file.bin
    
  4. Futtassuk ismét a buildet. Így már gyorsabb lesz.

Docker-compose

A fenti alkalmazás egy része még nem működik. A Python alkalmazás mellett egy Redis-re is szükségünk lenne. Futtassunk több konténert egyszerre.

  1. Visual Studio Code-ban nyisd meg a mappát, amiben az előző feladat során használt pythonweb mappa van. Tehát nem az előzőleg használt mappa kell, hanem egy szinttel feljebb (pl. c:\work\<neptun>\dockerlab).

  2. Készíts ide egy docker-compose.yaml nevű fájlt az alábbi tartalommal.

    version: "3"
    
    services:
      redis:
        image: redis:5.0.5-alpine
        networks:
          - mikroszolg_network
      web:
        build: pythonweb
        ports:
          - 5000:80
        depends_on:
          - redis
        networks:
          - mikroszolg_network
    
    networks:
      mikroszolg_network:
        driver: bridge
    
  3. Nyiss egy PowerShell konzolt ugyanebbe a mappába. Indítsd el az alkalmazásokat az alábbi paranccsal: docker-compose up --build

    • Két lépésben a parancs: docker-compose build és docker-compose up
  4. Nyisd meg böngészőben a http://localhost:5000 oldalt.

  5. Egy új konzolban nézd meg a futó konténereket a docker ps parancs segítségével.

docker-compose üzemeltetéshez

A docker-compose alkalmas üzemeltetésre is. A docker-compose.yaml fájl nem csak fejlesztői környezetet ír le, hanem üzemeltetéshez szükséges környezetet is. Ha a compose fájlt megfelelően írjuk meg (pl. használjuk a restart direktívát is), az elindított szolgáltatások automatikusan újraindulnak a rendszer indulásakor.

Több compose yaml fájl

A docker-compose parancsnak nem adtuk meg, hogy milyen yaml fájlból dolgozzon. Alapértelmezésként a docker-compose.yaml kiterjesztésű fájlt és ezzel összefésülve a docker-compose.override.yaml fájlt használja.

  1. Készíts egy docker-compose.override.yaml fájlt a másik compose yaml mellé az alábbi tartalommal

    version: "3"
    
    services:
      redis:
        command: redis-server --loglevel verbose
    
  2. Indítsd el a rendszert docker-compose up paranccsal. A redis konténer részletesebben fog naplózni a command direktívában megadott utasítás szerint. Állítsd le a rendszert.

  3. Nevezd át az előbbi override fájlt docker-compose.debug.yaml-re. Készíts egy új docker-compose.prod.yaml fájlt a többi yaml mellé az alábbi tartalommal

    version: "3"
    
    services:
      redis:
        command: redis-server --loglevel warning
    
  4. Indítsuk el a rendszert az alábbi paranccsal

    docker-compose -f docker-compose.yaml -f docker-compose.prod.yaml up
    

    A -f kapcsolóval tudjuk kérni a megadott yaml fájlok összefésülését.

Általában a docker-compose.yaml-be kerülnek a közös konfigurációk, és a további fájlokba a környezet specifikus konfigurációk.

Tipikusan használt image-ek

Konténer alapú fejlesztésnél tehát két féle image-et használunk:

  • amit magunk készítünk egy adott alap image-re épülve,
  • illetve kész image-eket, amiket csak futtatunk (és esetleg konfigurálunk).

Alap image-ek, amikre tipikusan saját alkalmazást építünk:

  • Linux disztribúciók
  • Futtató platformok
    • .NET Core, pl. mcr.microsoft.com/dotnet/core/runtime:2.1.12-bionic
    • OpenJDK pl. openjdk:11-jre-stretch
    • NodeJS pl. node:12.7.0-alpine
    • Python pl. python:2.7-slim
  • scratch: üres image, speciális esetek, pl. go

A kész image-ek, amiket pedig felhasználunk:

  • Adatbázis szerverek, webszerverek, gyakran használt szolgáltatások
  • MSSQL Server, redis, mongodb, mysql, nginx, ...
  • Termérdek elérhető image: https://hub.docker.com

Verziózás fontos

Az image-ek verziózását minden esetben meg kell érteni! Minden image más-más megközelítést alkalmaz.

Kész image testreszabása

Az előbb a Redis memória alapú adatbázist minden konfiguráció nélkül felhasználtuk. Gyakran az ilyen image-ek "majdnem" jók közvetlen felhasználásra, de azért szükség van egy kevés testreszabásra. Ilyen esetben a következő lehetőségeink vannak:

  • Saját image-et készítünk kiindulva a számunkra megfelelő alap image-ből. A saját image-ben módosíthatunk a konfigurációs fájlokat, avagy további fájlokat adhatunk az image-be. Ezt a megoldást alkalmazhatjuk például tipikusan weboldal kiszolgálásánál, ahol is a kiinduló image a webszerver, viszont a kiszolgálandó fájlokat még mellé kell tennünk.

  • Környezeti változókon keresztül konfiguráljuk a futtatandó szolgáltatást. Az alap image-ek általában elég jó konfigurációval rendelkeznek, csak keveset kell rajta módosítanunk. Erre tökéletesen alkalmas egy-egy környezeti változó. A jól felépített Docker image-ek előre meghatározott környezeti változókon keresztül testreszabhatóak.

    Erre egy jó példa a Microsoft SQL Server Docker változata. Az alábbi parancsban a -e argumentumokban adunk át környezeti változókat:

    docker run
      -e 'ACCEPT_EULA=Y'
      -e 'SA_PASSWORD=yourStrong(!)Password'
      -p 1433:1433
      mcr.microsoft.com/mssql/server:2017-CU8-ubuntu
    
  • Becsatolhatjuk a saját konfigurációs fájljainkat a konténerbe. Korábban láttuk, hogy lehetőségünk van egy mappát a host géptről a konténerbe csatolni. Ha elkészítjük a testreszabott konfigurációs fájlt, akkor a docker-compose.yaml leírásban a következő módon tudjuk ezt a fájlt becsatolni a konténer indulásakor.

    services:
      redis:
        image: redis:5.0.5-alpine
        volumes:
          - my-redis.conf:/usr/local/etc/redis/redis.conf
    

    Ezen megoldás előnye, hogy nincs szükség saját image-et készíteni, tárolni, kezelni. Amikor a környezeti változó már nem elegendő a testreszabáshoz, ez a javasolt megoldás.

Microsoft Visual Studio támogatás Docker-alapú fejlesztéshez

A Microsoft Visual Studio a 2017-es verzió óta támogatja és megkönnyíti a konténer alapú szoftverfejlesztést. Segíti a fejlesztőt a fejlesztett alkalmazás konténerizálásában, és támogatja a konténerben való debuggolást is.

  1. Engedélyezzük Docker-ben a volume sharing-et!
  2. Indítsuk el a Visual Studio-t (nem a Code-ot!).
  3. Készítsünk egy új ASP.NET Core Web Application típusú projektet a Web application sablonnal, és engedélyezzük a Linux-alapú konténer támogatást a projektben. (A pontos lépések Visual Studio verzió függőek, lásd itt.)
  4. Nézzük meg és értsük meg az elkészült solution struktúrát, valamint a Dockerfile-t és a docker-compose fájlokat is.
  5. Indítsuk el az alkalmazást Docker-compose használatával: legyen a docker-compose a startup projektünk, és F5-tel indítsuk debug módban az alkalmazást.
  6. Egy konzolból listázzuk ki a futó konténereket: docker ps

Debuggolás konténerben is

A Visual Studio Code is támogatja a konténerek debuggolását. Erről részletesen lásd itt.

További olvasnivaló

Back to top