Docker// Complete Guide

Everything you need to containerize, ship, and run applications anywhere

v27.x Containers DevOps Cloud Native Open Source
🐳 What is Docker?
An open platform for developing, shipping, and running applications in isolated environments called containers.
13M+
Docker Hub Images
11M+
Active Developers
1B+
Monthly Image Pulls
2013
Year Founded
📦

Containers

Lightweight, portable units that package code and all its dependencies so the application runs quickly and reliably across different computing environments.

🏃

Runs Anywhere

"Build once, run anywhere" — containers work identically on developer laptops, staging servers, and production clouds.

Lightweight

Containers share the host OS kernel, making them far more efficient than traditional VMs. Start in seconds, not minutes.

🔒

Isolated

Each container runs in its own isolated environment with its own filesystem, network, and process space — no conflicts.

🔄

Version Control

Docker images are versioned and immutable. Roll back to any previous version instantly. Reproducible builds every time.

🌊

Microservices

Perfect for microservices architecture — each service in its own container, independently deployable and scalable.

🔄 Container Lifecycle
📝

Dockerfile

Define image
🔨

Build

Create image
🚀

Push

Ship to registry
▶️

Run

Start container
🗑️

Remove

Clean up
⚖️ Containers vs Virtual Machines
Feature 🐳 Docker Containers 🖥️ Virtual Machines
Startup TimeSecondsMinutes
SizeMBsGBs
PerformanceNear-nativeOverhead from hypervisor
OS IncludedNo (shared kernel)Full OS per VM
IsolationProcess-levelFull hardware-level
PortabilityExcellentLimited
Resource UsageVery lowHigh
🏗️ Docker Architecture
Docker uses a client-server architecture with three main components working together.
Your Applications
App A
App B
App C
App D
Containers (Isolated Processes)
Container 1
Container 2
Container 3
Docker Engine (Daemon)
🐳 Docker Engine (dockerd)
Host OS Kernel
Linux Kernel (namespaces + cgroups)
Hardware
CPU / RAM / Storage / Network
🖥️

Docker Client (CLI)

The primary way users interact with Docker. Commands like docker run, docker build, and docker pull send instructions to the Docker daemon via REST API.

⚙️

Docker Daemon (dockerd)

Listens for Docker API requests and manages Docker objects — images, containers, networks, and volumes. The daemon is the heart of Docker.

🗄️

Docker Registry

Stores Docker images. Docker Hub is the default public registry. You can also run private registries (AWS ECR, GCR, self-hosted).

🔧

containerd

An industry-standard container runtime that manages the complete container lifecycle — from image transfer to execution and storage.

📦

runc

The low-level OCI-compliant container runtime that actually creates and runs containers using Linux namespaces and cgroups.

🔌

REST API

An API interface that programs can use to talk to the daemon and instruct it. Both the CLI and Docker Compose communicate via this API.

🔑 Linux Kernel Features
🏠

Namespaces

Provide isolation for PID (processes), NET (networking), IPC (inter-process communication), MNT (filesystem mounts), and UTS (hostname).

📊

Control Groups (cgroups)

Limit and account for resource usage (CPU, memory, disk I/O, network) for each container, preventing resource starvation.

📚

Union File Systems

Overlay filesystems (OverlayFS) create efficient copy-on-write layered images, allowing containers to share base image layers.

💡 Core Concepts
Master the fundamental building blocks of Docker.
📦 Images — The Blueprint +

A Docker image is a read-only template used to create containers. It contains everything needed to run an application — the code, runtime, libraries, environment variables, and config files.


Images are built in layers. Each instruction in a Dockerfile creates a new layer. Layers are cached and shared across images, making builds fast and storage efficient.


Key facts:

  • Images are immutable — they never change once built
  • Identified by name + tag (e.g., nginx:1.25)
  • Stored in registries (Docker Hub, ECR, GCR)
  • Based on other images (parent/base images)
🏃 Containers — The Running Instance +

A container is a runnable instance of an image. You can create, start, stop, move, or delete a container. Multiple containers can run from the same image simultaneously.


Containers are ephemeral by default — any data written inside is lost when the container is removed (unless using volumes). Container state: created → running → paused → stopped → removed.

📋 Dockerfile — The Recipe +

A Dockerfile is a text document with instructions to build a Docker image. Docker reads it top-to-bottom and each instruction creates a new layer.


Common instructions: FROM, RUN, COPY, ADD, ENV, EXPOSE, CMD, ENTRYPOINT, WORKDIR, VOLUME, ARG, LABEL, USER.

🗄️ Registry — The Image Store +

