\section{Dockerfile} \begin{frame}{Mi a Dockerfile?} \begin{block}{Dockerfile -- Image építési utasítások} \begin{itemize} \item Szöveges fájl, amely leírja hogyan kell egy image-et építeni \item Tartalmazza az összes parancsot sorrendben \item Verziókezelhető (Git-ben tárolva) \end{itemize} \end{block} \end{frame} \begin{frame}{Dockerfile -- Jellemzők} \begin{block}{Tulajdonságok} \begin{itemize} \item Reprodukálható: ugyanaz a Dockerfile = ugyanaz az image \item Neve: \texttt{Dockerfile} (kiterjesztés nélkül) \end{itemize} \end{block} \begin{exampleblock}{Analógia} A Dockerfile olyan, mint egy \textbf{sütési recept} -- lépésről lépésre leírja, hogyan készüljön az image. \end{exampleblock} \end{frame} \begin{frame}[fragile]{Első Dockerfile -- Kód} \begin{block}{Legegyszerűbb példa} \begin{lstlisting}[language=Docker,basicstyle=\scriptsize\ttfamily] FROM ubuntu:22.04 CMD echo "Hello World!" \end{lstlisting} \end{block} \end{frame} \begin{frame}[fragile]{Első Dockerfile -- Build és futtatás} \begin{exampleblock}{Build és futtatás} \begin{lstlisting}[language=bash,basicstyle=\scriptsize\ttfamily] # Image építése docker build -t my-hello . # Konténer futtatása docker run my-hello # Kimenet: Hello World! \end{lstlisting} \end{exampleblock} \end{frame} \begin{frame}{Első Dockerfile -- Magyarázat} \begin{block}{Utasítások} \begin{itemize} \item \texttt{FROM}: Alap image megadása \item \texttt{CMD}: Alapértelmezett parancs futtatáskor \end{itemize} \end{block} \begin{block}{Build paraméterek} \begin{itemize} \item \texttt{-t}: Tag (név) adása az image-nek \item \texttt{.}: Build context (jelenlegi mappa) \end{itemize} \end{block} \end{frame} \begin{frame}{Dockerfile alaputasítások -- 1. rész} \begin{block}{Alapépítő utasítások} \begin{enumerate} \item \texttt{FROM} -- Alap image kiválasztása \begin{itemize} \item Minden Dockerfile ezzel kezdődik \item Meghatározza a kiinduló környezetet \end{itemize} \item \texttt{WORKDIR} -- Munkakönyvtár beállítása \begin{itemize} \item Létrehozza és beállítja a dolgozó könyvtárat \item Minden következő utasítás itt fut \end{itemize} \end{enumerate} \end{block} \end{frame} \begin{frame}{Dockerfile alaputasítások -- 2. rész} \begin{block}{Fájl és csomag kezelés} \begin{enumerate} \setcounter{enumi}{2} \item \texttt{COPY} / \texttt{ADD} -- Fájlok másolása \begin{itemize} \item Fájlok hozzáadása az image-hez \item COPY javasolt, ADD extra funkciókkal \end{itemize} \item \texttt{RUN} -- Parancs futtatása build közben \begin{itemize} \item Csomagok telepítése, fájlok létrehozása \item Minden RUN új réteget hoz létre \end{itemize} \end{enumerate} \end{block} \end{frame} \begin{frame}{Dockerfile alaputasítások -- 3. rész} \begin{block}{Konfiguráció és indítás} \begin{enumerate} \setcounter{enumi}{4} \item \texttt{ENV} -- Környezeti változó beállítása \item \texttt{EXPOSE} -- Port deklarálása \item \texttt{CMD} / \texttt{ENTRYPOINT} -- Indítási parancs \end{enumerate} \end{block} \begin{alertblock}{Sorrend fontos!} A Dockerfile utasításai felülről lefelé hajtódnak végre \end{alertblock} \end{frame} \begin{frame}[fragile]{FROM -- Alap image kiválasztása} \begin{block}{Hivatalos image-ek} \begin{lstlisting}[language=Docker,basicstyle=\scriptsize\ttfamily] # Hivatalos Node.js image FROM node:18 # Specifikus verzió FROM node:18.16.0 # Alpine Linux alapú (kisebb méret) FROM node:18-alpine \end{lstlisting} \end{block} \end{frame} \begin{frame}[fragile]{FROM -- További példák} \begin{block}{Más nyelvek és rendszerek} \begin{lstlisting}[language=Docker,basicstyle=\scriptsize\ttfamily] # Ubuntu FROM ubuntu:22.04 # Python FROM python:3.11 \end{lstlisting} \end{block} \begin{alertblock}{Ajánlás} Használj \textbf{specifikus verziót} (pl. \texttt{node:18.16}) a \texttt{latest} helyett!\\ Alpine verzió: kisebb méret, gyorsabb build. \end{alertblock} \end{frame} \begin{frame}[fragile]{WORKDIR -- Kód} \begin{block}{Beállítja a munkakönyvtárat} \begin{lstlisting}[language=Docker,basicstyle=\scriptsize\ttfamily] FROM node:18 # Munkakönyvtár létrehozása és beállítása WORKDIR /usr/src/app # Minden utána következő parancs itt fut COPY package.json ./ RUN npm install \end{lstlisting} \end{block} \end{frame} \begin{frame}{WORKDIR -- Magyarázat} \begin{block}{Funkcionalitás} \begin{itemize} \item Létrehozza a könyvtárat, ha nem létezik \item Minden következő \texttt{RUN}, \texttt{COPY}, \texttt{CMD} itt fut \item Konténerben \texttt{docker exec} is ide lép be \end{itemize} \end{block} \begin{alertblock}{Jó gyakorlat} Használj dedikált könyvtárat: \texttt{/app} vagy \texttt{/usr/src/app} \end{alertblock} \end{frame} \begin{frame}[fragile]{COPY -- Fájl másolás} \begin{block}{Egy és több fájl másolása} \begin{lstlisting}[language=Docker,basicstyle=\scriptsize\ttfamily] # Egy fájl COPY package.json ./ # Több fájl COPY file1.txt file2.txt ./ \end{lstlisting} \end{block} \end{frame} \begin{frame}[fragile]{COPY -- Mappák és teljes tartalom} \begin{block}{Mappák másolása} \begin{lstlisting}[language=Docker,basicstyle=\scriptsize\ttfamily] # Mappa teljes tartalma COPY src/ ./src/ # Minden a build context-ből COPY . . \end{lstlisting} \end{block} \begin{exampleblock}{Jellemzők} \begin{itemize} \item Egyszerű fájl és mappa másolás \item Látható és érthető \item \textbf{Ajánlott használni!} \end{itemize} \end{exampleblock} \end{frame} \begin{frame}[fragile]{ADD -- Speciális másolás} \begin{block}{ADD utasítás} \begin{lstlisting}[language=Docker,basicstyle=\scriptsize\ttfamily] # Automatikus kicsomagolás ADD archive.tar.gz /app/ # URL letöltés (nem ajánlott) ADD http://example.com/file ./ \end{lstlisting} \end{block} \end{frame} \begin{frame}{ADD vs COPY -- Összehasonlítás} \begin{block}{ADD vs COPY} \begin{itemize} \item ADD: automatikus kicsomagolás, URL támogatás \item COPY: egyszerű, explicit, ajánlott \end{itemize} \end{block} \begin{alertblock}{Best Practice} Használj \texttt{COPY}-t, kivéve ha kifejezetten kell az \texttt{ADD} extra funkciója! \end{alertblock} \begin{exampleblock}{URL-hez} URL letöltéshez jobb RUN + curl/wget használata \end{exampleblock} \end{frame} \begin{frame}[fragile]{RUN -- Csomagok telepítése} \begin{block}{Csomag telepítés} \begin{lstlisting}[language=Docker,basicstyle=\scriptsize\ttfamily] # Csomag telepítés RUN apt-get update && apt-get install -y curl # NPM függőségek RUN npm install # Python csomagok RUN pip install -r requirements.txt \end{lstlisting} \end{block} \end{frame} \begin{frame}[fragile]{RUN -- Több parancs kombinálása} \begin{block}{Több parancs egyetlen RUN-ban} \begin{lstlisting}[language=Docker,basicstyle=\scriptsize\ttfamily] # Több parancs (shell form) RUN apt-get update && \ apt-get install -y git curl && \ apt-get clean \end{lstlisting} \end{block} \begin{alertblock}{Fontos} Minden \texttt{RUN} egy új \textbf{réteg} (layer) az image-ben.\\ Kombináld parancsokat \texttt{\&\&}-del a rétegek csökkentéséhez! \end{alertblock} \end{frame} \begin{frame}[fragile]{ENV -- Környezeti változók} \begin{block}{Környezeti változók beállítása} \begin{lstlisting}[language=Docker,basicstyle=\scriptsize\ttfamily] # Egy változó ENV NODE_ENV=production # Több változó ENV NODE_ENV=production \ PORT=3000 \ DB_HOST=localhost \end{lstlisting} \end{block} \end{frame} \begin{frame}[fragile]{ENV -- Használat utasításokban} \begin{block}{Használat későbbi utasításokban} \begin{lstlisting}[language=Docker,basicstyle=\scriptsize\ttfamily] ENV APP_HOME=/usr/src/app WORKDIR $APP_HOME \end{lstlisting} \end{block} \begin{exampleblock}{Mikor érhető el?} \begin{itemize} \item Build időben: későbbi \texttt{RUN} parancsokban \item Runtime-ban: futó konténerben \item Felülírható: \texttt{docker run -e NODE\_ENV=dev} \end{itemize} \end{exampleblock} \end{frame} \begin{frame}[fragile]{EXPOSE -- Port deklaráció} \begin{block}{Dokumentálja, melyik porton fut az app} \begin{lstlisting}[language=Docker,basicstyle=\scriptsize\ttfamily] # HTTP port EXPOSE 3000 # Több port EXPOSE 3000 5000 8080 # UDP port EXPOSE 53/udp \end{lstlisting} \end{block} \end{frame} \begin{frame}{EXPOSE -- Magyarázat} \begin{alertblock}{Fontos megértés} \texttt{EXPOSE} \textbf{NEM} nyitja meg a portot! \end{alertblock} \begin{block}{Funkció} \begin{itemize} \item Csak \textbf{dokumentáció}, hogy melyik porton fut az alkalmazás \item Tényleges mapping: \texttt{docker run -p 3000:3000} \end{itemize} \end{block} \begin{exampleblock}{Hasznos} Docker Compose és orchestration eszközök használják ezt az információt. \end{exampleblock} \end{frame} \begin{frame}[fragile]{CMD -- Alapértelmezett parancs} \begin{block}{CMD utasítás} \begin{lstlisting}[language=Docker,basicstyle=\scriptsize\ttfamily] # Shell form CMD npm start # Exec form (ajánlott) CMD ["npm", "start"] # Paraméterekkel CMD ["node", "server.js"] \end{lstlisting} \end{block} \end{frame} \begin{frame}[fragile]{CMD -- Felülírás futtatáskor} \begin{exampleblock}{Felülírás futtatáskor} \begin{lstlisting}[language=bash,basicstyle=\scriptsize\ttfamily] # Alapértelmezett CMD fut docker run my-app # CMD felülírása docker run my-app npm test \end{lstlisting} \end{exampleblock} \begin{exampleblock}{Tippek} \begin{itemize} \item Exec form ajánlott: \texttt{["cmd", "param"]} \item Shell form: stringek közvetlenül \end{itemize} \end{exampleblock} \end{frame} \begin{frame}[fragile]{ENTRYPOINT -- Fő végrehajtható} \begin{block}{ENTRYPOINT utasítás} \begin{lstlisting}[language=Docker,basicstyle=\scriptsize\ttfamily] # Exec form (ajánlott) ENTRYPOINT ["node"] # CMD paramétereket ad hozzá CMD ["server.js"] \end{lstlisting} \end{block} \end{frame} \begin{frame}[fragile]{ENTRYPOINT -- Paraméter változtatás} \begin{exampleblock}{Paraméter változtatás} \begin{lstlisting}[language=bash,basicstyle=\scriptsize\ttfamily] # server.js fut (CMD alapértelmezett) docker run my-app # app.js fut (CMD felülírva, de node marad) docker run my-app app.js \end{lstlisting} \end{exampleblock} \begin{alertblock}{Best Practice} Használj \texttt{CMD}-t egyszerű esetekben, \texttt{ENTRYPOINT + CMD}-t összetettebb esetekben. \end{alertblock} \end{frame} \begin{frame}[fragile]{Teljes Node.js példa -- Dockerfile} \begin{exampleblock}{Dockerfile Node.js alkalmazáshoz} \begin{lstlisting}[language=Docker,basicstyle=\scriptsize\ttfamily] # Alap image FROM node:18-alpine # Munkakönyvtár WORKDIR /usr/src/app # Függőségek másolása és telepítése COPY package*.json ./ RUN npm ci --only=production \end{lstlisting} \end{exampleblock} \end{frame} \begin{frame}[fragile]{Teljes Node.js példa -- Kód és indítás} \begin{exampleblock}{Alkalmazás és futtatás} \begin{lstlisting}[language=Docker,basicstyle=\scriptsize\ttfamily] # Alkalmazás kódjának másolása COPY . . # Környezeti változó ENV NODE_ENV=production # Port deklarálás EXPOSE 3000 # Indítási parancs CMD ["node", "server.js"] \end{lstlisting} \end{exampleblock} \end{frame} \begin{frame}[fragile]{Layer caching -- Probléma} \begin{alertblock}{Mi a probléma?} Minden Dockerfile sor egy \textbf{layer} (réteg).\\ Ha egy layer változik, az összes utána következő újraépül! \end{alertblock} \end{frame} \begin{frame}[fragile]{Layer caching -- Nem hatékony megoldás} \begin{block}{Nem hatékony megközelítés} \begin{lstlisting}[language=Docker,basicstyle=\scriptsize\ttfamily] FROM node:18 WORKDIR /app # Minden változásra újra COPY . . RUN npm install CMD ["npm", "start"] \end{lstlisting} \end{block} \end{frame} \begin{frame}{Layer caching -- Következmény} \begin{alertblock}{Következmény} Bármilyen kód módosítás után az \texttt{npm install} is újrafut,\\ pedig a \texttt{package.json} nem változott! \end{alertblock} \begin{exampleblock}{Példa} \begin{itemize} \item 1 sor kód változik a src/app.js-ben \item \texttt{COPY . .} layer változik \item \texttt{RUN npm install} újrafut (pár perc!) \end{itemize} \end{exampleblock} \end{frame} \begin{frame}[fragile]{Layer caching -- Optimalizálás} \begin{exampleblock}{Jó megoldás} \begin{lstlisting}[language=Docker,basicstyle=\scriptsize\ttfamily] FROM node:18 WORKDIR /app # Cache-elhető - csak ha package.json változik COPY package*.json ./ RUN npm install # Gyakran változik - de nem érinti a fenti layer-eket COPY . . CMD ["npm", "start"] \end{lstlisting} \end{exampleblock} \end{frame} \begin{frame}{Layer caching -- Alapelvek} \begin{block}{Alapelv} \textbf{Ritkábban változó dolgok előre, gyakran változók hátra!} \end{block} \begin{exampleblock}{Példa szervezet} \begin{enumerate} \item FROM -- alap image (soha nem változik) \item Függőségek (package.json) $\rightarrow$ ritkán változnak \item Forráskód $\rightarrow$ gyakran változik \end{enumerate} \end{exampleblock} \end{frame} \begin{frame}{Layer caching -- Eredmény} \begin{alertblock}{Eredmény} Kód változtatás $\Rightarrow$ csak COPY és CMD layer újraépül\\ npm install cache-elve marad! \end{alertblock} \end{frame} \begin{frame}{.dockerignore -- Mi ez?} \begin{block}{Mi ez és miért fontos?} Megadja, mely fájlokat \textbf{NE} másolja be az image-be.\\ Hasonló a \texttt{.gitignore}-hoz. \end{block} \begin{alertblock}{Előnyök} \begin{itemize} \item Kisebb image méret \item Gyorsabb build folyamat \item Biztonságosabb (nincs .env, .git) \end{itemize} \end{alertblock} \end{frame} \begin{frame}[fragile]{.dockerignore -- Node.js példa} \begin{exampleblock}{Node.js projekt .dockerignore fájlja} \begin{lstlisting}[language=bash,basicstyle=\scriptsize\ttfamily] # Node.js node_modules npm-debug.log # Git .git .gitignore # Fejlesztői fájlok *.md .env .env.local \end{lstlisting} \end{exampleblock} \end{frame} \begin{frame}[fragile]{.dockerignore -- További kizárások} \begin{exampleblock}{Teszt és IDE fájlok} \begin{lstlisting}[language=bash,basicstyle=\scriptsize\ttfamily] # Teszt fájlok *.test.js # IDE .vscode .idea # Logs logs *.log \end{lstlisting} \end{exampleblock} \end{frame} \begin{frame}{Multi-stage build -- Alapok} \begin{block}{Mi a multi-stage build?} \begin{itemize} \item Több \texttt{FROM} utasítás egy Dockerfile-ban \item Különböző szakaszok különböző célokra \item Végső image: csak a szükséges fájlok \end{itemize} \end{block} \end{frame} \begin{frame}{Multi-stage build -- Előnyök} \begin{exampleblock}{Miért jó?} \begin{itemize} \item Build eszközök nem kerülnek a végső image-be \item Fejlesztői függőségek nem kellenek production-ben \item Kisebb méret = gyorsabb deploy, kevesebb tárhely \end{itemize} \end{exampleblock} \end{frame} \begin{frame}{Multi-stage build -- Méretösszehasonlítás} \begin{exampleblock}{Méretösszehasonlítás} \begin{itemize} \item Egy-stage build: \textasciitilde500MB (Node.js + dev deps + TS compiler) \item Multi-stage build: \textasciitilde150MB (csak Node.js + prod deps + JS) \item Méretcsökkenés: 70\%! \end{itemize} \end{exampleblock} \begin{alertblock}{Példa} TypeScript: \texttt{tsc} fordítás és csak a JS megy a végső image-be \end{alertblock} \end{frame} \begin{frame}[fragile]{Multi-stage build -- Builder stage} \begin{exampleblock}{Stage 1: Build} \begin{lstlisting}[language=Docker,basicstyle=\scriptsize\ttfamily] FROM node:18 AS builder WORKDIR /app COPY package*.json ./ RUN npm install COPY . . RUN npm run build \end{lstlisting} \end{exampleblock} \end{frame} \begin{frame}[fragile]{Multi-stage build -- Production stage} \begin{exampleblock}{Stage 2: Production} \begin{lstlisting}[language=Docker,basicstyle=\scriptsize\ttfamily] FROM node:18-alpine WORKDIR /app COPY package*.json ./ RUN npm ci --only=production COPY --from=builder /app/dist ./dist EXPOSE 3000 CMD ["node", "dist/server.js"] \end{lstlisting} \end{exampleblock} \begin{block}{Kulcs elemek} \begin{itemize} \item \texttt{AS builder}: Első stage elnevezése \item \texttt{--from=builder}: Fájl másolás előző stage-ből \end{itemize} \end{block} \end{frame} \begin{frame}[fragile]{Multi-stage build -- Go példa} \begin{exampleblock}{Go alkalmazás -- drasztikus méretcsökkentés} \begin{lstlisting}[language=Docker,basicstyle=\scriptsize\ttfamily] # Stage 1: Build FROM golang:1.20 AS builder WORKDIR /app COPY . . RUN CGO_ENABLED=0 GOOS=linux go build -o main . # Stage 2: Production (scratch = üres image!) FROM scratch COPY --from=builder /app/main /main EXPOSE 8080 ENTRYPOINT ["/main"] \end{lstlisting} \end{exampleblock} \begin{alertblock}{Eredmény} Golang image: \textasciitilde800MB $\Rightarrow$ Végső image: \textasciitilde10MB \end{alertblock} \end{frame} \begin{frame}[fragile]{ARG -- Build-time változók} \begin{block}{ARG vs ENV} \begin{itemize} \item \texttt{ARG}: Csak build közben érhető el \item \texttt{ENV}: Build és runtime is \end{itemize} \end{block} \end{frame} \begin{frame}[fragile]{ARG -- Használat} \begin{exampleblock}{ARG használata} \begin{lstlisting}[language=Docker,basicstyle=\scriptsize\ttfamily] # Alapértelmezett érték ARG NODE_VERSION=18 FROM node:${NODE_VERSION} ARG VERSION=1.0.0 # Convert to ENV (ha runtime kell) ENV APP_VERSION=${VERSION} \end{lstlisting} \end{exampleblock} \end{frame} \begin{frame}[fragile]{ARG -- Build argument átadása} \begin{exampleblock}{Parancssorból} \begin{lstlisting}[language=bash,basicstyle=\scriptsize\ttfamily] # Build argument átadása docker build --build-arg NODE_VERSION=20 \ --build-arg VERSION=2.0 . \end{lstlisting} \end{exampleblock} \end{frame} \begin{frame}{USER -- Biztonság} \begin{alertblock}{Biztonság} \textbf{Soha ne futtass produkciós konténert root-ként!} \end{alertblock} \begin{block}{Miért veszélyes a root?} \begin{itemize} \item Ha a konténer kompromittálódik, a támadó teljes hozzáféréssel rendelkezik \item Biztonsági rések kihasználása könnyebb \item Host rendszer veszélyeztetett lehet \end{itemize} \end{block} \end{frame} \begin{frame}[fragile]{USER -- Implementáció} \begin{block}{Root user elkerülése} \begin{lstlisting}[language=Docker,basicstyle=\scriptsize\ttfamily] FROM node:18-alpine WORKDIR /app COPY package*.json ./ RUN npm ci --only=production # Nem privilegizált user létrehozása RUN addgroup -S appgroup && \ adduser -S appuser -G appgroup # Fájlok tulajdonjogának változtatása RUN chown -R appuser:appgroup /app \end{lstlisting} \end{block} \end{frame} \begin{frame}[fragile]{USER -- Váltás és használat} \begin{block}{User váltás} \begin{lstlisting}[language=Docker,basicstyle=\scriptsize\ttfamily] # User váltás USER appuser COPY --chown=appuser:appgroup . . CMD ["node", "server.js"] \end{lstlisting} \end{block} \end{frame} \begin{frame}[fragile]{HEALTHCHECK -- Állapot ellenőrzés} \begin{block}{Konténer egészség ellenőrzés} \begin{lstlisting}[language=Docker,basicstyle=\scriptsize\ttfamily] HEALTHCHECK --interval=30s --timeout=3s \ --start-period=5s --retries=3 \ CMD node healthcheck.js \end{lstlisting} \end{block} \end{frame} \begin{frame}[fragile]{HEALTHCHECK -- HTTP endpoint} \begin{exampleblock}{HTTP endpoint ellenőrzés} \begin{lstlisting}[language=Docker,basicstyle=\scriptsize\ttfamily] HEALTHCHECK --interval=30s --timeout=3s \ CMD wget --no-verbose --tries=1 \ --spider http://localhost:3000/health || exit 1 \end{lstlisting} \end{exampleblock} \end{frame} \begin{frame}{HEALTHCHECK -- Paraméterek} \begin{block}{Paraméterek magyarázata} \begin{itemize} \item \texttt{--interval=30s}: Ellenőrzések közötti idő \item \texttt{--timeout=3s}: Max várakozás egy ellenőrzésre \item \texttt{--start-period=5s}: Kezdeti várakozási idő \end{itemize} \end{block} \end{frame} \begin{frame}{HEALTHCHECK -- Retries} \begin{block}{Újrapróbálkozás} \begin{itemize} \item \texttt{--retries=3}: Hányszor próbálja újra hiba esetén \item 3 sikertelen után unhealthy státusz \end{itemize} \end{block} \end{frame} \begin{frame}[fragile]{Build parancsok -- Alapok} \begin{block}{docker build alapok} \begin{lstlisting}[language=bash,basicstyle=\scriptsize\ttfamily] # Alap build docker build -t my-app:latest . # Specifikus Dockerfile docker build -f Dockerfile.prod -t my-app:prod . # Build argument docker build --build-arg NODE_ENV=production \ -t my-app . \end{lstlisting} \end{block} \end{frame} \begin{frame}[fragile]{Build parancsok -- Haladó} \begin{block}{Haladó build opciók} \begin{lstlisting}[language=bash,basicstyle=\scriptsize\ttfamily] # No cache (teljes újraépítés) docker build --no-cache -t my-app . # Több tag egyszerre docker build -t my-app:latest -t my-app:1.0.0 . \end{lstlisting} \end{block} \end{frame} \begin{frame}{Best Practices -- Verzió és méret} \begin{exampleblock}{Követendő gyakorlatok} \begin{itemize} \item Használj \textbf{specifikus verziókat} (\texttt{node:18.16} nem \texttt{latest}) \item \textbf{Alpine image}: kisebb méret \item \textbf{.dockerignore}: felesleges fájlok kizárása \end{itemize} \end{exampleblock} \end{frame} \begin{frame}{Best Practices -- Cache és struktúra} \begin{exampleblock}{Követendő gyakorlatok} \begin{itemize} \item \textbf{Layer cache}: függőségek előre, kód hátra \item \textbf{Multi-stage build}: kisebb production image \item \textbf{Egy konténer = egy folyamat} (ne futtass többet) \end{itemize} \end{exampleblock} \end{frame} \begin{frame}{Best Practices -- Biztonság} \begin{exampleblock}{Követendő gyakorlatok} \begin{itemize} \item \textbf{USER}: ne root userként futtass \item \textbf{HEALTHCHECK}: alkalmazás monitorozás \item RUN utasítások \textbf{kombinálása} (\&\&) \end{itemize} \end{exampleblock} \end{frame} \begin{frame}{Anti-patterns -- Biztonsági hibák} \begin{alertblock}{Biztonsági problémák} \begin{itemize} \item Jelszavak, API kulcsok a Dockerfile-ban \item Root user production-ben \item \texttt{sudo} használata Dockerfile-ban \end{itemize} \end{alertblock} \end{frame} \begin{frame}{Anti-patterns -- Alap image hibák} \begin{alertblock}{Alap image hibák} \begin{itemize} \item \texttt{FROM ubuntu} és minden manuális telepítés \item \texttt{latest} tag production-ben \end{itemize} \end{alertblock} \begin{exampleblock}{Megoldás} Használj official image-et (pl. \texttt{node:18-alpine}) \end{exampleblock} \end{frame} \begin{frame}{Anti-patterns -- Cache hibák} \begin{alertblock}{Cache és build context hibák} \begin{itemize} \item \texttt{COPY . .} a Dockerfile elejére (cache miss) \item \texttt{RUN apt-get update} külön sorban \item Nagy fájlok (logs, cache) az image-ben \end{itemize} \end{alertblock} \begin{exampleblock}{Megoldások} \begin{itemize} \item Függőségek előbb, kód később \item RUN parancsok összevonása \end{itemize} \end{exampleblock} \end{frame} \begin{frame}[fragile]{Production Dockerfile -- Builder} \begin{exampleblock}{Stage 1: Builder} \begin{lstlisting}[language=Docker,basicstyle=\scriptsize\ttfamily] FROM node:18-alpine AS builder WORKDIR /app # Függőségek telepítése COPY package*.json ./ RUN npm ci # Alkalmazás fordítása COPY . . RUN npm run build && npm prune --production \end{lstlisting} \end{exampleblock} \end{frame} \begin{frame}{Production Dockerfile -- Builder magyarázat} \begin{block}{Mit csinál?} \begin{itemize} \item Teljes node\_modules telepítés (dev + prod) \item TypeScript/Build folyamat futtatása \item Production függőségek megtartása \end{itemize} \end{block} \end{frame} \begin{frame}[fragile]{Production Dockerfile -- Alap} \begin{exampleblock}{Stage 2: Production alap} \begin{lstlisting}[language=Docker,basicstyle=\scriptsize\ttfamily] FROM node:18-alpine WORKDIR /app # Biztonsági user létrehozása RUN addgroup -S appgroup && \ adduser -S appuser -G appgroup # Csak a szükséges fájlok másolása COPY package*.json ./ COPY --from=builder /app/node_modules ./node_modules COPY --from=builder /app/dist ./dist \end{lstlisting} \end{exampleblock} \end{frame} \begin{frame}[fragile]{Production Dockerfile -- Indítás} \begin{exampleblock}{Stage 2: Konfiguráció és indítás} \begin{lstlisting}[language=Docker,basicstyle=\scriptsize\ttfamily] # Tulajdonjogok beállítása RUN chown -R appuser:appgroup /app USER appuser # Port és healthcheck EXPOSE 3000 HEALTHCHECK --interval=30s --timeout=3s \ CMD node healthcheck.js || exit 1 # Indítás ENV NODE_ENV=production CMD ["node", "dist/server.js"] \end{lstlisting} \end{exampleblock} \end{frame} \begin{frame}{Összefoglalás -- Főbb utasítások} \begin{block}{Dockerfile = Image recept} \begin{itemize} \item \texttt{FROM} -- Alap image \item \texttt{WORKDIR} -- Munka könyvtár \item \texttt{COPY} -- Fájlok másolása \end{itemize} \end{block} \end{frame} \begin{frame}{Összefoglalás -- Futtatás} \begin{block}{Parancsok és indítás} \begin{itemize} \item \texttt{RUN} -- Parancsok futtatása \item \texttt{ENV} -- Környezeti változók \item \texttt{EXPOSE} -- Port deklarálás \end{itemize} \end{block} \begin{block}{Indítás} \begin{itemize} \item \texttt{CMD} -- Indítási parancs \end{itemize} \end{block} \end{frame} \begin{frame}{Összefoglalás -- Optimalizálás} \begin{block}{Cache és méret optimalizálás} \begin{itemize} \item \textbf{Layer caching:} függőségek előre, kód hátra \item \textbf{Multi-stage build:} sokkal kisebb production image \item \textbf{.dockerignore:} tiszta build context \end{itemize} \end{block} \end{frame} \begin{frame}{Összefoglalás -- Biztonság} \begin{block}{Biztonság és monitorozás} \begin{itemize} \item \textbf{Alpine:} kompakt alap image, kisebb méret \item \textbf{USER:} ne root-ként futtass (biztonság) \item \textbf{HEALTHCHECK:} alkalmazás állapot monitorozás \end{itemize} \end{block} \begin{alertblock}{Következő lépés} Docker Image-ek kezelése, majd Docker Compose \end{alertblock} \end{frame}