DevOps

Docker Fundamentals

Learn Docker basics: images, containers, Dockerfile creation, networking, volumes, and essential commands for containerization.

By TechCoder TeamLast updated: 2026-06-02
In a Nutshell

Learn Docker basics: images, containers, Dockerfile creation, networking, volumes, and essential commands for containerization. This hands-on tutorial focuses on practical implementation of docker fundamentals concepts.

Docker Fundamentals

Docker revolutionized application deployment by packaging code with its dependencies into portable containers.

What is Docker?

Docker is a platform for developing, shipping, and running applications in containers—lightweight, portable, and self-sufficient environments.

Traditional VMs:              Docker Containers:
┌─────────────┐              ┌─────────────┐
│   App A     │              │   App A     │
│   Bins/Libs │              │   Bins/Libs │
│   Guest OS  │              ├─────────────┤
├─────────────┤              │   App B     │
│   App B     │              │   Bins/Libs │
│   Bins/Libs │              ├─────────────┤
│   Guest OS  │              │   App C     │
├─────────────┤              │   Bins/Libs │
│   Hypervisor│              ├─────────────┤
├─────────────┤              │ Docker      │
│   Host OS   │              │ Engine      │
├─────────────┤              ├─────────────┤
│   Hardware  │              │   Host OS   │
└─────────────┘              ├─────────────┤
                             │   Hardware  │
                             └─────────────┘

Docker Architecture

┌───────────────────────────────────────────────────────────────┐
│                     Docker Architecture                        │
├───────────────────────────────────────────────────────────────┤
│                                                                │
│   Docker Client ──API──> Docker Daemon (Host)                │
│       (CLI)                  ┌─────────────────────┐          │
│       (REST)                 │  Image Management   │          │
│                              │  Container Runtime  │          │
│                              │  Networks/Volumes   │          │
│                              └──────────┬──────────┘          │
│                                         │                     │
│                              ┌──────────┴──────────┐          │
│                              │   Containerd        │          │
│                              │   (Container        │          │
│                              │    Runtime)         │          │
│                              └──────────┬──────────┘          │
│                              ┌──────────┴──────────┐          │
│                              │   runc              │          │
│                              │   (Low-level)       │          │
│                              └─────────────────────┘          │
│                                                                │
└───────────────────────────────────────────────────────────────┘

Core Concepts

Images

Read-only templates used to create containers.

# List images
docker images

# Pull image from registry
docker pull nginx:latest
docker pull ubuntu:22.04

# Build image from Dockerfile
docker build -t myapp:1.0 .

# Tag image
docker tag myapp:1.0 registry.example.com/myapp:1.0

# Remove image
docker rmi nginx:latest
docker image prune  # Remove dangling images

Containers

Runnable instances of images.

# Run container
docker run nginx

# Run interactively
docker run -it ubuntu:22.04 /bin/bash

# Run in background (detached)
docker run -d -p 80:80 --name web nginx

# List containers
docker ps          # Running
docker ps -a       # All

# Start/Stop/Restart
docker start web
docker stop web
docker restart web

# Remove container
docker rm web
docker rm -f web   # Force remove running

# Execute command in running container
docker exec -it web /bin/bash
docker exec web nginx -t  # Test config

# View logs
docker logs web
docker logs -f web   # Follow

Dockerfile

A script containing instructions to build a Docker image.

Basic Structure

# Base image
FROM node:18-alpine

# Set working directory
WORKDIR /app

# Copy package files
COPY package*.json ./

# Install dependencies
RUN npm ci --only=production

# Copy application code
COPY . .

# Create non-root user
RUN addgroup -g 1001 -S nodejs
RUN adduser -S nextjs -u 1001

# Change ownership
RUN chown -R nextjs:nodejs /app
USER nextjs

# Expose port
EXPOSE 3000

# Health check
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
  CMD curl -f http://localhost:3000/api/health || exit 1

# Start command
CMD ["npm", "start"]