A registry is a stateless, server-side application that stores and distributes Docker images. Docker Hub is the default public registry.


Popular registries: Docker Hub, Amazon ECR, Google Container Registry (GCR), GitHub Container Registry (GHCR), Azure Container Registry (ACR), self-hosted with Harbor or Nexus.

🌐 Networks — Container Communication +

Docker networks allow containers to communicate with each other and the outside world. Docker creates default networks automatically and you can create custom ones.


Containers on the same network can reach each other by container name (DNS resolution). Port mapping (-p host:container) exposes container ports to the host.

💾 Volumes — Persistent Data +

Volumes are the preferred mechanism for persisting data generated by and used by Docker containers. They live outside the container's writable layer.


Volumes are managed by Docker and stored in /var/lib/docker/volumes/. They survive container restarts and removal, and can be shared among multiple containers.

⌨️ Essential Commands
The complete Docker CLI reference for daily use.
🔍
CommandDescription
docker run [OPTIONS] IMAGECreate and start a container from an image
docker run -d nginxRun container in detached (background) mode
docker run -p 8080:80 nginxMap host port 8080 to container port 80
docker run --name myapp -v data:/app nginxRun with a name and volume mounted
docker run -it ubuntu bashRun interactively with terminal (TTY)
docker run -e NODE_ENV=prod appSet environment variable in container
docker run --rm alpine echo "hi"Remove container automatically after it stops
docker psList running containers
docker ps -aList all containers (including stopped)
docker imagesList all local images
docker pull nginx:latestPull an image from a registry
docker push myuser/myimage:tagPush an image to a registry
docker build -t myapp:1.0 .Build an image from Dockerfile in current dir
docker build --no-cache -t myapp .Build without using layer cache
docker stop CONTAINERGracefully stop a running container (SIGTERM)
docker kill CONTAINERForcefully stop a container (SIGKILL)
docker start CONTAINERStart a stopped container
docker restart CONTAINERStop and then start a container
docker rm CONTAINERRemove a stopped container
docker rmi IMAGERemove an image
docker exec -it CONTAINER bashExecute command inside running container
docker logs -f CONTAINERFollow/stream container output logs
docker inspect CONTAINERDisplay detailed info about container/image
docker statsLive stream of container resource usage
docker top CONTAINERDisplay running processes inside container
docker cp file.txt CONTAINER:/path/Copy files between host and container
docker commit CONTAINER myimage:v1Create image from container's current state
docker tag SOURCE_IMAGE TARGET_IMAGECreate a new tag pointing to an image
docker login registry.example.comLog in to a Docker registry
docker volume create mydataCreate a named volume
docker volume lsList all volumes
docker volume rm mydataRemove a volume
docker network create mynetCreate a custom network
docker network lsList all networks
docker network connect mynet CONTAINERConnect container to a network
docker system prune -afRemove all unused containers, images, networks
docker infoDisplay system-wide Docker information
docker versionShow Docker client and server version info
docker search nginxSearch Docker Hub for images
docker history IMAGEShow the build history/layers of an image
docker save -o image.tar myimageSave image to a tar archive
docker load -i image.tarLoad image from a tar archive
docker pause / unpause CONTAINERPause or unpause processes in a container
docker port CONTAINERList port mappings for a container
docker diff CONTAINERShow filesystem changes in a container
docker eventsStream real-time events from Docker daemon
📄 Dockerfile Reference
Every instruction you need to build efficient, production-grade images.
Dockerfile — Full Example (Node.js App)
# ── Stage 1: Builder ─────────────────────────────────────
FROM node:20-alpine AS builder

# Set working directory
WORKDIR /app

# Copy dependency files first (better layer caching)
COPY package*.json ./

# Install dependencies
RUN npm ci --only=production

# Copy source code
COPY . .

# Build the application
RUN npm run build

# ── Stage 2: Production ──────────────────────────────────
FROM node:20-alpine

# Add metadata labels
LABEL maintainer="dev@example.com" version="1.0"

# Create non-root user for security
RUN addgroup -S appgroup && adduser -S appuser -G appgroup

WORKDIR /app

# Copy only production build from builder stage
COPY --from=builder --chown=appuser:appgroup /app/dist ./dist
COPY --from=builder --chown=appuser:appgroup /app/node_modules ./node_modules

# Set environment variables
ENV NODE_ENV=production PORT=3000

# Build-time argument
ARG BUILD_VERSION
ENV BUILD_VERSION=$BUILD_VERSION

# Declare volume for logs
VOLUME ["/app/logs"]

