Secure your containers from development to production. Common mistakes and how to fix them.
Start with minimal images like Alpine or distroless. Less software = smaller attack surface.
Containers running as root can escape to host. Always use a non-root user.
Base images and dependencies may have known CVEs. Scan before deploying.
Secrets in Dockerfiles or images persist in layers and can be extracted.
Keep build tools out of production images. Reduces size and attack surface.
ENV API_KEY=sk-xxxFix: Pass secrets at runtime: docker run -e API_KEY=$API_KEY
FROM node:latestFix: Pin specific versions: FROM node:20.11-alpine
No USER directiveFix: Add: RUN adduser -D appuser && USER appuser
EXPOSE 22 (SSH in container)Fix: Only expose ports your app needs. Never SSH into containers.
COPY . .Fix: Use .dockerignore. Copy only what's needed.
# Use specific version, minimal base FROM node:20.11-alpine AS builder WORKDIR /app # Copy package files first (cache dependencies) COPY package*.json ./ RUN npm ci --only=production # Copy source code COPY src/ ./src/ # Build RUN npm run build # Production stage - minimal image FROM node:20.11-alpine # Create non-root user RUN addgroup -S appgroup && adduser -S appuser -G appgroup WORKDIR /app # Copy only production artifacts COPY --from=builder /app/dist ./dist COPY --from=builder /app/node_modules ./node_modules # Set ownership and switch to non-root RUN chown -R appuser:appgroup /app USER appuser # Don't run as PID 1 CMD ["node", "dist/index.js"]
This template demonstrates: minimal base images, multi-stage builds, non-root user, and proper layer ordering.
VAS scans your deployed applications for security issues— including exposed secrets that might have leaked from Docker images.
Free Security ScanNo. Docker provides isolation but defaults aren't hardened. Containers run as root by default, images may have vulnerabilities, and secrets can leak into layers. You need to actively implement security practices—use non-root users, scan images, and properly manage secrets.
Yes, especially if running as root or with privileged mode. Container escapes are real vulnerabilities. Mitigate by: never using --privileged, running as non-root, keeping Docker updated, and using security tools like AppArmor or seccomp profiles.
Never put secrets in Dockerfiles or images. Options: Docker secrets (Swarm), Kubernetes secrets, environment variables at runtime (not build time), or secret managers like Vault, AWS Secrets Manager. For development, use .env files that aren't copied into images.
Alpine is good for most use cases—small but has a shell for debugging. Distroless is more secure (no shell, minimal binaries) but harder to debug. Start with Alpine, consider distroless for high-security production workloads where you don't need shell access.
At minimum, weekly to pick up security patches in base images. Better: trigger rebuilds when base images update. Use tools like Dependabot or Renovate to track base image updates. Critical CVEs should trigger immediate rebuilds.
Last updated: January 16, 2026