„Kontejnery jsou izolované, takže jsou bezpečné.” Tohle jsme si mysleli, než nám penetrační tester během půl hodiny eskaloval z kontejneru na root hosta. Kontejnery nejsou VM a bezpečnostní model je zásadně odlišný.
Kontejner není sandbox¶
Docker kontejner sdílí jádro s hostem. Namespace a cgroups poskytují izolaci procesů, síťového stacku a souborového systému — ale není to hardwarová virtualizace. Kernel exploit v kontejneru = kernel exploit na hostu. Tohle je fundamentální rozdíl oproti VM a musí se s ním počítat.
To neznamená, že kontejnery jsou nebezpečné. Znamená to, že bezpečnost musíte řešit na všech vrstvách — od base image přes build pipeline až po runtime konfiguraci.
Base image — minimalizujte útočnou plochu¶
Každý balíček v image je potenciální zranitelnost. Ubuntu base image má stovky balíčků, které vaše aplikace nepotřebuje — a každý z nich může mít CVE. Pravidlo číslo jedna: použijte minimální base image.
# ❌ Špatně — plný Ubuntu, 188 MB, stovky balíčků
FROM ubuntu:16.04
# ✅ Lépe — Alpine, 5 MB, minimální balíčky
FROM alpine:3.6
# ✅ Nejlépe — distroless, jen runtime
FROM gcr.io/distroless/java:latest
Alpine Linux je dobrý kompromis — 5 MB, musl libc, apk package manager.
Pro maximální bezpečnost zvažte distroless images od Googlu:
žádný shell, žádný package manager, žádné utility. Útočník, který se
dostane do kontejneru, nemá k dispozici ani ls.
Multi-stage builds — oddělte build a runtime¶
Build nástroje (gcc, npm, maven) nemají co dělat v produkčním image. Multi-stage build oddělí kompilaci od finálního image.
FROM golang:1.9 AS builder
WORKDIR /app
COPY . .
RUN CGO_ENABLED=0 go build -o server .
FROM alpine:3.6
RUN adduser -D -u 1001 appuser
COPY --from=builder /app/server /server
USER appuser
EXPOSE 8080
CMD ["/server"]
Výsledný image obsahuje jen binárku a Alpine. Žádný Go toolchain, žádné zdrojové kódy, žádné build závislosti. Menší image = menší útočná plocha = rychlejší deploy.
Neběžte jako root¶
Překvapivě mnoho Docker images běží jako root. Pokud aplikace nepotřebuje privilegovaný port nebo přístup k systémovým resources, vždy přidejte USER directive. Root v kontejneru může za určitých okolností eskalovat na root hosta.
V Kubernetes použijte securityContext na úrovni podu:
securityContext:
runAsNonRoot: true
runAsUser: 1001
readOnlyRootFilesystem: true
allowPrivilegeEscalation: false
capabilities:
drop: ["ALL"]
readOnlyRootFilesystem zabrání zápisu do souborového systému
kontejneru — útočník nemůže persistovat malware. drop ALL capabilities
odebere Linux capabilities, které aplikace nepotřebuje.
Image scanning — najděte CVE dřív než útočník¶
Každý image by měl projít vulnerability scannerem před nasazením do produkce. Nástroje jako Clair, Trivy nebo Anchore analyzují vrstvy image a porovnávají balíčky s CVE databázemi.
My skenujeme na dvou místech: v CI pipeline (build time) a v registry (continuous scan). Build time scan zastaví deploy s kritickými CVE. Continuous scan odhalí nově objevené zranitelnosti v images, které už běží v produkci.
Klíčové je nastavit policy: co je akceptovatelné a co ne. Nulová tolerance na kritické CVE v base image. Medium severity s plánem opravy do 30 dní. Low severity sledovat, ale neblokovat deploy.
Supply chain — důvěřuj, ale prověřuj¶
docker pull node:latest — víte, co přesně stahujete?
Kdo ten image vytvořil? Byl modifikován? Docker Content Trust
(Notary) umožňuje podepisování images. Povolte ho a akceptujte jen
podepsané images.
Používejte konkrétní tagy, ne :latest.
Ještě lépe: pinujte na digest. Tag může být přepsán,
digest je immutable hash. A provozujte vlastní registry (Harbor, GitLab
Registry) místo přímého stahování z Docker Hub.
Runtime ochrana¶
Build-time bezpečnost nestačí. V runtime potřebujete detekci anomálií.
Seccomp profily omezují systémová volání — kontejner,
který normálně dělá HTTP requesty, nemá důvod volat ptrace
nebo mount. AppArmor nebo SELinux
profily přidávají další vrstvu mandatory access control.
Network policies v Kubernetes fungují jako firewall mezi pody. Default deny — žádný pod nekomunikuje s jiným, pokud to explicitně nepovolíte. Mikroslužba pro platby nemá důvod komunikovat s CMS.
Secrets management¶
Nikdy nepečte secrets do image. Ani jako environment variable v Dockerfile, ani jako soubor v build kontextu. Secrets patří do Kubernetes Secrets (ideálně s externím backendem jako HashiCorp Vault), mountované jako volumes, rotované automaticky.
Skenujte historii image vrstev — docker history ukáže
všechny vrstvy včetně smazaných souborů. Secret přidaný a pak
smazaný v dalším RUN příkazu je stále v předchozí vrstvě.
Security jako continuous process¶
Container security není jednorázový audit. Je to kontinuální proces integrovaný do celého životního cyklu — od Dockerfile přes CI pipeline až po runtime monitoring. Začněte základy: non-root, minimální image, scanning v CI. Postupně přidávejte seccomp, network policies, runtime detekci. Každá vrstva ztěžuje útočníkovi práci.
Brauchen Sie Hilfe bei der Implementierung?
Unsere Experten helfen Ihnen bei Design, Implementierung und Betrieb. Von der Architektur bis zur Produktion.
Kontaktieren Sie uns