- Introduction to Docker
- Docker Architecture
- Installation
- Docker Commands Reference
- Dockerfile Basics
- Docker Compose
- Hands-On Tasks
- Best Practices
Docker is an open-source platform that enables developers to automate the deployment of applications inside lightweight, portable containers. Containers package an application with all its dependencies, ensuring it runs consistently across different environments.
- Consistency: "Works on my machine" problem solved
- Isolation: Applications run in isolated environments
- Portability: Run anywhere - development, testing, production
- Efficiency: Lightweight compared to virtual machines
- Scalability: Easy to scale applications horizontally
- Version Control: Track changes to your application environment
| Feature | Docker Containers | Virtual Machines |
|---|---|---|
| Size | Lightweight (MBs) | Heavy (GBs) |
| Startup Time | Seconds | Minutes |
| Performance | Native | Overhead |
| Isolation | Process-level | Complete |
| OS | Shares host kernel | Separate OS |
- Docker Engine: The runtime that builds and runs containers
- Docker Client: CLI tool to interact with Docker daemon
- Docker Daemon: Background service managing containers
- Docker Registry: Storage for Docker images (Docker Hub)
- Docker Images: Read-only templates for containers
- Docker Containers: Running instances of images
┌─────────────────────────────────────────────┐
│ Docker Client (CLI) │
└─────────────────┬───────────────────────────┘
│ (REST API)
┌─────────────────▼───────────────────────────┐
│ Docker Daemon │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │Container │ │Container │ │Container │ │
│ │ 1 │ │ 2 │ │ 3 │ │
│ └──────────┘ └──────────┘ └──────────┘ │
│ ┌──────────────────────────────────────┐ │
│ │ Docker Images │ │
│ └──────────────────────────────────────┘ │
└─────────────────────────────────────────────┘
│
┌─────────────────▼───────────────────────────┐
│ Docker Registry (Hub) │
└─────────────────────────────────────────────┘
- Download Docker Desktop from docker.com
- Run the installer
- Enable WSL 2 (Windows Subsystem for Linux)
- Restart your computer
- Verify installation:
docker --version
docker run hello-world# Update package index
sudo apt-get update
# Install prerequisites
sudo apt-get install ca-certificates curl gnupg lsb-release
# Add Docker's official GPG key
sudo mkdir -p /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
# Set up repository
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
# Install Docker Engine
sudo apt-get update
sudo apt-get install docker-ce docker-ce-cli containerd.io docker-compose-plugin
# Verify installation
sudo docker run hello-world- Download Docker Desktop for Mac
- Install the .dmg file
- Start Docker Desktop
- Verify:
docker --version
# Pull latest version
docker pull <image-name>
# Pull specific version
docker pull <image-name>:<tag>
# Examples
docker pull nginx
docker pull nginx:1.21
docker pull ubuntu:20.04# List all images
docker images
# List with specific format
docker images --format "table {{.Repository}}\t{{.Tag}}\t{{.Size}}"
# List image IDs only
docker images -q# Build from Dockerfile in current directory
docker build -t <image-name>:<tag> .
# Build with specific Dockerfile
docker build -t myapp:1.0 -f Dockerfile.prod .
# Build without cache
docker build --no-cache -t myapp:1.0 .# Remove single image
docker rmi <image-id>
# Remove multiple images
docker rmi <image-id1> <image-id2>
# Remove all unused images
docker image prune
# Remove all images
docker rmi $(docker images -q)
# Force remove
docker rmi -f <image-id># Tag an image
docker tag <source-image>:<tag> <target-image>:<tag>
# Example
docker tag myapp:latest myapp:v1.0
docker tag myapp:latest username/myapp:latest# Login to Docker Hub
docker login
# Push image
docker push <username>/<image-name>:<tag>
# Example
docker push johndoe/myapp:latest# View detailed information
docker inspect <image-name>
# View image history
docker history <image-name># Basic run
docker run <image-name>
# Run with name
docker run --name <container-name> <image-name>
# Run in detached mode (background)
docker run -d <image-name>
# Run with port mapping
docker run -p <host-port>:<container-port> <image-name>
# Run with environment variables
docker run -e ENV_VAR=value <image-name>
# Run with volume mount
docker run -v <host-path>:<container-path> <image-name>
# Run interactively
docker run -it <image-name> /bin/bash
# Complete example
docker run -d --name mynginx -p 8080:80 -v $(pwd)/html:/usr/share/nginx/html nginx# List running containers
docker ps
# List all containers (including stopped)
docker ps -a
# List container IDs only
docker ps -q
# List with specific format
docker ps --format "table {{.ID}}\t{{.Names}}\t{{.Status}}"# Start a stopped container
docker start <container-id/name>
# Stop a running container
docker stop <container-id/name>
# Restart a container
docker restart <container-id/name>
# Pause a container
docker pause <container-id/name>
# Unpause a container
docker unpause <container-id/name>
# Kill a container (force stop)
docker kill <container-id/name># Execute command
docker exec <container-id/name> <command>
# Interactive shell
docker exec -it <container-id/name> /bin/bash
# Execute as specific user
docker exec -u root -it <container-id/name> /bin/bash
# Examples
docker exec mynginx ls /etc/nginx
docker exec -it myapp npm install# View logs
docker logs <container-id/name>
# Follow logs (real-time)
docker logs -f <container-id/name>
# View last N lines
docker logs --tail 100 <container-id/name>
# View logs with timestamps
docker logs -t <container-id/name>
# View logs since specific time
docker logs --since 2023-01-01T00:00:00 <container-id/name># Remove stopped container
docker rm <container-id/name>
# Force remove running container
docker rm -f <container-id/name>
# Remove multiple containers
docker rm <container-id1> <container-id2>
# Remove all stopped containers
docker container prune
# Remove all containers
docker rm -f $(docker ps -aq)# View detailed information
docker inspect <container-id/name>
# View specific field
docker inspect --format='{{.NetworkSettings.IPAddress}}' <container-id/name>
# View container stats
docker stats <container-id/name>
# View all containers stats
docker stats
# View container processes
docker top <container-id/name># Copy from container to host
docker cp <container-id>:<container-path> <host-path>
# Copy from host to container
docker cp <host-path> <container-id>:<container-path>
# Examples
docker cp myapp:/app/logs ./logs
docker cp ./config.json myapp:/app/config.json# List networks
docker network ls
# Create network
docker network create <network-name>
# Create network with specific driver
docker network create --driver bridge my-network
# Inspect network
docker network inspect <network-name>
# Connect container to network
docker network connect <network-name> <container-name>
# Disconnect container from network
docker network disconnect <network-name> <container-name>
# Remove network
docker network rm <network-name>
# Remove all unused networks
docker network prune# List volumes
docker volume ls
# Create volume
docker volume create <volume-name>
# Inspect volume
docker volume inspect <volume-name>
# Remove volume
docker volume rm <volume-name>
# Remove all unused volumes
docker volume prune
# Remove all volumes
docker volume rm $(docker volume ls -q)# View Docker disk usage
docker system df
# Remove all unused data
docker system prune
# Remove all unused data including volumes
docker system prune -a --volumes
# View Docker info
docker info
# View Docker version
docker version
# View events
docker events
# View events with filter
docker events --filter 'type=container'A Dockerfile is a text file containing instructions to build a Docker image. Each instruction creates a layer in the image.
Specifies the base image
FROM ubuntu:20.04
FROM node:16-alpine
FROM python:3.9-slimSets the working directory
WORKDIR /appCopy files from host to container
# COPY is preferred
COPY package.json .
COPY . /app
# ADD can extract archives and download from URLs
ADD archive.tar.gz /appExecute commands during build
RUN apt-get update && apt-get install -y curl
RUN npm install
RUN pip install -r requirements.txtSet environment variables
ENV NODE_ENV=production
ENV PORT=3000
ENV DATABASE_URL=postgresql://localhost/mydbDocument which ports the container listens on
EXPOSE 80
EXPOSE 3000
EXPOSE 8080Default command to run when container starts
CMD ["npm", "start"]
CMD ["python", "app.py"]
CMD ["nginx", "-g", "daemon off;"]Configure container as executable
ENTRYPOINT ["python"]
CMD ["app.py"]Build-time variables
ARG VERSION=latest
ARG BUILD_DATE
RUN echo "Building version ${VERSION}"Add metadata to image
LABEL maintainer="your-email@example.com"
LABEL version="1.0"
LABEL description="My application"Set user for subsequent instructions
USER node
USER www-dataCreate mount point
VOLUME /data
VOLUME ["/var/log", "/var/db"]# Use official Node.js image
FROM node:16-alpine
# Set working directory
WORKDIR /app
# Copy package files
COPY package*.json ./
# Install dependencies
RUN npm ci --only=production
# Copy application code
COPY . .
# Expose port
EXPOSE 3000
# Set environment
ENV NODE_ENV=production
# Start application
CMD ["node", "server.js"]FROM python:3.9-slim
WORKDIR /app
# Install dependencies
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
# Copy application
COPY . .
# Expose port
EXPOSE 5000
# Run application
CMD ["python", "app.py"]# Build stage
FROM node:16 AS builder
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
RUN npm run build
# Production stage
FROM node:16-alpine
WORKDIR /app
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/node_modules ./node_modules
EXPOSE 3000
CMD ["node", "dist/server.js"]Docker Compose is a tool for defining and running multi-container Docker applications using a YAML file.
version: '3.8'
services:
web:
build: .
ports:
- "3000:3000"
environment:
- NODE_ENV=production
depends_on:
- db
volumes:
- ./app:/app
networks:
- mynetwork
db:
image: postgres:13
environment:
- POSTGRES_PASSWORD=secret
- POSTGRES_DB=mydb
volumes:
- db-data:/var/lib/postgresql/data
networks:
- mynetwork
volumes:
db-data:
networks:
mynetwork:
driver: bridge# Start services
docker-compose up
# Start in detached mode
docker-compose up -d
# Build and start
docker-compose up --build
# Stop services
docker-compose down
# Stop and remove volumes
docker-compose down -v
# View logs
docker-compose logs
# Follow logs
docker-compose logs -f
# List containers
docker-compose ps
# Execute command in service
docker-compose exec web bash
# Scale services
docker-compose up -d --scale web=3
# Restart services
docker-compose restart
# Pull images
docker-compose pull
# Build images
docker-compose buildSee TASKS.md for detailed hands-on exercises.
- Use specific image tags, not
latest - Use Alpine-based images when possible
- Minimize layers by combining RUN commands
- Use multi-stage builds
- Remove unnecessary files
- Don't run containers as root
- Scan images for vulnerabilities
- Use official images
- Don't store secrets in images
- Keep images updated
# Good: Combine commands
RUN apt-get update && apt-get install -y \
package1 \
package2 \
&& rm -rf /var/lib/apt/lists/*
# Bad: Multiple layers
RUN apt-get update
RUN apt-get install -y package1
RUN apt-get install -y package2Create a .dockerignore file to exclude files:
node_modules
npm-debug.log
.git
.env
*.md
.DS_Store
- Use health checks
- Set resource limits
- Use proper logging
- Implement graceful shutdown
- Use restart policies
# Development
FROM node:16
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
CMD ["npm", "run", "dev"]
# Production
FROM node:16-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY . .
CMD ["node", "server.js"]Solution: Check logs with docker logs <container-id>
Solution: Use different port or stop conflicting service
Solution: Check file permissions or run with appropriate user
Solution: Ensure Docker service is running
Solution: Clean up with docker system prune -a
- Official Docker Documentation
- Docker Hub
- Docker Compose Documentation
- Dockerfile Best Practices
- Play with Docker
# Images
docker pull <image> # Download image
docker build -t <name> . # Build image
docker images # List images
docker rmi <image> # Remove image
# Containers
docker run <image> # Create and start container
docker ps # List running containers
docker ps -a # List all containers
docker stop <container> # Stop container
docker start <container> # Start container
docker rm <container> # Remove container
docker exec -it <container> bash # Access container shell
# Cleanup
docker system prune # Remove unused data
docker container prune # Remove stopped containers
docker image prune # Remove unused images
docker volume prune # Remove unused volumes
# Compose
docker-compose up # Start services
docker-compose down # Stop services
docker-compose logs # View logs
docker-compose ps # List servicesHappy Dockerizing! 🐳