← Vissza a bloghoz Biztonság

Titkok kezelése Dockerben: jelszavak és API-kulcsok biztonságosan

Soha ne süsd bele a jelszavakat az image-be! Megnézzük az environment változók buktatóit, a Docker secrets-et, a build secrets-et és a .env fájlok helyes használatát.

Szinte minden valós alkalmazásnak szüksége van titkokra: adatbázis-jelszóra, API-kulcsra, tokenekre, privát kulcsokra. A kérdés nem az, hogy vannak-e titkaid, hanem hogy hogyan kezeled őket. Ez az a terület, ahol nagyon könnyű hibázni, és a hibák költségesek lehetnek — egy publikus registry-be feltöltött image-ben felejtett API-kulcs órákon belül vissza is élhet vele valaki. Ebben a cikkben végigvesszük, miért veszélyes a titkokat az image-be sütni, milyen buktatói vannak az environment változóknak, és milyen biztonságos megoldások közül választhatsz.

Miért ne süsd bele a titkokat az image-be?

A legrosszabb, amit tehetsz, hogy a titkot közvetlenül a Dockerfile-ba írod:

# SOHA ne csináld ezt!
ENV DB_PASSWORD=szupertitkos123
RUN curl -H "Authorization: Bearer abc123token" https://api.pelda.hu/setup

A probléma alapvető és nem megkerülhető: a Docker image rétegekből áll, és minden réteg megőrzi a tartalmát. Még ha egy későbbi rétegben “törlöd” is a titkot, az ott marad egy korábbi rétegben. Bárki, aki hozzáfér az image-hez, ki tudja nyerni:

docker history --no-trunc myapp:latest
docker save myapp:latest | tar -xf -

A docker history megmutathatja az ENV és RUN sorokat a beégetett értékekkel, a docker save pedig kicsomagolja a teljes réteg-tartalmat. Ha az image bekerül egy publikus vagy megosztott registry-be, a titok gyakorlatilag nyilvános.

⚠️ Figyelem: Egy image-be sütött titkot nem lehet “visszavonni” azzal, hogy építesz egy újabb verziót. Ha egyszer kiszivárgott, a titkot magát kell lecserélned (rotálnod) — a jelszót, a kulcsot, a tokent.

Az environment változók buktatói

Sokan az ENV helyett futásidejű környezeti változókra váltanak, ami már jobb, de nem hibátlan:

docker run -e DB_PASSWORD=szupertitkos123 myapp

Ez nem kerül bele az image rétegeibe, de így is van néhány szivárgási kockázat:

  • A környezeti változók láthatók a docker inspect kimenetében bárki számára, aki hozzáfér a daemonhoz.
  • A folyamatok /proc/<pid>/environ fájljából kiolvashatók a konténeren belül.
  • Gyakran bekerülnek a logokba, hibajelentésekbe, crash dumpokba.
  • A parancssorban (-e kapcsoló) megjelennek a shell history-ban és a futó folyamatok listájában.

Az environment változók tehát kényelmesek, de nem ideálisak igazán érzékeny titkokhoz. Konfigurációhoz (pl. LOG_LEVEL, PORT) tökéletesek, de jelszavakhoz és kulcsokhoz érdemes robusztusabb megoldást keresni.

.env fájlok Compose-szal

Fejlesztés közben kényelmes a titkokat egy .env fájlban tartani, amit a Docker Compose automatikusan beolvas:

# .env
POSTGRES_PASSWORD=fejlesztoi_jelszo
API_KEY=helyi_teszt_kulcs
services:
  db:
    image: postgres:16
    environment:
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}

A legfontosabb szabály: a .env fájl soha ne kerüljön verziókezelésbe. Mindig vedd fel a .gitignore-ba és a .dockerignore-ba is:

# .gitignore és .dockerignore
.env
*.env

💡 Tipp: A .env fájl remek fejlesztői kényelmi megoldás, de éles környezetben gyenge. Ott válts valódi secret-kezelésre — Docker secrets vagy külső titokkezelő. A Compose alapokhoz nézd meg a Docker Compose bevezető cikket.

Docker secrets

A Docker secrets mechanizmus a titkokat nem környezeti változóként, hanem fájlként teszi elérhetővé a konténer számára, jellemzően a /run/secrets/ könyvtárban. Ez kikerüli az environment változók legtöbb szivárgási kockázatát. Compose-ban így néz ki:

