Containerization Checklist

From Dockerfiles to Kubernetes orchestration — a structured checklist for containerizing applications with security, performance, and production readiness.

Checklist: Containerization (engineering)

Containerization packages your application and its dependencies into portable, reproducible units that run consistently across environments. Done right, containers eliminate "works on my machine" issues, enable horizontal scaling, and simplify deployment. Done wrong, they introduce security vulnerabilities, bloated images, and operational complexity. This checklist ensures you get it right.

Checklist Items

  1. Write a multi-stage Dockerfile [critical]: Use multi-stage builds to separate build dependencies from runtime. Final image should contain only the compiled app and runtime deps.
  2. Use minimal base images [critical]: Start from Alpine, distroless, or slim images instead of full Ubuntu/Debian. Smaller images mean faster pulls and smaller attack surface.
  3. Scan images for vulnerabilities [critical]: Integrate Trivy, Snyk, or Docker Scout into CI/CD to catch known CVEs before images reach production.
  4. Do not run containers as root [important]: Create a non-root user in the Dockerfile and use the USER directive. Running as root in production is a serious security risk.
  5. Configure health checks [important]: Add HEALTHCHECK instructions to Dockerfiles and liveness/readiness probes in Kubernetes for reliable container lifecycle management.
  6. Set resource limits (CPU and memory) [important]: Define resource requests and limits in Kubernetes or Docker Compose to prevent single containers from consuming all host resources.
  7. Externalize configuration via environment variables [important]: Use environment variables or mounted config files for all environment-specific settings. Never bake secrets into images.
  8. Tag images with specific versions [recommended]: Use semantic version tags or Git SHA tags — never deploy with :latest in production. Pin all base image versions.
  9. Set up a container registry with access controls [recommended]: Use ECR, GCR, or Docker Hub with private repos. Restrict push access to CI/CD pipelines only.
  10. Implement graceful shutdown handling [recommended]: Handle SIGTERM signals to drain connections, complete in-flight requests, and release resources before container termination.

Common Mistakes

  • Bloated images with build tools included: Use multi-stage builds. Your runtime image should not include compilers, package managers, or source code.
  • Storing secrets in environment variables in the Dockerfile: Use Docker secrets, Kubernetes secrets, or external secret managers. ENV directives in Dockerfiles are visible in image layers.
  • Ignoring container logging: Log to stdout and stderr. Use a log aggregator to collect container output — do not write logs to files inside containers.

Frequently Asked Questions

Docker Compose or Kubernetes?
Docker Compose for local development and simple deployments with 2-5 containers. Kubernetes for production workloads needing auto-scaling, rolling updates, and service mesh. Many teams use both — Compose for dev, Kubernetes for prod.
How small should my container image be?
Aim for under 100 MB for most applications. Node.js apps can be under 50 MB with Alpine. Go and Rust apps can be under 20 MB with distroless or scratch base images.
Should I use Docker or Podman?
Docker is the industry standard with the largest ecosystem. Podman is rootless and daemonless, making it better for security-sensitive environments. Both use the same image format — choose based on your security and infrastructure requirements.