Docker maakt het eenvoudig om applicaties te containerizen, maar de standaardinstellingen zijn verre van veilig. Containers die als root draaien, bloated images met onnodige packages en ontbrekende resource limits vormen serieuze risicos. In deze hands-on tutorial doorlopen we elke stap om uw Docker containers production-ready en veilig te maken.
Minimale base images en multi-stage builds
De eerste regel van container security: minimaliseer het aanvalsoppervlak. Gebruik Alpine Linux (5 MB) of distroless images in plaats van volledige Ubuntu of Debian images. Elk extra package in uw image is een potentiële kwetsbaarheid. Met multi-stage builds compileert u uw applicatie in een builder-stage met alle development tools, en kopieert u alleen het uiteindelijke artefact naar een minimaal runtime image.
Scan uw images regelmatig met tools als Trivy, Snyk of Docker Scout. Integreer dit in uw CI/CD pipeline zodat kwetsbare images nooit in productie komen. Pin uw base image versies met een specifieke digest hash in plaats van mutable tags zoals :latest om supply chain risicos te voorkomen.
# Optimaal Dockerfile met multi-stage build
# Stage 1: Build
FROM node:20-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY . .
RUN npm run build
# Stage 2: Runtime (minimaal image)
FROM gcr.io/distroless/nodejs20-debian12
WORKDIR /app
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/node_modules ./node_modules
# Draai als non-root gebruiker (uid 1000)
USER 1000
EXPOSE 3000
CMD ["dist/server.js"]
Non-root users, read-only filesystems en resource limits
Containers draaien standaard als root — een enorm beveiligingsrisico. Als een aanvaller uit de container breekt, heeft hij root-toegang op de host. Gebruik altijd de USER directive in uw Dockerfile om als non-root gebruiker te draaien. Maak een dedicated gebruiker aan of gebruik de ingebouwde node, www-data of nobody gebruiker.
Draai containers met een read-only root filesystem via --read-only. Mount alleen specifieke directories als writable waar uw applicatie tijdelijke bestanden moet schrijven. Stel ook altijd resource limits in met --memory en --cpus om te voorkomen dat een gecompromitteerde container het hele systeem kan uitputten. Drop alle Linux capabilities met --cap-drop ALL en voeg alleen de strikt noodzakelijke terug.
- Gebruik distroless of Alpine als base image — vermijd bloated images
- Draai altijd als non-root met de USER directive
- Activeer read-only root filesystem met --read-only flag
- Stel memory en CPU limits in voor elke container
- Drop alle capabilities met --cap-drop ALL en voeg alleen noodzakelijke toe
- Scan images met Trivy of Snyk in uw CI/CD pipeline
Runtime beveiliging en secrets in Docker
Build-time security is slechts de helft van het verhaal. Gebruik Docker's seccomp profiel om syscalls te beperken en AppArmor of SELinux voor mandatory access control. Schakel ook --no-new-privileges in om te voorkomen dat processen in de container hun privileges kunnen verhogen na het starten.
Sla nooit secrets op in Docker images of environment variables. Gebruik Docker Secrets (in Swarm) of externe secret managers zoals HashiCorp Vault. Voor development kunt u Docker Compose met een .env bestand gebruiken dat in .gitignore staat. In productie mount u secrets als bestanden in een tmpfs volume met restrictieve permissions (0400). Vergeet niet om uw Docker daemon zelf ook te beveiligen: activeer TLS, beperk API-toegang en houd Docker up-to-date.
Pro Tip
Draai nu docker run --rm -v /var/run/docker.sock:/var/run/docker.sock aquasec/trivy image <uw-image> op uw productiemages. U zult waarschijnlijk kritieke kwetsbaarheden vinden in uw base images. Schakel daarna over naar een distroless of Alpine base image, voeg USER 1000 toe aan elk Dockerfile, en u hebt in minder dan een uur 80% van de meest voorkomende container-kwetsbaarheden geëlimineerd.
Deel dit artikel