services:
  app:
    image: myapp:latest
    secrets:
      - db_password

secrets:
  db_password:
    file: ./db_password.txt

A konténerben az alkalmazás a /run/secrets/db_password fájlból olvassa ki az értéket. Mivel ez fájl, nem szerepel a docker inspect környezeti változói között, és nem szivárog be olyan könnyen a logokba. Sok hivatalos image (például a postgres) támogatja a _FILE utótagú változatot, amely közvetlenül egy fájlból olvas:

services:
  db:
    image: postgres:16
    environment:
      POSTGRES_PASSWORD_FILE: /run/secrets/db_password
    secrets:
      - db_password

secrets:
  db_password:
    file: ./db_password.txt

Docker Swarm módban a secrets ráadásul titkosítva tárolódik és titkosított csatornán jut el a node-okhoz, ami éles környezetben jelentős előny.

BuildKit build secrets

Mi van akkor, ha a build során van szükséged egy titokra — például egy privát csomagregisztrációhoz kell egy token, de nem akarod, hogy az bekerüljön az image-be? Erre való a BuildKit build secrets. A titok csak az adott RUN lépés idejére, memóriában érhető el, és nem kerül bele egyetlen rétegbe sem.

A Dockerfile-ban a RUN --mount=type=secret szintaxist használod:

# syntax=docker/dockerfile:1
FROM alpine:3.20

RUN --mount=type=secret,id=npm_token \
    NPM_TOKEN=$(cat /run/secrets/npm_token) && \
    echo "Token használata a buildhez..." && \
    # itt használod a tokent, pl. privát csomag letöltéséhez
    true

A buildet pedig a --secret kapcsolóval indítod:

docker build --secret id=npm_token,src=./npm_token.txt -t myapp .

A titok így átmenetileg felcsatolódik a /run/secrets/npm_token útvonalra a build alatt, de a kész image-ben semmi nyoma. Ellenőrizheted is: a docker history nem fogja megmutatni. Ez a build során használt titkok kezelésének helyes módja.

💡 Tipp: A # syntax=docker/dockerfile:1 sor a Dockerfile elején biztosítja, hogy a modern BuildKit szintaxis (köztük a --mount=type=secret) elérhető legyen. A Docker Engine 23+ alapból BuildKit-tel buildel.

Külső titokkezelők

Nagyobb, éles rendszerekben érdemes dedikált titokkezelőt használni, amely központilag tárolja, titkosítja, auditálja és rotálja a titkokat. A leggyakoribbak:

  • HashiCorp Vault — sokoldalú, dinamikus titkokkal és szigorú hozzáférés-szabályozással.
  • AWS Secrets Manager / GCP Secret Manager / Azure Key Vault — felhőszolgáltatói megoldások, mély integrációval.
  • Kubernetes Secrets (külső kezelővel kombinálva) — ha Kubernetesen futtatsz.

Ezek lényege, hogy a titok soha nem kerül se az image-be, se a verziókezelésbe; az alkalmazás futásidőben, hitelesítve kéri le a titokkezelőtől. Cserébe a titkokat egy helyen kezeled, könnyen rotálod, és pontosan tudod, ki mikor fért hozzá.

Összefoglalás

A titokkezelés aranyszabálya egyszerű: soha ne süsd bele a titkokat az image-be, mert a rétegek megőrzik őket. Az environment változók kényelmesek, de szivárognak (inspect, logok, /proc), ezért érzékeny adathoz csak óvatosan. Fejlesztéshez használj .env fájlt, amit kihagysz a verziókezelésből; futás közben Docker secrets-et fájl alapú átadással; buildhez BuildKit build secrets-et a --secret és RUN --mount=type=secret párossal; éles, nagyobb rendszerekben pedig dedikált titokkezelőt.

Nézd át a saját Dockerfile-jaidat és Compose fájljaidat még ma — keress beégetett jelszavakat és kulcsokat, és cseréld le őket biztonságos megoldásra! A tágabb képhez olvasd el a Docker biztonsági alapok cikket, és ha a Dockerfile felépítését csiszolnád, a Dockerfile írása lépésről lépésre útmutató segít.