| name | docker |
| description | Guide for using Docker - a containerization platform for building, running, and deploying applications in isolated containers. Use when containerizing applications, creating Dockerfiles, working with Docker Compose, managing images/containers, configuring networking and storage, optimizing builds, deploying to production, or implementing CI/CD pipelines with Docker. |
Docker Skill
This skill provides comprehensive guidance for working with Docker, covering containerization concepts, practical workflows, and best practices across all major technology stacks.
When to Use This Skill
Use this skill when:
- Containerizing applications for any language or framework
- Creating or optimizing Dockerfiles and Docker Compose configurations
- Setting up development environments with Docker
- Deploying containerized applications to production
- Implementing CI/CD pipelines with Docker
- Managing container networking, storage, and security
- Troubleshooting Docker-related issues
- Building multi-platform images
- Implementing microservices architectures
Core Docker Concepts
Containers
- Lightweight, isolated processes that bundle applications with all dependencies
- Provide filesystem isolation via union filesystems and namespace technology
- Ephemeral by default - changes are lost when container stops (unless persisted to volumes)
- Single responsibility principle: each container should do one thing well
- Multiple identical containers can run from same immutable image without conflicts
Images
- Blueprint/template for containers - read-only filesystems + configuration
- Composed of layered filesystem (immutable, reusable layers)
- Built from Dockerfile instructions or committed from running containers
- Stored in registries (Docker Hub, ECR, ACR, GCR, private registries)
- Image naming:
REGISTRY/NAMESPACE/REPOSITORY:TAG (e.g., docker.io/library/nginx:latest)
Volumes & Storage
- Volumes: Docker-managed persistent storage that survives container deletion
- Bind mounts: Direct mapping of host filesystem paths into containers
- tmpfs mounts: In-memory storage for temporary data
- Enable data sharing between containers and persist beyond container lifecycle
Networks
- Default bridge network connects containers on same host
- Custom networks allow explicit container communication with DNS resolution
- Host network removes network isolation for performance
- Overlay networks enable multi-host container communication (Swarm)
- MACVLAN/IPvlan for containers needing direct L2/L3 network access
Dockerfile Best Practices
Essential Instructions
FROM <image>:<tag> # Base image (use specific versions, not 'latest')
WORKDIR /app # Working directory for subsequent commands
COPY package*.json ./ # Copy dependency files first (for caching)
RUN npm install --production # Execute build commands
COPY . . # Copy application code
ENV NODE_ENV=production # Environment variables
EXPOSE 3000 # Document exposed ports
USER node # Run as non-root user (security)
CMD ["node", "server.js"] # Default command when container starts
Multi-Stage Builds (Critical for Production)
Separate build environment from runtime environment to reduce image size and improve security:
# Stage 1: Build
FROM node:20-alpine AS build
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
RUN npm run build
# Stage 2: Production
FROM node:20-alpine AS production
WORKDIR /app
COPY --from=build /app/dist ./dist
COPY --from=build /app/node_modules ./node_modules
USER node
EXPOSE 3000
CMD ["node", "dist/server.js"]
Benefits: Compiled assets without build tools in final image, smaller size, improved security
Layer Caching Optimization
Order matters! Docker reuses layers if instruction unchanged:
- Dependencies first (COPY package.json, RUN npm install)
- Application code last (COPY . .)
- This way, code changes don't invalidate dependency layers
Security Hardening
# Use specific versions
FROM node:20.11.0-alpine3.19
# Create non-root user
RUN addgroup -g 1001 -S nodejs && \
adduser -S nodejs -u 1001
# Set ownership
COPY --chown=nodejs:nodejs . .
# Switch to non-root
USER nodejs
# Read-only root filesystem (when possible)
# Add --read-only flag when running container
.dockerignore File
Exclude unnecessary files from build context:
node_modules
.git
.env
.env.local
*.log
.DS_Store
README.md
docker-compose.yml
.dockerignore
Dockerfile
dist
coverage
.vscode
Common Workflows
Building Images
docker build -t myapp:1.0 .
docker build -t myapp:dev --target build .
docker build --build-arg NODE_ENV=production -t myapp:1.0 .
docker buildx build --platform linux/amd64,linux/arm64 -t myapp:1.0 .
docker image history myapp:1.0
docker image ls
Running Containers
docker run myapp:1.0
docker run -d --name myapp myapp:1.0
docker run -p 8080:3000 myapp:1.0
docker run -e NODE_ENV=production -e API_KEY=secret myapp:1.0
docker run -v mydata:/app/data myapp:1.0
docker run -v $(pwd)/src:/app/src myapp:1.0
docker run --network my-network myapp:1.0
docker run --memory 512m --cpus 0.5 myapp:1.0
docker run -it myapp:1.0 /bin/sh
docker run --entrypoint /bin/sh myapp:1.0
docker run myapp:1.0 custom-command --arg
Container Management
docker ps
docker ps -a
docker logs myapp
docker logs -f myapp
docker logs --tail 100 myapp
docker exec myapp ls /app
docker exec -it myapp /bin/sh
docker stop myapp
docker kill myapp
docker rm myapp
docker rm -f myapp
docker inspect myapp
docker stats myapp
docker top myapp
docker cp myapp:/app/logs ./logs
docker cp ./config.json myapp:/app/config.json
Image Management
docker tag myapp:1.0 registry.example.com/myapp:1.0
docker login registry.example.com
docker push registry.example.com/myapp:1.0
docker pull nginx:alpine
docker image rm myapp:1.0
docker image prune
docker system prune -a
docker system df
Volume Management
docker volume create mydata
docker volume ls
docker volume inspect mydata
docker volume rm mydata
docker volume prune
Network Management
docker network create my-network
docker network create --driver bridge my-bridge
docker network ls
docker network inspect my-network
docker network connect my-network myapp
docker network disconnect my-network myapp
docker network rm my-network
Docker Compose
When to Use Compose
- Multi-container applications (web + database + cache)
- Consistent development environments across team
- Simplifying complex docker run commands
- Managing application dependencies and startup order
Basic Compose File Structure
version: '3.8'
services:
web:
build: .
ports:
- "3000:3000"
environment:
- NODE_ENV=production
- DATABASE_URL=postgresql://user:pass@db:5432/app
depends_on:
- db
- redis
volumes:
- ./src:/app/src
networks:
- app-network
restart: unless-stopped
db:
image: postgres:15-alpine
environment:
POSTGRES_USER: user
POSTGRES_PASSWORD: pass
POSTGRES_DB: app
volumes:
- postgres_data:/var/lib/postgresql/data
networks:
- app-network
healthcheck:
test: ["CMD-SHELL", "pg_isready -U user"]
interval: 10s
timeout: 5s
retries: 5
redis:
image: redis:7-alpine
networks:
- app-network
volumes:
- redis_data:/data
volumes:
postgres_data:
redis_data:
networks:
app-network:
driver: bridge
Compose Commands
docker compose up
docker compose up -d
docker compose up --build
docker compose up -d --scale web=3
docker compose down
docker compose down --volumes
docker compose logs
docker compose logs -f web
docker compose exec web sh
docker compose exec db psql -U user -d app
docker compose ps
docker compose restart web
docker compose pull
docker compose config
Development vs Production Compose
compose.yml (base configuration):
services:
web:
build: .
ports:
- "3000:3000"
environment:
- DATABASE_URL=postgresql://user:pass@db:5432/app
compose.override.yml (development overrides, loaded automatically):
services:
web:
volumes:
- ./src:/app/src
environment:
- NODE_ENV=development
- DEBUG=true
command: npm run dev
compose.prod.yml (production overrides):
services:
web:
image: registry.example.com/myapp:1.0
restart: always
environment:
- NODE_ENV=production
deploy:
replicas: 3
resources:
limits:
cpus: '0.5'
memory: 512M
Usage:
docker compose up
docker compose -f compose.yml -f compose.prod.yml up -d
Language-Specific Dockerfiles
Node.js
FROM node:20-alpine AS build
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY . .
RUN npm run build
FROM node:20-alpine AS production
WORKDIR /app
COPY --from=build /app/dist ./dist
COPY --from=build /app/node_modules ./node_modules
COPY package*.json ./
USER node
EXPOSE 3000
CMD ["node", "dist/server.js"]
Python
FROM python:3.11-slim AS build
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
FROM python:3.11-slim AS production
WORKDIR /app
COPY --from=build /usr/local/lib/python3.11/site-packages /usr/local/lib/python3.11/site-packages
COPY . .
RUN adduser --disabled-password --gecos '' appuser && \
chown -R appuser:appuser /app
USER appuser
EXPOSE 8000
CMD ["python", "app.py"]
Go
FROM golang:1.21-alpine AS build
WORKDIR /app
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 GOOS=linux go build -o main .
FROM scratch
COPY --from=build /app/main /main
EXPOSE 8080
CMD ["/main"]
Java (Spring Boot)
FROM eclipse-temurin:21-jdk-alpine AS build
WORKDIR /app
COPY pom.xml .
COPY src ./src
RUN ./mvnw clean package -DskipTests
FROM eclipse-temurin:21-jre-alpine AS production
WORKDIR /app
COPY --from=build /app/target/*.jar app.jar
RUN addgroup -g 1001 -S spring && \
adduser -S spring -u 1001
USER spring
EXPOSE 8080
ENTRYPOINT ["java", "-jar", "app.jar"]
React/Vue/Angular (Static SPA)
FROM node:20-alpine AS build
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
FROM nginx:alpine AS production
COPY --from=build /app/dist /usr/share/nginx/html
COPY nginx.conf /etc/nginx/nginx.conf
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
Production Deployment
Health Checks
In Dockerfile:
HEALTHCHECK --interval=30s --timeout=3s --start-period=40s --retries=3 \
CMD curl -f http://localhost:3000/health || exit 1
In Compose:
services:
web:
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:3000/health"]
interval: 30s
timeout: 3s
start-period: 40s
retries: 3
Resource Limits
services:
web:
deploy:
resources:
limits:
cpus: '0.5'
memory: 512M
reservations:
cpus: '0.25'
memory: 256M
Restart Policies
services:
web:
restart: unless-stopped
Logging Configuration
services:
web:
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"
Environment Variables & Secrets
Using .env file:
DATABASE_URL=postgresql://user:pass@db:5432/app
API_KEY=secret
services:
web:
env_file:
- .env
Using Docker secrets (Swarm):
services:
web:
secrets:
- db_password
secrets:
db_password:
external: true
Production Checklist
- ✅ Use specific image versions (not
latest)
- ✅ Run as non-root user
- ✅ Multi-stage builds to minimize image size
- ✅ Health checks implemented
- ✅ Resource limits configured
- ✅ Restart policy set
- ✅ Logging configured
- ✅ Secrets managed securely (not in environment variables)
- ✅ Vulnerability scanning (Docker Scout)
- ✅ Read-only root filesystem when possible
- ✅ Network segmentation
- ✅ Regular image updates
CI/CD Integration
GitHub Actions Example
name: Docker Build and Push
on:
push:
branches: [ main ]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Login to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
- name: Build and push
uses: docker/build-push-action@v5
with:
context: .
push: true
tags: user/app:latest,user/app:${{ github.sha }}
cache-from: type=registry,ref=user/app:buildcache
cache-to: type=registry,ref=user/app:buildcache,mode=max
- name: Run vulnerability scan
uses: docker/scout-action@v1
with:
command: cves
image: user/app:${{ github.sha }}
Security Best Practices
Scan for Vulnerabilities
docker scout cves myapp:1.0
docker scout recommendations myapp:1.0
docker scout quickview myapp:1.0
Run Containers Securely
docker run --read-only -v /tmp --tmpfs /run myapp:1.0
docker run --cap-drop=ALL --cap-add=NET_BIND_SERVICE myapp:1.0
docker run --security-opt=no-new-privileges myapp:1.0
docker run --security-opt apparmor=docker-default myapp:1.0
docker run --memory=512m --cpus=0.5 --pids-limit=100 myapp:1.0
Image Security Checklist
- ✅ Start with minimal base images (Alpine, Distroless)
- ✅ Use specific versions, not
latest
- ✅ Scan for vulnerabilities regularly
- ✅ Run as non-root user
- ✅ Don't include secrets in images (use runtime secrets)
- ✅ Minimize attack surface (only install needed packages)
- ✅ Use multi-stage builds (no build tools in final image)
- ✅ Sign and verify images
- ✅ Keep images updated
Networking Patterns
Bridge Network (Default)
docker network create my-bridge
docker run -d --name web --network my-bridge nginx
docker run -d --name db --network my-bridge postgres
Container Communication
services:
web:
depends_on:
- db
environment:
- DATABASE_URL=postgresql://user:pass@db:5432/app
db:
image: postgres:15-alpine
Port Publishing
docker run -p 8080:80 nginx
docker run -p 8080-8090:8080-8090 myapp
docker run -p 127.0.0.1:8080:80 nginx
docker run -P nginx
Storage Patterns
Named Volumes (Recommended for Data)
docker volume create app-data
docker run -v app-data:/app/data myapp
docker run -v app-data:/app/data myapp
Bind Mounts (Development)
docker run -v $(pwd)/src:/app/src myapp
docker run -v $(pwd)/config:/app/config:ro myapp
tmpfs Mounts (Temporary In-Memory)
docker run --tmpfs /tmp myapp
Volume Backup & Restore
docker run --rm -v app-data:/data -v $(pwd):/backup alpine \
tar czf /backup/backup.tar.gz /data
docker run --rm -v app-data:/data -v $(pwd):/backup alpine \
tar xzf /backup/backup.tar.gz -C /data
Troubleshooting
Debug Running Container
docker logs -f myapp
docker logs --tail 100 myapp
docker exec -it myapp /bin/sh
docker inspect myapp
docker top myapp
docker stats myapp
docker diff myapp
Debug Build Issues
docker build --progress=plain -t myapp .
docker build --target build -t myapp:build .
docker run -it myapp:build /bin/sh
docker build --no-cache -t myapp .
Common Issues
Container exits immediately:
docker logs myapp
docker run -it myapp /bin/sh
docker run -it --entrypoint /bin/sh myapp
Cannot connect to container:
docker ps
docker port myapp
docker network inspect bridge
docker inspect myapp | grep IPAddress
docker exec myapp netstat -tulpn
Out of disk space:
docker system df
docker system prune -a
docker volume prune
docker image prune -a
Build cache issues:
docker build --no-cache -t myapp .
docker builder prune
Advanced Topics
Multi-Platform Builds
docker buildx create --use
docker buildx build --platform linux/amd64,linux/arm64 \
-t myapp:1.0 --push .
Build Optimization
DOCKER_BUILDKIT=1 docker build -t myapp .
docker build --cache-from myapp:latest -t myapp:1.0 .
docker build --cache-to type=registry,ref=myapp:buildcache \
--cache-from type=registry,ref=myapp:buildcache \
-t myapp:1.0 .
Docker Contexts
docker context ls
docker context create remote --docker "host=ssh://user@remote"
docker context use remote
docker ps
docker context use default
Quick Reference
Most Common Commands
| Task | Command |
|---|
| Build image | docker build -t myapp:1.0 . |
| Run container | docker run -d -p 8080:3000 myapp:1.0 |
| View logs | docker logs -f myapp |
| Shell into container | docker exec -it myapp /bin/sh |
| Stop container | docker stop myapp |
| Remove container | docker rm myapp |
| Start Compose | docker compose up -d |
| Stop Compose | docker compose down |
| View Compose logs | docker compose logs -f |
| Clean up all | docker system prune -a |
Recommended Base Images
| Language/Framework | Recommended Base |
|---|
| Node.js | node:20-alpine |
| Python | python:3.11-slim |
| Java | eclipse-temurin:21-jre-alpine |
| Go | scratch (for compiled binary) |
| .NET | mcr.microsoft.com/dotnet/aspnet:8.0-alpine |
| PHP | php:8.2-fpm-alpine |
| Ruby | ruby:3.2-alpine |
| Static sites | nginx:alpine |
Additional Resources
Summary
Docker containerization provides:
- Consistency across development, testing, and production
- Isolation for applications and dependencies
- Portability across different environments
- Efficiency through layered architecture and caching
- Scalability for microservices and distributed systems
Follow multi-stage builds, run as non-root, use specific versions, implement health checks, scan for vulnerabilities, and configure resource limits for production-ready containerized applications.