Back to Blog
team@tinypod.app

Docker Image Optimization: Shrink Your Containers by 90%

Large Docker images waste bandwidth, slow deployments, and increase attack surface. Here's how to dramatically reduce image size.

dockeroptimizationdevops

Why Image Size Matters


A 1.2 GB Node.js image vs a 120 MB optimized one:

  • Pulls 10x faster
  • Deploys 10x faster
  • Uses less disk on every server
  • Has fewer packages = fewer vulnerabilities

  • Multi-Stage Builds


    The single most impactful optimization. Build in one stage, copy only artifacts to a minimal runtime stage.


    Before: 1.2 GB

    FROM node:20

    COPY . .

    RUN npm install

    RUN npm run build

    CMD ["node", "dist/index.js"]


    After: 150 MB

    FROM node:20 AS builder

    COPY . .

    RUN npm install && npm run build


    FROM node:20-alpine

    COPY --from=builder /app/dist ./dist

    COPY --from=builder /app/node_modules ./node_modules

    CMD ["node", "dist/index.js"]


    Use Alpine Base Images


    Alpine Linux is ~5 MB vs Ubuntu's ~75 MB. Most language runtimes offer Alpine variants: node:20-alpine, python:3.12-alpine, golang:1.22-alpine.


    Layer Optimization


    Combine RUN Commands

    Every RUN creates a layer. Combine related commands:

    RUN apt-get update && apt-get install -y curl && rm -rf /var/lib/apt/lists/*


    Order Layers by Change Frequency

    Put rarely-changing layers first (dependency install) and frequently-changing layers last (source code copy).


    Use .dockerignore

    Exclude node_modules, .git, tests, docs, and anything else not needed at runtime.


    Language-Specific Tips


    Go

    Compile to a static binary and use FROM scratch — zero base image overhead. Final image can be under 10 MB.


    Python

    Use --no-cache-dir with pip. Remove __pycache__ directories. Consider using distroless images.


    Node.js

    Use npm ci --omit=dev for production. Prune devDependencies in the final stage.


    Scan Your Images


    Use docker scout or trivy to find vulnerabilities. Smaller images have fewer packages and fewer vulnerabilities.


    On TinyPod, optimized images deploy faster and use less of your server's disk space — it's worth the few minutes of Dockerfile tuning.