← Vissza a bloghoz DevOps

Docker a CI/CD-ben: egységes szállítószalag a fejlesztéstől az élesig

A konténerek a modern CI/CD pipeline építőkövei: buildelj egyszer, futtasd mindenhol. Megnézzük, hogyan illeszkedik a Docker egy automatizált szállítószalagba.

Ha valaha is azt mondtad (vagy hallottad), hogy “nálam működik”, akkor pontosan tudod, miért született a Docker és a CI/CD ötvözete. A konténerek pont azt a problémát oldják meg, amitől a folyamatos integráció és szállítás igazán hatékony lesz: egy egyszer megépített, megváltoztathatatlan artefaktumot adsz tovább a fejlesztéstől egészen az éles környezetig. Ebben a cikkben végigvesszük, hogyan illeszkedik a Docker egy automatizált szállítószalagba, és építünk egy valódi, működő GitHub Actions pipeline-t is.

Mi az a CI/CD röviden?

A CI/CD két, egymásra épülő gyakorlat rövidítése:

  • CI (Continuous Integration) – folyamatos integráció. Minden commit után automatikusan lefuttatod a buildet és a teszteket, így a hibák azonnal kiderülnek, nem hetekkel később.
  • CD (Continuous Delivery / Deployment) – folyamatos szállítás vagy telepítés. A sikeresen tesztelt változás automatikusan eljut egy registrybe, majd onnan a staging vagy az éles környezetbe.

A lényeg az automatizálás: az ember helyett a gép végzi a monoton, hibára hajlamos lépéseket, te pedig a kódra koncentrálhatsz.

Miért illik a Docker a CI/CD-be?

A hagyományos pipeline-ok egyik örök fájdalma, hogy a fejlesztői gép, a CI runner és a szerver környezete sosem egyezik pontosan. Más a Node verzió, hiányzik egy rendszerkönyvtár, eltér a locale. A Docker ezt felszámolja egyetlen alapelvvel:

💡 Tipp: Build once, run anywhere. Egyszer megépíted az image-et, és pontosan ugyanaz a bájtsorozat fut a tesztkörnyezetben, a stagingen és az éles szerveren is. Nem buildelsz újra minden lépésben.

Az image egy megváltoztathatatlan (immutable) artefaktum. Amit leteszteltél, az fog éles üzemben futni — nincs “csak gyorsan átfordítom a szerveren” típusú meglepetés. Ha még nem vagy tisztában az alapokkal, érdemes elolvasni, Mi az a Docker? és átfutni a Hogyan működik oldalt.

Egy tipikus konténeres pipeline

A legtöbb Docker-alapú szállítószalag négy nagy szakaszra bomlik:

  1. Build – a forráskódból docker build paranccsal image készül.
  2. Test – a tesztek magában a frissen épített konténerben futnak, így pontosan azt teszteled, ami élesbe kerül.
  3. Push – a zöld build image-ét feltöltöd egy registrybe (Docker Hub, GitHub Container Registry, GitLab Registry stb.).
  4. Deploy – a célkörnyezet lehúzza és elindítja az új image-et.

A kulcs a második lépés: nem a runner csupasz gépén tesztelsz, hanem a konténerben. Így a tesztkörnyezet bitre azonos a produkcióssal.

Konkrét példa: GitHub Actions pipeline

Nézzünk egy valódi, copy-paste-elhető workflow-t, amely megépíti és feltölti az image-et a GitHub Container Registrybe (ghcr.io). Hozd létre a .github/workflows/docker.yml fájlt:

name: Build and push image

on:
  push:
    branches: [main]
    tags: ["v*"]

env:
  IMAGE_NAME: ghcr.io/${{ github.repository }}

