Getting Started
Installation
# Install Docker Desktop (Windows/Mac)
# Download from https://www.docker.com/products/docker-desktop
# Install Docker Engine (Linux)
curl -fsSL https://get.docker.com -o get-docker.sh
sudo sh get-docker.sh
Basic Commands
# Check Docker version
docker --version
# Check Docker status
docker info
# Login to Docker Hub
docker login
Quick Start
5-Minute Docker Introduction
# 1. Verify Docker is installed
docker --version
# 2. Run your first container
docker run hello-world
# 3. Run an interactive container
docker run -it ubuntu:latest bash
# 4. Create a simple Dockerfile
echo 'FROM alpine:latest
CMD ["echo", "Hello from Docker!"]' > Dockerfile
# 5. Build and run your image
docker build -t hello-app .
docker run hello-app
# 6. Clean up
docker system prune -f
Common First Commands
# List running containers
docker ps
# List all containers (including stopped)
docker ps -a
# List images
docker images
# Stop a running container
docker stop container_name
# Remove a container
docker rm container_name
# Remove an image
docker rmi image_name
Dockerfile Basics
Structure
A Dockerfile is a text file that contains instructions for building a Docker image.
# Use a base image
FROM ubuntu:20.04
# Set working directory
WORKDIR /app
# Copy files from host to container
COPY . /app
# Install dependencies
RUN apt-get update && apt-get install -y \
python3 \
python3-pip \
&& rm -rf /var/lib/apt/lists/*
# Expose ports
EXPOSE 8080
# Define startup command
CMD ["python3", "app.py"]
Common Instructions
| Instruction | Purpose | Example |
|---|---|---|
FROM | Base image | FROM node:18-alpine |
WORKDIR | Set working directory | WORKDIR /usr/src/app |
COPY | Copy files | COPY package.json . |
ADD | Copy + extract tar/URL | ADD app.tar.gz /app |
RUN | Execute commands | RUN npm install |
ENV | Set environment variables | ENV NODE_ENV=production |
EXPOSE | Expose ports | EXPOSE 3000 |
CMD | Default command | CMD ["npm", "start"] |
ENTRYPOINT | Container entrypoint | ENTRYPOINT ["python3"] |
Build an Image
# Build from Dockerfile in current directory
docker build -t my-app .
# Build with specific Dockerfile
docker build -f Dockerfile.prod -t my-app:prod .
# Build with build arguments
docker build --build-arg VERSION=1.0 -t my-app:v1.0 .
Docker Compose (Stack Management)
docker-compose.yml Structure
version: '3.8'
services:
web:
build: .
ports:
- "3000:3000"
volumes:
- .:/app
- /app/node_modules
environment:
- NODE_ENV=development
depends_on:
- db
db:
image: postgres:13
environment:
POSTGRES_DB: mydb
POSTGRES_USER: user
POSTGRES_PASSWORD: password
volumes:
- postgres_data:/var/lib/postgresql/data
volumes:
postgres_data:
Stack Commands
Bring Stack Up
# Start all services
docker-compose up
# Start in background (detached)
docker-compose up -d
# Start specific service
docker-compose up web
# Build and start
docker-compose up --build
Bring Stack Down
# Stop all services
docker-compose down
# Stop and remove volumes
docker-compose down -v
# Stop and remove images
docker-compose down --rmi all
Rebuild Stack
# Rebuild all services
docker-compose build
# Rebuild and restart
docker-compose up --build
# Rebuild specific service
docker-compose build web
# Force rebuild (no cache)
docker-compose build --no-cache
Other Stack Operations
# View running services
docker-compose ps
# View logs
docker-compose logs
# View logs for specific service
docker-compose logs web
# Follow logs
docker-compose logs -f
# Execute command in running container
docker-compose exec web bash
# Scale services
docker-compose up -d --scale web=3
Copying Files In/Out of Containers
Copy FROM Container TO Host
# Copy file from container to host
docker cp container_name:/path/in/container/file.txt /host/path/
# Copy directory from container to host
docker cp container_name:/app/logs /host/logs/
# From running container (using exec)
docker exec container_name cat /app/config.json > config.json
Copy FROM Host TO Container
# Copy file to running container
docker cp /host/file.txt container_name:/container/path/
# Copy directory to running container
docker cp /host/myfolder container_name:/app/
# Copy to named volume
docker cp /host/data.db $(docker volume ls -q | grep myvolume):/data/
Advanced Copy Operations
# Copy from one container to another
docker cp container1:/file.txt container2:/file.txt
# Copy with tar (preserve permissions)
docker exec container_name tar czf - /app/data | tar xzf - -C /host/backup/
# Copy large files (use volume mounts instead)
# In docker-compose.yml:
volumes:
- ./host_data:/container_data
Volumes: Host vs Container Paths
Volume Types
Named Volumes
# Create a named volume
docker volume create mydata
# Use in container
docker run -v mydata:/container/path ubuntu
# Inspect volume
docker volume inspect mydata
# List volumes
docker volume ls
# Remove volume
docker volume rm mydata
Bind Mounts (Host Directories)
# Mount host directory to container
docker run -v /host/path:/container/path ubuntu
# Read-only mount
docker run -v /host/path:/container/path:ro ubuntu
# With docker-compose
volumes:
- ./host/folder:/container/folder
- /host/readonly:/container/readonly:ro
Path Differences: Host vs Container
| Operation | Host Path | Container Path | Notes |
|---|---|---|---|
| Working Directory | C:\Users\john\project | /app | Container paths are Unix-style |
| File Permissions | Windows permissions | Unix permissions | May cause permission issues |
| Path Separators | \ (Windows) | / (Unix) | Always use / in Dockerfiles |
| Case Sensitivity | Case insensitive (Windows) | Case sensitive (Linux) | file.txt ≠ FILE.TXT |
| Absolute Paths | C:\data\file.txt | /data/file.txt | No drive letters in containers |
Common Volume Patterns
Development Setup
# docker-compose.yml
services:
app:
volumes:
- .:/app # Source code
- /app/node_modules # Anonymous volume for deps
- ./logs:/app/logs # Logs to host
Data Persistence
services:
db:
image: postgres
volumes:
- postgres_data:/var/lib/postgresql/data
- ./init.sql:/docker-entrypoint-initdb.d/init.sql
volumes:
postgres_data:
Configuration Management
services:
app:
env_file:
- .env
volumes:
- ./config:/app/config:ro # Read-only config
Troubleshooting Volume Issues
# Check volume contents
docker run --rm -v myvolume:/data alpine ls -la /data
# Fix permission issues (Linux)
sudo chown -R $USER:$USER /host/directory
# Fix permission issues (Windows)
# Use Docker Desktop settings > Resources > File sharing
# Clean up unused volumes
docker volume prune
# Inspect container mounts
docker inspect container_name | grep -A 10 Mounts
Complete Workflow Example
1. Create Dockerfile
FROM node:18-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY . .
EXPOSE 3000
CMD ["npm", "start"]
2. Create docker-compose.yml
version: '3.8'
services:
web:
build: .
ports:
- "3000:3000"
volumes:
- .:/app
- /app/node_modules
environment:
- NODE_ENV=development
db:
image: postgres:13
environment:
POSTGRES_DB: myapp
volumes:
- db_data:/var/lib/postgresql/data
volumes:
db_data:
3. Development Workflow
# Start development environment
docker-compose up -d
# View logs
docker-compose logs -f web
# Run tests
docker-compose exec web npm test
# Access container shell
docker-compose exec web sh
# Stop environment
docker-compose down
4. Production Deployment
# Build for production
docker-compose -f docker-compose.yml -f docker-compose.prod.yml up --build -d
# Backup data
docker exec myapp_db pg_dump -U user myapp > backup.sql
# Restore data
docker exec -i myapp_db psql -U user myapp < backup.sql
Typical Workflow
Daily Development Cycle
Morning: Start Your Environment
# Start all services in background
docker-compose up -d
# Check everything is running
docker-compose ps
# View logs to ensure startup succeeded
docker-compose logs --tail=50
During Development: Make Changes
# Rebuild specific service after code changes
docker-compose up --build web
# Run tests in container
docker-compose exec web npm test
# Access container shell for debugging
docker-compose exec web bash
# View real-time logs
docker-compose logs -f web
End of Day: Clean Up
# Stop all services
docker-compose down
# Remove unused containers and networks
docker system prune -f
# Save space by cleaning dangling images
docker image prune -f
Debugging Workflow
Container Won’t Start
# Check container logs
docker-compose logs service_name
# Run container with bash override to debug
docker-compose run --entrypoint bash service_name
# Inspect container configuration
docker inspect container_name
# Check resource usage
docker stats
Application Errors Inside Container
# Access running container
docker-compose exec service_name bash
# Check environment variables
docker-compose exec service_name env
# View application logs
docker-compose exec service_name tail -f /app/logs/app.log
# Test network connectivity
docker-compose exec service_name ping google.com
Performance Issues
# Monitor resource usage
docker stats
# Check disk usage
docker system df
# Inspect volume usage
docker volume ls
docker volume inspect volume_name
Environment Management
Switching Between Projects
# Stop current project
docker-compose down
# Navigate to new project
cd /path/to/other/project
# Start new environment
docker-compose up -d
# List all running containers across projects
docker ps --format "table {{.Names}}\t{{.Image}}\t{{.Status}}"
Managing Multiple Environments
# Development environment
docker-compose -f docker-compose.yml -f docker-compose.dev.yml up -d
# Production environment
docker-compose -f docker-compose.yml -f docker-compose.prod.yml up -d
# Testing environment
docker-compose -f docker-compose.yml -f docker-compose.test.yml up -d
Deployment Workflow
Local Testing Before Deploy
# Build production images locally
docker-compose build
# Run production-like environment
docker-compose -f docker-compose.yml -f docker-compose.prod.yml up -d
# Run integration tests
docker-compose exec web npm run test:integration
# Clean up test environment
docker-compose down -v
Production Deployment
# Tag and push images (if using registry)
docker tag myapp:latest registry.example.com/myapp:v1.0
docker push registry.example.com/myapp:v1.0
# Deploy with new images
docker-compose pull
docker-compose up -d
# Verify deployment
docker-compose ps
curl http://localhost:3000/health
# Rollback if needed
docker-compose down
docker-compose up -d previous_version
Maintenance Tasks
# Weekly: Clean up unused resources
docker system prune -a --volumes -f
# Monthly: Update base images
docker-compose build --no-cache
docker-compose up -d
# Backup data volumes
docker run --rm -v myapp_data:/data -v $(pwd):/backup alpine tar czf /backup/backup.tar.gz -C /data .
# Restore from backup
docker run --rm -v myapp_data:/data -v $(pwd):/backup alpine tar xzf /backup/backup.tar.gz -C /data
Troubleshooting Common Issues
“Port already in use”
# Find what's using the port
netstat -tulpn | grep :3000 # Linux
# Or on Windows/Mac: lsof -i :3000
# Stop conflicting service or change port in docker-compose.yml
“No space left on device”
# Check disk usage
docker system df
# Clean up everything
docker system prune -a --volumes -f
# Remove specific large images
docker images
docker rmi image_id
“Permission denied” on volumes
# Fix host directory permissions
sudo chown -R $USER:$USER /host/directory
# Or run container as current user
docker-compose exec -u $(id -u):$(id -g) service_name command
Pro Tips
- Use .dockerignore – Exclude unnecessary files from build context
- Multi-stage builds – Reduce final image size
- Health checks – Ensure containers are healthy
- Docker layers – Order instructions to maximize cache usage
- Security – Use non-root users, scan images
- Networking – Understand bridge, host, and overlay networks
- Resource limits – Set CPU and memory limits
- Logging – Configure proper log drivers and rotation
Remember: Containers are ephemeral! Use volumes for persistent data.
Leave a Reply