Dockerfile Instructions

InstructionPurposeExample
FROMBase imageFROM ubuntu:22.04
WORKDIRSet working directoryWORKDIR /app
COPYCopy files from hostCOPY . /app
ADDCopy + extract/URL supportADD https://... /tmp/
RUNExecute commandRUN apt-get update
CMDDefault commandCMD ["node", "app.js"]
ENTRYPOINTFixed commandENTRYPOINT ["java", "-jar"]
ENVSet environment variableENV NODE_ENV=production
ARGBuild-time variableARG VERSION=1.0
EXPOSEDocument portEXPOSE 8080
VOLUMECreate mount pointVOLUME /data
USERSet userUSER 1000
LABELAdd metadataLABEL version="1.0"

Multi-stage Builds

# Build stage
FROM node:18-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build

# Production stage
FROM node:18-alpine AS production
WORKDIR /app
ENV NODE_ENV=production

# Copy only necessary files from builder
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/node_modules ./node_modules
COPY --from=builder /app/package.json ./

USER node
EXPOSE 3000
CMD ["node", "dist/main.js"]

Essential Commands

Container Management

# Lifecycle
docker create nginx          # Create but don't start
docker start container_id    # Start created/stopped
docker stop container_id     # Stop gracefully
docker kill container_id     # Stop forcefully
docker restart container_id  # Restart
docker pause container_id    # Pause processes
docker unpause container_id  # Resume
docker rm container_id       # Remove

# Information
docker ps                    # List running
docker ps -a                 # List all
docker ps -q                 # List IDs only
docker ps --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}"

docker inspect container_id  # Detailed info (JSON)
docker stats                 # Resource usage
docker top container_id      # Running processes

docker logs container_id     # View logs
docker logs -f container_id  # Follow logs
docker logs --tail 100 container_id  # Last 100 lines

Image Management

# Build
docker build -t myapp:1.0 .
docker build -f Dockerfile.prod -t myapp:prod .
docker build --no-cache -t myapp:1.0 .
docker build --target production -t myapp:prod .

# Registry operations
docker login registry.example.com
docker push registry.example.com/myapp:1.0
docker pull nginx:latest

# Information
docker images
docker history myapp:1.0
docker inspect myapp:1.0

# Cleanup
docker rmi image_id
docker image prune           # Remove dangling
docker image prune -a        # Remove all unused
docker system prune          # Remove unused data

Networking

Network Types

TypeDescriptionUse Case
bridgeDefault private networkContainer communication
hostUse host's networkPerformance, no isolation
noneNo networkIsolated containers
overlayMulti-host networkDocker Swarm
macvlanAssign MAC addressLegacy apps

Network Commands

# List networks
docker network ls

# Create network
docker network create my-network

# Run with network
docker run -d --network my-network --name web nginx
docker run -d --network my-network --name db postgres

# Container DNS
docker exec web ping db  # Works within same network

# Inspect network
docker network inspect my-network

# Connect/disconnect
docker network connect my-network container2
docker network disconnect my-network container2

# Remove
docker network rm my-network

Port Mapping

# Map host port to container port
docker run -p 8080:80 nginx           # Host:Container
docker run -p 127.0.0.1:8080:80 nginx # Bind to specific IP
docker run -p 8080:80/udp nginx       # UDP port
docker run -P nginx                   # Publish all EXPOSED ports

Storage

Volume Types

# Named volumes (managed by Docker)
docker volume create my-data
docker run -v my-data:/data nginx

# Bind mounts (host directory)
docker run -v /host/path:/container/path nginx
docker run -v $(pwd):/app nginx

# tmpfs mounts (in memory)
docker run --tmpfs /cache:rw,noexec,nosuid,size=100m nginx

Volume Commands

# Create
docker volume create my-volume

# List
docker volume ls

# Inspect
docker volume inspect my-volume

# Remove
docker volume rm my-volume
docker volume prune  # Remove unused

