TUTORIAL

Docker Fundamentals: Containers, Images, and Compose

A hands-on introduction to Docker — from understanding containers vs VMs to building production-ready images and multi-service stacks.


Table of Contents

Docker Fundamentals: Containers, Images, and Compose

Docker revolutionized how we build, ship, and run software. By packaging applications into portable containers, Docker eliminates the "works on my machine" problem and makes deployments reproducible and consistent.

Containers vs Virtual Machines

A container shares the host OS kernel, making it far lighter than a VM:

Container Virtual Machine
Startup Milliseconds Minutes
Size MBs GBs
Isolation Process-level Hardware-level
Overhead Minimal Significant

Core Concepts

1. **Image** — a read-only blueprint (like a class in OOP) 2. **Container** — a running instance of an image (like an object) 3. **Dockerfile** — instructions to build an image 4. **Registry** — storage for images (e.g., Docker Hub) 5. **Compose** — tool for defining multi-container apps

Your First Dockerfile

Dockerfile
# Use an official Node.js 20 slim image
FROM node:20-alpine

# Set working directory
WORKDIR /app

# Copy dependency files first (layer caching optimization)
COPY package*.json ./
RUN npm ci --only=production

# Copy application source
COPY . .

# Expose the port
EXPOSE 3000

# Run as non-root user for security
USER node

CMD ["node", "server.js"]
Copy `package.json` before your source code. Docker caches each layer — if your source changes but dependencies don't, the expensive `npm install` layer won't re-run.

Building and Running

Bash
# Build the image
docker build -t myapp:1.0 .

# Run a container
docker run -d \
  --name myapp \
  -p 3000:3000 \
  -e NODE_ENV=production \
  myapp:1.0

# View logs
docker logs -f myapp

# Execute a command inside
docker exec -it myapp sh

Docker Compose

Compose lets you define multi-service applications in a single YAML file:

YAML
version: '3.9'

services:
  app:
    build: .
    ports:
      - "3000:3000"
    environment:
      DATABASE_URL: postgresql://user:pass@db:5432/mydb
    depends_on:
      db:
        condition: service_healthy

  db:
    image: postgres:15-alpine
    environment:
      POSTGRES_PASSWORD: pass
      POSTGRES_USER: user
      POSTGRES_DB: mydb
    volumes:
      - postgres_data:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U user"]
      interval: 10s
      retries: 5

volumes:
  postgres_data:
Bash
# Start all services
docker compose up -d

# View all containers
docker compose ps

# Tear everything down
docker compose down -v

Multi-Stage Builds

Drastically reduce image size by separating build and runtime stages:

Dockerfile
# Stage 1: Build
FROM node:20-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build

# Stage 2: Production (no dev dependencies, no build tools)
FROM node:20-alpine AS production
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY --from=builder /app/dist ./dist
USER node
EXPOSE 3000
CMD ["node", "dist/index.js"]

The final image only contains what's needed to run — not the entire build toolchain.

Key Commands Reference

Bash
docker ps -a                    # list all containers
docker images                   # list images
docker rm $(docker ps -aq)      # remove all stopped containers
docker rmi $(docker images -q)  # remove all images
docker volume prune             # remove unused volumes
docker system prune -af         # nuclear cleanup
`docker system prune -af` removes **all** unused images, containers, networks, and build cache. Don't run this on production hosts.

Docker is an essential tool in modern development. Master these fundamentals and you have a solid foundation for Kubernetes, CI/CD pipelines, and cloud deployments.


Was this article helpful?

w

webencher Editorial

Software engineers and technical writers with 10+ years of combined experience in algorithms, systems design, and web development. Every article is reviewed for accuracy, depth, and practical applicability.

More by this author →