jobs:
  build:
    runs-on: ubuntu-latest
    permissions:
      contents: read
      packages: write
    steps:
      - name: Checkout
        uses: actions/checkout@v4

      - name: Set up Buildx
        uses: docker/setup-buildx-action@v3

      - name: Log in to GHCR
        uses: docker/login-action@v3
        with:
          registry: ghcr.io
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}

      - name: Extract metadata
        id: meta
        uses: docker/metadata-action@v5
        with:
          images: ${{ env.IMAGE_NAME }}
          tags: |
            type=sha,prefix=,format=short
            type=ref,event=branch
            type=semver,pattern={{version}}

      - name: Build and push
        uses: docker/build-push-action@v6
        with:
          context: .
          push: true
          tags: ${{ steps.meta.outputs.tags }}
          labels: ${{ steps.meta.outputs.labels }}
          cache-from: type=gha
          cache-to: type=gha,mode=max

Ez a workflow minden main-re érkező push és minden v* tag esetén lefut, bejelentkezik a registrybe, kiszámolja a megfelelő tageket, majd megépíti és feltölti az image-et.

Tesztelés a buildelt konténerben

A build előtt érdemes egy külön lépésben lefuttatni a teszteket. Ha multi-stage Dockerfile-od van egy test célállomással, ezt akár így is megteheted:

      - name: Run tests in container
        run: |
          docker build --target test -t app:test .
          docker run --rm app:test

Így a teszt pontosan abban a környezetben fut, amit utána szállítasz.

Image tagging: a git SHA a barátod

A tagelési stratégia fontosabb, mint elsőre tűnik. A leggyakoribb hibákról külön is olvashatsz a 10 gyakori Docker hiba cikkben, de a CI/CD szempontjából a legfontosabb szabály:

⚠️ Figyelem: Soha ne támaszkodj a latest tagre a pipeline-odban! A latest változik, nem reprodukálható, és lehetetlen visszakövetni, melyik kód fut éppen. Mindig használj egyedi, megváltoztathatatlan tageket.

A bevett gyakorlat, hogy minden image-et a hozzá tartozó git commit SHA-jával tagelsz (a fenti workflow type=sha sora pontosan ezt csinálja). Így bármikor egyértelmű, melyik forráskódból készült egy adott image.

Tag típusPéldaMire jó
Git SHAa1b2c3dPontos, reprodukálható azonosítás
Semver1.4.2Emberek számára olvasható kiadás
BranchmainMozgó mutató a legutóbbi állapotra
latestlatestKényelmes, de ne a deployhoz

A deployban a SHA-s vagy a semver tagre hivatkozz, a main/latest legfeljebb kényelmi mutató maradjon.

Build cache: gyorsabb pipeline-ok

A CI runner minden futáskor tiszta lappal indul, így alapból minden réteget újraépítene. A fenti példában a cache-from/cache-to sorok a GitHub Actions cache-ét (type=gha) használják, így a változatlan rétegek a következő futásnál a cache-ből jönnek.

A cache hatékonysága azon múlik, mennyire jól van rendezve a Dockerfile-od. Az alapszabály: a ritkán változó dolgok (függőségek telepítése) kerüljenek előre, a gyakran változó forráskód hátra. Erről részletesen is írunk a Dockerfile írása lépésről lépésre cikkben — ott látható az a minta is, amikor a package.json-t a forrás előtt másolod be, hogy a függőség-réteg cache-elhető maradjon.

# A függőségek réteg ritkán változik -> cache-elhető
COPY package*.json ./
RUN npm ci

# A forrás gyakran változik -> ez a réteg invalidálódik csak
COPY . .

Összefoglalás

A Docker és a CI/CD természetes partnerek: a konténer az a megváltoztathatatlan artefaktum, amit egyszer megépítesz, leteszteled, majd változatlanul szállítasz tovább. Egy jól felépített pipeline a forrásból image-et épít, a konténerben tesztel, SHA-val tagelve registrybe tölt, majd onnan deployol — mindezt automatikusan, a latest tag csapdáját elkerülve és a build cache-t kihasználva. Ettől lesz a “nálam működik” helyett “mindenhol ugyanúgy működik”.

Ha most kezded a Docker-utadat, nézd meg a Kezdő lépések útmutatót, vagy ha kíváncsi vagy, miért érdemes egyáltalán belevágni, olvasd el a Miért a Docker? oldalt. Aztán fogd a saját projekted, írj rá egy Dockerfile-t, és kösd be egy pipeline-ba — meglátod, mennyivel nyugodtabb lesz a deploy.