Cheat SheetsDockerFundamentals

Fundamentals — Cheat Sheet

Docker · 3 topics. Download the PDF or the Instagram carousel and share it.

Cheat Sheet · AiCanCode.org
Fundamentals
Docker3 topicsQuick revision reference
1

What is Docker & Why Containers?

Docker packages an application and all its dependencies into a lightweight, portable container that runs identically on any machine — solving the classic "works on my machine" problem.

  • Containers share the host OS kernel; VMs have their own full OS.
  • An image is a read-only blueprint; a container is a running instance.
  • Docker layers are cached — put infrequently-changing instructions first.
  • Registries (Docker Hub, ECR) store and distribute images.
  • Docker uses Linux namespaces, cgroups, and Union FS under the hood.
Container vs VM architecture
┌──────────────────────────────────────────┐

│              YOUR MACHINE                │

│                                          │

│  ┌──────────┐   ┌──────────┐            │

│  │ Container│   │ Container│            │

│  │  App A   │   │  App B   │            │

│  │ + libs   │   │ + libs   │            │

│  â””────┬─────┘   â””────┬─────┘            │

│       â””──────┬────────┘                 │

│         Docker Engine                   │

│         (shared OS kernel)              │

│              │                          │

│        Host OS Kernel                   │

â””──────────────────────────────────────────┘



vs VM:

┌──────────────────────────────────────────┐

│  VM 1: full Linux OS (2 GB)             │

│  VM 2: full Linux OS (2 GB)             │

│         Hypervisor (VMware/VirtualBox)   │

│              Host OS                    │

â””──────────────────────────────────────────┘
2

Docker Images & Layers

Docker images are built from stacked read-only layers stored in a Union File System. Understanding layers is the key to writing efficient Dockerfiles and keeping image sizes small.

  • Each Dockerfile instruction creates an immutable, cached layer.
  • Layers are shared across images via content-addressed SHA256 hashes.
  • Cache invalidation: once a layer changes, all subsequent layers rebuild.
  • Put stable instructions (base image, dependencies) before volatile ones (source code).
  • Combine RUN commands and clean up in the same layer to avoid bloat.
  • Alpine-based images are 10-20x smaller than Debian/Ubuntu-based ones.
Docker layer stack — node app example
Layer 5 (COPY . .)              ← writable, specific to your app

Layer 4 (RUN npm ci)            ← node_modules, cached until package.json changes

Layer 3 (COPY package*.json ./) ← package files

Layer 2 (WORKDIR /app)          ← just sets a directory pointer

Layer 1 (FROM node:20-alpine)   ← ~120 MB base: Linux Alpine + Node runtime

         ────────────────────

         All layers = final image



# Inspect layers with:

docker history my-app:latest



IMAGE          CREATED       SIZE    COMMENT

7f2a1b3c9d4e   2 min ago    1.2MB   COPY . .

<missing>      2 min ago    45.1MB  RUN npm ci

<missing>      2 min ago    1.5KB   COPY package*.json ./

<missing>      2 min ago    0B      WORKDIR /app

<missing>      3 days ago   121MB   node:20-alpine
3

Writing Production-Grade Dockerfiles

Production Dockerfiles use multi-stage builds, non-root users, .dockerignore, explicit version pinning, and health checks to produce small, secure, reproducible images.

  • Multi-stage builds separate build environment from runtime — dramatically smaller images.
  • .dockerignore prevents leaking node_modules, .git, and .env files into the build context.
  • Never run containers as root in production — always add a non-root user.
  • Pin exact base image versions (node:20.15.1-alpine3.20) for reproducibility.
  • HEALTHCHECK lets Docker and orchestrators know if the container is actually healthy.
  • Never bake secrets (API keys, passwords) into Docker images — use env vars or secrets managers.
Dockerfile — multi-stage Node.js build
# ──── Stage 1: build ────────────────────────────────

FROM node:20-alpine AS builder

WORKDIR /app

COPY package*.json ./

RUN npm ci                        # includes devDependencies

COPY . .

RUN npm run build                 # compile TypeScript, bundle, etc.



# ──── Stage 2: production runtime ────────────────────

FROM node:20-alpine AS runtime    # fresh image — no build tools

WORKDIR /app



# Only copy what the app needs to run

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

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

COPY package.json .



# Security: run as non-root

RUN addgroup -S appgroup && adduser -S appuser -G appgroup

USER appuser



EXPOSE 3000

HEALTHCHECK --interval=30s --timeout=5s --retries=3 \

  CMD wget -qO- http://localhost:3000/health || exit 1



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



# Result:

# Without multi-stage: ~700 MB (includes TypeScript compiler, source maps, devDeps)

# With multi-stage:    ~180 MB (only runtime + dist output)
Learn this free with Aria, your AI tutor → AiCanCode.org/learn/docker