# Document the port
EXPOSE 3000

# Switch to non-root user
USER appuser

# Health check
HEALTHCHECK --interval=30s --timeout=10s --retries=3 \
  CMD wget -qO- http://localhost:3000/health || exit 1

# Default entrypoint
ENTRYPOINT ["node"]

# Default command (can be overridden)
CMD ["dist/server.js"]
🏁

FROM

Sets the base image. Every Dockerfile starts with FROM. Use specific tags (not latest) for reproducibility. Alpine variants are smallest.

📁

WORKDIR

Sets the working directory for subsequent RUN, CMD, ENTRYPOINT, COPY, ADD instructions. Creates the directory if it doesn't exist.

⚙️

RUN

Executes commands in a new layer. Chain commands with && to minimize layers. Always clean up in the same RUN command.

📋

COPY vs ADD

Prefer COPY for simple file copying. ADD has extra features (URL download, tar extraction) but COPY is more transparent and predictable.

🌍

ENV vs ARG

ENV sets runtime environment variables. ARG sets build-time variables only. Use ARG for build secrets, ENV for app configuration.

🎯

CMD vs ENTRYPOINT

ENTRYPOINT defines the executable. CMD provides default arguments. Together: ENTRYPOINT ["node"] + CMD ["app.js"] = node app.js.

.dockerignore — Exclude files from build context
# Dependencies
node_modules/
# VCS
.git/
.gitignore
# Build artifacts
dist/
build/
*.log
# Secrets
.env
.env.*
*.pem
# Docker files themselves
Dockerfile*
docker-compose*
🔗 Docker Compose
Define and run multi-container applications with a single YAML file.
docker-compose.yml — Full Stack App (React + Node + Postgres + Redis)
name: myapp

services:

  frontend:
    build:
      context: ./frontend
      target: production
    ports:
      - "3000:3000"
    environment:
      - REACT_APP_API_URL=http://localhost:8080
    depends_on:
      - api
    networks:
      - frontend-net

  api:
    build: ./backend
    ports:
      - "8080:8080"
    environment:
      - DATABASE_URL=postgres://user:pass@db:5432/mydb
      - REDIS_URL=redis://cache:6379
    depends_on:
      db:
        condition: service_healthy
      cache:
        condition: service_started
    networks:
      - frontend-net
      - backend-net
    restart: unless-stopped

  db:
    image: postgres:16-alpine
    volumes:
      - postgres_data:/var/lib/postgresql/data
      - ./init.sql:/docker-entrypoint-initdb.d/init.sql
    environment:
      POSTGRES_DB: mydb
      POSTGRES_USER: user
      POSTGRES_PASSWORD: pass
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U user"]
      interval: 10s
      timeout: 5s
      retries: 5
    networks:
      - backend-net

  cache:
    image: redis:7-alpine
    command: redis-server --appendonly yes
    volumes:
      - redis_data:/data
    networks:
      - backend-net

volumes:
  postgres_data:
  redis_data:

networks:
  frontend-net:
    driver: bridge
  backend-net:
    driver: bridge
    internal: true  # no external access
🚀 Compose Services Overview
⚛️
frontend
React app served on port 3000, depends on API service
:3000
🟢
api
Node.js REST API, waits for healthy DB before starting
:8080
🐘
db (PostgreSQL)
Persistent database with health checks and init scripts
:5432
🔴
cache (Redis)
In-memory cache with append-only file persistence
:6379

Docker Compose CLI Commands
docker compose up          # Start all services
docker compose up -d       # Start in detached mode
docker compose down        # Stop and remove containers
docker compose down -v    # Also remove volumes
docker compose ps          # List service containers
docker compose logs -f    # Follow all logs
docker compose build       # Build all service images
docker compose pull        # Pull latest images
docker compose restart api # Restart specific service
docker compose exec db psql # Exec into service
docker compose scale api=3 # Scale a service to 3 replicas
docker compose config      # Validate and print config
🌐 Docker Networking
How containers communicate with each other and the outside world.
🌉

Bridge

Default network driver. Containers can communicate via IP. Use custom bridges for DNS-based name resolution.

DEFAULT
🖥️

Host

Container shares the host's network stack directly. No port mapping needed. Best performance but no isolation.

LINUX ONLY
🔇

None

Completely disables networking for the container. Useful for batch jobs and offline processing tasks.

ISOLATED
🔗

Overlay

Spans multiple Docker hosts — used with Docker Swarm and Kubernetes for multi-host container communication.

MULTI-HOST
🔌

Macvlan

Assigns a MAC address to containers, making them appear as physical devices on your network.

