Back to Blogs
Docker
Docker for Dummies - Part 3

Base Images: The Secret to Smaller Docker Images

January 29, 2024
9 min read
Atharva Unde

Choosing the right base image can reduce your Docker image size from gigabytes to megabytes. Discover Alpine, slim, and distroless options.

The base image you choose for your Docker containers can make a dramatic difference in the final image size. Let's explore the options and learn when to use each one.

Base Image Comparison

Here's a size comparison of popular base images:

Base Image Sizes
# Full Ubuntu-based image
FROM ubuntu:22.04          # ~77MB
FROM node:20               # ~1.1GB

# Alpine-based images
FROM alpine:3.18           # ~7MB
FROM node:20-alpine        # ~180MB

# Slim variants
FROM node:20-slim          # ~250MB

# Distroless
FROM gcr.io/distroless/nodejs20  # ~100MB

Standard Images (Ubuntu, Debian)

Full-featured Linux distributions like Ubuntu and Debian come with:

  • Complete package managers (apt, dpkg)
  • Many pre-installed utilities and tools
  • Full shell environments
  • Large size (hundreds of megabytes to gigabytes)

Best for: Development environments, complex applications requiring many system tools, legacy applications.

Alpine Linux

Alpine is a security-oriented, lightweight Linux distribution perfect for containers:

  • Base image is only ~7MB
  • Uses musl libc instead of glibc
  • Includes apk package manager
  • Security-focused with minimal attack surface

Here's a practical example using Alpine:

Alpine Dockerfile Example
FROM node:20-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY . .
EXPOSE 3000
CMD ["node", "index.js"]

Gotcha!

Some native Node modules may need compilation or may not work with musl libc. You might need to install build dependencies like python3 and make.

Best for: Production containers, microservices, applications without complex dependencies.

Slim Variants

Slim images are a middle ground - they strip out unnecessary packages but keep glibc:

  • Smaller than full images, larger than Alpine
  • Uses glibc (better compatibility)
  • Essential tools included
  • Good balance of size and functionality

Best for: Applications that need glibc compatibility but don't require full system tools.

Distroless Images

Google's distroless images contain only your application and runtime dependencies:

  • No shell, package manager, or unnecessary tools
  • Minimal attack surface
  • Very secure for production
  • Debugging can be challenging

Best for: Security-critical production workloads, serverless functions.

Scratch Image

The scratch image is completely empty - it's literally an empty filesystem:

  • Zero bytes base size
  • Only contains what you add
  • Perfect for static binaries
  • No debugging tools whatsoever

Best for: Compiled languages (Go, Rust), static binaries.

Decision Matrix

Base ImageSizeUse CaseProsCons
Ubuntu/DebianLargeDevelopmentFull toolingHuge size
AlpineVery SmallProductionTiny, secureCompatibility issues
SlimMediumProductionGood balanceStill fairly large
DistrolessSmallProductionVery secureHard to debug

Practical Recommendations

Start with Alpine

For most applications, Alpine is the sweet spot between size and functionality. It works well for Node.js, Python, and many other runtimes.

Use Slim for Compatibility

If you encounter issues with Alpine (native modules, glibc dependencies), switch to slim variants.

Consider Distroless for Production

For production workloads where security is paramount, distroless images offer minimal attack surface.

Pro Tip

Use multi-stage builds to compile on a full image and run on Alpine or distroless. Best of both worlds!

In the next article, we'll explore Dockerfile labels and how they help with organization and automation. Stay tuned!