# Backup
docker run --rm -v my-volume:/data -v $(pwd):/backup alpine \
  tar czf /backup/backup.tar.gz -C /data .

# Restore
docker run --rm -v my-volume:/data -v $(pwd):/backup alpine \
  tar xzf /backup/backup.tar.gz -C /data

Docker Compose

Basic docker-compose.yml

version: '3.8'

services:
  web:
    build: ./web
    ports:
      - "80:80"
    volumes:
      - ./web:/usr/share/nginx/html:ro
    depends_on:
      - api
    networks:
      - frontend
      - backend
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 10s
    restart: unless-stopped

  api:
    build:
      context: ./api
      dockerfile: Dockerfile
      target: production
    environment:
      - NODE_ENV=production
      - DB_HOST=db
      - DB_PORT=5432
    env_file:
      - .env.api
    ports:
      - "3000:3000"
    depends_on:
      db:
        condition: service_healthy
    networks:
      - backend
    deploy:
      replicas: 2
      resources:
        limits:
          cpus: '0.5'
          memory: 512M
        reservations:
          cpus: '0.25'
          memory: 256M
    restart: unless-stopped

  db:
    image: postgres:15-alpine
    environment:
      POSTGRES_DB: myapp
      POSTGRES_USER: appuser
      POSTGRES_PASSWORD_FILE: /run/secrets/db_password
    volumes:
      - db-data:/var/lib/postgresql/data
      - ./init.sql:/docker-entrypoint-initdb.d/init.sql
    secrets:
      - db_password
    networks:
      - backend
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U appuser -d myapp"]
      interval: 10s
      timeout: 5s
      retries: 5

  redis:
    image: redis:7-alpine
    volumes:
      - redis-data:/data
    networks:
      - backend
    command: redis-server --appendonly yes --maxmemory 256mb --maxmemory-policy allkeys-lru

networks:
  frontend:
    driver: bridge
  backend:
    driver: bridge
    internal: true  # No external access

volumes:
  db-data:
    driver: local
  redis-data:
    driver: local

secrets:
  db_password:
    file: ./secrets/db_password.txt

Compose Commands

# Start services
docker-compose up
docker-compose up -d              # Detached
docker-compose up --build         # Rebuild images
docker-compose up --force-recreate # Recreate containers

# Stop services
docker-compose down
docker-compose down -v            # Remove volumes too
docker-compose down --rmi all     # Remove images too

# View status
docker-compose ps
docker-compose logs
docker-compose logs -f web      # Follow web service

# Execute commands
docker-compose exec web /bin/bash
docker-compose run --rm api npm test

# Scale services
docker-compose up -d --scale web=3

# Validate config
docker-compose config

Best Practices

Image Optimization

# Use specific base image tags
FROM node:18.17.0-alpine3.18

# Multi-stage builds for smaller images
# .dockerignore to exclude files
# Minimize layers (combine RUN commands)
# Use --no-cache for reproducible builds
# Scan images for vulnerabilities

Security

# Run as non-root
RUN adduser -D appuser
USER appuser

# Use read-only root filesystem
docker run --read-only nginx

# Drop capabilities
docker run --cap-drop=ALL --cap-add=NET_BIND_SERVICE nginx

# Use secrets for sensitive data
# Don't embed secrets in images
# Scan images: docker scan or trivy

.dockerignore

# Git
.git
.gitignore

# Dependencies
node_modules
vendor

# Build outputs
*.log
*.tmp
dist
build

# IDE
.idea
.vscode

# OS
.DS_Store
Thumbs.db

# Tests
__tests__
*.test.js
coverage

# Documentation
*.md
docs

Quiz

Quiz

Question 1 of 5

What is the difference between a Docker image and a container?

They are the same thing
An image is a template; a container is a running instance of an image
Images are for production; containers are for development
Containers are larger than images

Next Steps

Now let's explore advanced Docker concepts and then dive into Kubernetes for container orchestration.