ADVANCED
🔧

IPvlan

Similar to Macvlan but shares the host MAC address. Supports L2 and L3 modes for different routing needs.

ADVANCED
Networking Commands & Examples
# Create a custom bridge network
docker network create --driver bridge myapp-net

# Run containers on the same network
docker run -d --name db --network myapp-net postgres
docker run -d --name api --network myapp-net myapi

# Containers can now reach each other by name:
# api connects to db using hostname "db"

# Port mapping: HOST_PORT:CONTAINER_PORT
docker run -p 8080:80 nginx        # TCP only
docker run -p 53:53/udp dns-server  # UDP port
docker run -P nginx               # Auto-assign all EXPOSED ports

# Connect existing container to another network
docker network connect mynet mycontainer

# Inspect network details
docker network inspect myapp-net
💾 Volumes & Storage
Persist data beyond container lifecycle and share data between containers.
📦

Named Volumes

Managed by Docker, stored in /var/lib/docker/volumes/. Best for production data persistence. Easy to back up.

RECOMMENDED
📂

Bind Mounts

Maps a host directory directly into the container. Great for development — changes on host reflect instantly in container.

DEV FRIENDLY

tmpfs Mounts

Stored in host memory only, never written to disk. Useful for sensitive data (secrets, tokens) that shouldn't persist.

IN-MEMORY
Volume Usage Examples
# ── Named Volumes ────────────────────────────────────────
docker volume create pgdata
docker run -v pgdata:/var/lib/postgresql/data postgres

# ── Bind Mounts ──────────────────────────────────────────
# Mount current directory into container (dev mode)
docker run -v $(pwd):/app -w /app node npm start

# Read-only bind mount
docker run -v /host/config:/app/config:ro myapp

# ── tmpfs Mounts ─────────────────────────────────────────
docker run --tmpfs /run:rw,noexec,nosuid,size=65536k myapp

# ── Backup a Named Volume ────────────────────────────────
docker run --rm -v pgdata:/data -v $(pwd):/backup alpine \
  tar czf /backup/pgdata-backup.tar.gz /data

# ── Share volume between containers ──────────────────────
docker run -d --name writer -v shared:/data writer-app
docker run -d --name reader --volumes-from writer reader-app

# ── Volume management ────────────────────────────────────
docker volume ls
docker volume inspect pgdata
docker volume prune          # Remove unused volumes
⭐ Best Practices
Production-grade tips for building secure, efficient, and maintainable Docker setups.
1

Use Multi-Stage Builds

Separate build environment from runtime. Compile/install in a builder stage, copy only artifacts to the final slim image. Reduces image size by 60–90%.

2

Pin Specific Image Tags

Never use :latest in production. Pin to specific versions (e.g., node:20.11.1-alpine3.19) for reproducible, predictable builds.

3

Run as Non-Root User

Create and switch to a non-root user in your Dockerfile. Running as root is a security risk — if a container is compromised, the attacker gets root.

4

Optimize Layer Caching

Order Dockerfile instructions from least to most frequently changing. Copy dependency files before source code to maximize cache hits on rebuilds.

5

Use .dockerignore

Exclude node_modules, .git, build artifacts, and secrets from the build context. Speeds up builds and prevents leaking sensitive files.

6

One Process Per Container

Each container should have one responsibility. Avoid running multiple services (nginx + node + postgres) in a single container. Use Compose instead.

7

Add HEALTHCHECK Instructions

Define health checks so orchestrators know when a container is truly ready. Without this, traffic may be sent to containers that are starting up.

8

Never Hardcode Secrets

Don't put passwords, API keys, or tokens in Dockerfiles or images. Use Docker secrets, environment variables at runtime, or a secrets manager (Vault, AWS SSM).

9

Use Alpine/Distroless Base Images

Alpine images are ~5MB vs ~100MB for Debian-based. Smaller images = smaller attack surface, faster pulls, lower storage costs.

10

Scan Images for Vulnerabilities

Integrate docker scout, Snyk, or Trivy into CI/CD pipelines to catch vulnerabilities in base images and dependencies before they reach production.

11

Set Resource Limits

Always set --memory and --cpus limits in production to prevent a single container from starving the host or other containers of resources.

12

Use Named Volumes for Data

Prefer named volumes over bind mounts in production. They're portable, easier to manage with Docker APIs, and work correctly with backups and migrations.


📊 Image Size Optimization
Ubuntu 22.04~77MB
Debian Slim~45MB
Alpine Linux~7MB
Distroless (Google)~2MB
Scratch (empty)~0MB