← Vissza a bloghoz Útmutató

Dockerfile írása lépésről lépésre

Tanuld meg megírni az első saját Dockerfile-od. Végigvesszük a FROM, WORKDIR, COPY, RUN, EXPOSE és CMD utasításokat egy valódi példán keresztül.

Eddig kész image-eket futtattál a Docker Hubról, de a Docker igazi ereje akkor mutatkozik meg, amikor saját image-et építesz a saját alkalmazásodhoz. Ennek receptje a Dockerfile: egy egyszerű szöveges fájl, amely lépésről lépésre leírja, hogyan épüljön fel az image-ed. Ebben a cikkben végigvesszük a legfontosabb utasításokat, majd egy valódi Node.js alkalmazáshoz közösen megírunk egy teljes Dockerfile-t. A végére képes leszel a saját projektedet is konténerizálni!

Mi az a Dockerfile?

A Dockerfile egy Dockerfile nevű (kiterjesztés nélküli) szöveges fájl, amely utasítások sorozatából áll. Minden utasítás egy lépést ír le az image felépítésében, és többségük egy új réteget hoz létre. A Docker fentről lefelé, sorban hajtja végre őket, amikor lefuttatod a docker build parancsot.

Nézzük meg az utasításokat egyenként, mielőtt összerakjuk a teljes példát.

Az alapvető utasítások

FROM – az alapimage

Minden Dockerfile egy FROM utasítással kezdődik, amely megadja, milyen alapimage-ből indulsz. Ez lehet egy operációs rendszer vagy egy nyelvi futtatókörnyezet.

FROM node:22-alpine

Itt a Node.js 22-es verzióját választottuk az alpine változatban, amely egy minimális, kis méretű Linux disztribúción alapul. A kisebb alapimage gyorsabb buildet és kisebb végeredményt jelent.

WORKDIR – a munkakönyvtár

A WORKDIR beállítja az aktuális munkakönyvtárat a konténeren belül. Az ezután következő utasítások (COPY, RUN, CMD) ehhez képest értelmeződnek. Ha a könyvtár nem létezik, a Docker létrehozza.

WORKDIR /app

COPY – fájlok másolása

A COPY a build contextből (a gazdagépedről) másol fájlokat az image-be. Az első paraméter a forrás, a második a célhely a konténeren belül.

COPY package.json package-lock.json ./

RUN – parancs futtatása build közben

A RUN egy parancsot futtat le az image építése során, és az eredményt egy új rétegként menti. Tipikusan függőségek telepítésére használjuk.

RUN npm ci --omit=dev

ENV – környezeti változók

Az ENV környezeti változókat állít be, amelyek a build során és a futó konténerben is elérhetők lesznek.

ENV NODE_ENV=production

EXPOSE – a figyelt port dokumentálása

Az EXPOSE jelzi, hogy az alkalmazás melyik porton figyel. Fontos tudni: ez önmagában nem nyitja meg a portot, csak dokumentál. A tényleges port-leképezést a docker run -p kapcsolóval végzed.

EXPOSE 3000

CMD és ENTRYPOINT – mi induljon a konténerben

A CMD megadja az alapértelmezett parancsot, amely a konténer indulásakor lefut. Ezt felül lehet írni a docker run után megadott paraméterekkel. Az ENTRYPOINT ezzel szemben a fő futtatható parancsot rögzíti, amelyet nem írnak felül olyan könnyen. A kettő gyakran együtt használatos: az ENTRYPOINT adja a programot, a CMD az alapértelmezett argumentumokat.

CMD ["node", "server.js"]

💡 Tipp: Mindig az úgynevezett „exec” formátumot használd (szögletes zárójeles JSON-tömb, pl. ["node", "server.js"]), ne a „shell” formátumot. Az exec forma helyesen kezeli a leállítási jelzéseket, így a konténered szabályosan tud leállni.

A teljes példa: egy Node.js alkalmazás

Most rakjuk össze az egészet egy valódi kis Node.js alkalmazáshoz. Tegyük fel, hogy van egy server.js fájlod és egy package.json-od. Így néz ki a teljes Dockerfile:

# Alapimage: Node.js 22 a kis méretű Alpine változaton
FROM node:22-alpine

