Optimizing a Bloated Production Container Image
Scenario Prompt:
“A team reports that their Node.js production image takes 4 minutes to download and deploy because it weighs 1.8 GB. Security scanners also flag dozens of high-severity CVEs from build packages. How do you re-architect the Dockerfile?”
Substantive Technical Concepts to Hit:
Multi-Stage Build Separation
Use a builder stage with npm install to compile dependencies, then copy only production node_modules and built artifacts to a clean runtime stage.
Minimal Base Image Selection
Replace heavy full-OS images (node:20) with lightweight Alpine, distroless, or slim Debian variants.
Layer Cache Ordering
Copy package.json and lockfiles first, run dependency installation, and copy application source code in subsequent layers to preserve caching.
Unprivileged Runtime User
Add a dedicated non-root application user and switch using USER node before the CMD instruction.
- Does the application require native C++ addon compilation that Alpine musl libc might complicate?
- Are we building images in CI with access to a shared remote registry cache or local BuildKit cache?
- What vulnerability scanning thresholds (e.g., Trivy or Grype) must the final image pass?