# Munkakönyvtár a konténeren belül
WORKDIR /app

# Először csak a függőséglistát másoljuk (a cache miatt)
COPY package.json package-lock.json ./

# Függőségek telepítése
RUN npm ci --omit=dev

# Most másoljuk a teljes alkalmazáskódot
COPY . .

# Környezeti változó
ENV NODE_ENV=production

# Az alkalmazás a 3000-es porton figyel
EXPOSE 3000

# Indítóparancs
CMD ["node", "server.js"]

Az image megépítése

Ha kész a Dockerfile, az image megépítése egyetlen paranccsal történik:

docker build -t sajat-app:1.0 .

A kapcsolók jelentése:

  • -t sajat-app:1.0 – Nevet (sajat-app) és tagot (1.0) ad az image-nek.
  • . – A build context, vagyis az aktuális könyvtár, ahonnan a Docker a fájlokat eléri.

A build után máris futtathatod:

docker run -d -p 3000:3000 --name app sajat-app:1.0

Miért fontos a rétegek sorrendje? A cache

Biztosan feltűnt, hogy a példában előbb csak a package.json-t másoltuk és telepítettük a függőségeket, és csak utána másoltuk a teljes kódot. Ez nem véletlen.

A Docker minden réteget gyorsítótáraz (cache-el). Ha egy réteg bemenete nem változott, akkor a Docker újra felhasználja a korábbi eredményt ahelyett, hogy újra lefuttatná. A függőségek telepítése (npm ci) a leglassabb lépés, ezért érdemes úgy szervezni a Dockerfile-t, hogy ez csak akkor fusson le újra, ha tényleg változott a package.json.

Mivel a kódod sűrűbben változik, mint a függőségeid, ezzel a sorrenddel a legtöbb buildnél a Docker megspórolja a teljes függőségtelepítést. A szabály egyszerű: a ritkán változó dolgok kerüljenek előre, a gyakran változók hátra.

A .dockerignore fájl

A docker build . parancs a teljes aktuális könyvtárat átküldi a Dockernek build contextként. Ha ide bekerül a node_modules, a .git vagy más felesleges fájl, a build lassú lesz, és akár nem kívánt dolgok is bekerülhetnek az image-be.

A megoldás egy .dockerignore fájl, amely a .gitignore-hoz hasonlóan kihagyja a felesleges fájlokat:

node_modules
.git
.env
*.log
Dockerfile

⚠️ Figyelem: A node_modules kihagyása különösen fontos Node.js-nél. A függőségeket a konténeren belül telepítjük a RUN npm ci lépésben, így a gazdagépről bemásolt node_modules nemcsak felesleges, de platformeltérések miatt hibákat is okozhat.

Egy szó a többlépcsős buildről

Ha még kisebb és biztonságosabb image-et szeretnél, érdemes megismerkedned a többlépcsős (multi-stage) buildekkel. Ennek lényege, hogy egy lépcsőben megépíted az alkalmazást (például lefordítod), egy másikban pedig csak a kész eredményt másolod át egy minimális image-be, a build eszközök nélkül. Ez egy haladóbb téma, amelyre egy külön cikkben térünk vissza, de a most tanult alapokra épül.

Összefoglalás

  • A Dockerfile lépésről lépésre írja le, hogyan épüljön fel az image-ed.
  • A legfontosabb utasítások: FROM (alapimage), WORKDIR (munkakönyvtár), COPY (fájlmásolás), RUN (parancs buildkor), ENV (változók), EXPOSE (port), CMD/ENTRYPOINT (indítóparancs).
  • A docker build -t név:tag . paranccsal építed meg az image-et.
  • A rétegek okos sorrendezésével (függőségek előre) kihasználod a cache-t, és gyorsabb lesz a build.
  • A .dockerignore fájllal kihagyod a felesleges fájlokat a build contextből.

Most már képes vagy saját image-et építeni, ez óriási lépés! A következő téma a több konténer együttes kezelése: ehhez olvasd el a Docker Compose bevezető cikket. Ha még az alapfogalmakban bizonytalan vagy, nézd át a Docker alapfogalmak kisszótárt, vagy térj vissza a Kezdő lépések oldalra.