Files
dotfiles/sources/opencode/skills/docker/SKILL.md
T

10 KiB

name, description, metadata
name description metadata
docker Docker containerization - images, containers, volumes, networking, docker-compose, best practices
language audience
bash developers

Overview

Docker is a platform for developing, shipping, and running applications in containers. Use this skill when working with Docker or Docker Compose.

Installation

Docker Engine

# Ubuntu/Debian
sudo apt update
sudo apt install docker.io
sudo systemctl start docker
sudo systemctl enable docker

# Add user to docker group
sudo usermod -aG docker $USER

Docker Compose

# Standalone (recommended)
sudo curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose

Verify installation:

docker --version
docker-compose --version

Basic Concepts

Images

  • Image: A read-only template for creating containers
  • Container: A runnable instance of an image
  • Tag: Version identifier for images (e.g., nginx:latest)
  • Registry: Storage for images (Docker Hub, GHCR, ECR, etc.)

Common Commands

# List images
docker images
docker image ls

# Pull an image
docker pull nginx:latest

# Remove an image
docker rmi nginx:latest

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

# Tag an image
docker tag myapp:latest registry.io/myapp:latest

# Push to registry
docker push registry.io/myapp:latest

Docker Contexts

Docker contexts allow you to manage connections to multiple Docker hosts from a single Docker CLI. Useful for switching between local Docker, remote servers, or Kubernetes clusters.

Basic Context Management

# List all contexts
docker context ls

# Show current context
docker context show

# Use a specific context
docker context use my-remote-host

# Create a new context
docker context create my-remote-host \
  --docker "host=ssh://user@remote-server:22"

# Create context from existing Docker configuration
docker context create my-context --docker "host=tcp://localhost:2375"

# Inspect a context
docker context inspect my-remote-host

# Remove a context
docker context rm my-remote-host

SSH Context

Connect to a remote Docker host via SSH:

# Create SSH context
docker context create production \
  --docker "host=ssh://user@production-server"

# Use the context
docker context use production
docker ps
docker run -d nginx:latest

Kubernetes Context

# List Kubernetes contexts (requires kubectl)
kubectl config get-contexts

# Create Docker context from Kubernetes context
docker context create k8s-prod \
  --kubernetes "context-name=production"

# Switch to Kubernetes context
docker context use k8s-prod

Use with Docker Compose

# Use a specific context with compose
docker --context my-remote-host compose up -d

# Or set context in compose file (Docker Compose v2)
COMPOSE_DOCKER_CLI_HOST=1 docker compose up -d

Best Practices

  1. Name meaningfully - Use prefixes like local-, prod-, dev-
  2. Test before switching - Use docker context inspect to verify
  3. Keep local default - Keep default or local for local development
  4. Document remote connections - Note SSH keys and endpoints
# Example context setup
docker context create local     # Local Docker (default)
docker context create dev-server --docker "host=ssh://dev@dev-server"
docker context create prod-server --docker "host=ssh://prod@prod-server"

# Quick switch
docker context use dev-server

Dockerfile

Best Practices

  1. Use multi-stage builds - Reduce final image size
  2. Order commands by change frequency - Cache unchanged layers
  3. Use specific tags - Avoid latest in production
  4. Use .dockerignore - Exclude unnecessary files
  5. Run as non-root - Security best practice
  6. Use official base images - Better security and maintenance

Node.js Example

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

# Production stage
FROM node:20-alpine AS production
WORKDIR /app
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/node_modules ./node_modules
USER node
EXPOSE 3000
CMD ["node", "dist/index.js"]

Python Example

FROM python:3.11-slim AS builder
WORKDIR /app
COPY requirements.txt .
RUN pip install --user -r requirements.txt

FROM python:3.11-slim
WORKDIR /app
COPY --from=builder /root/.local /root/.local
COPY . .
ENV PATH=/root/.local/bin:$PATH
EXPOSE 8000
CMD ["python", "main.py"]

.dockerignore

node_modules
.git
.gitignore
.env
.env.*
README.md
dist
build
coverage
*.log
.DS_Store

Containers

Run a Container

# Run in background (detached)
docker run -d myapp:latest

# Run with port mapping
docker run -d -p 8080:3000 myapp:latest

# Run with volume mount
docker run -d -v /host/path:/container/path myapp:latest

# Run with environment variables
docker run -d -e NODE_ENV=production -e API_KEY=xxx myapp:latest

# Run with name
docker run -d --name my-container myapp:latest

# Interactive mode
docker run -it ubuntu:latest /bin/bash

# Remove container after exit
docker run --rm myapp:latest

Container Management

# List running containers
docker ps

# List all containers
docker ps -a

# Stop a container
docker stop my-container

# Start a stopped container
docker start my-container

# Restart a container
docker restart my-container

# Remove a container
docker rm my-container

# Remove all stopped containers
docker container prune

# View logs
docker logs -f my-container

# Execute command in running container
docker exec -it my-container sh

# Inspect container details
docker inspect my-container

# View resource usage
docker stats my-container

Volumes

Named Volumes

# Create a volume
docker volume create my-data

# List volumes
docker volume ls

# Inspect volume
docker volume inspect my-data

# Remove volume
docker volume rm my-data

Bind Mounts

# Mount host directory
docker run -v /host/path:/container/path myapp:latest

# Mount read-only
docker run -v /host/path:/container/path:ro myapp:latest

Use in Dockerfile

VOLUME /app/data

Networking

Networks

# Create a network
docker network create my-network

# List networks
docker network ls

# Connect container to network
docker network connect my-network my-container

# Disconnect container from network
docker network disconnect my-network my-container

Port Exposure

EXPOSE 3000 8080

Docker Compose

Basic Structure

version: '3.8'

services:
  app:
    build: .
    ports:
      - "3000:3000"
    environment:
      - NODE_ENV=production
    volumes:
      - ./data:/app/data
    depends_on:
      - db
    restart: unless-stopped

  db:
    image: postgres:15-alpine
    environment:
      POSTGRES_DB: myapp
      POSTGRES_USER: user
      POSTGRES_PASSWORD: password
    volumes:
      - db-data:/var/lib/postgresql/data
    restart: unless-stopped

volumes:
  db-data:

Common Commands

# Start services
docker-compose up -d

# Start with build
docker-compose up -d --build

# Stop services
docker-compose down

# Stop and remove volumes
docker-compose down -v

# View logs
docker-compose logs -f

# List services
docker-compose ps

# Execute command in service
docker-compose exec app sh

# Scale a service
docker-compose up -d --scale app=3

Healthchecks

services:
  app:
    build: .
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:3000/health"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 40s

Profiles

services:
  app:
    build: .
  
  debug:
    build: .
    profiles:
      - debug
    command: ["sleep", "infinity"]

Run with profile: docker-compose --profile debug up

Development

Development with Volumes

services:
  app:
    build:
      context: .
      target: development
    volumes:
      - .:/app
      - /app/node_modules
    environment:
      - NODE_ENV=development
    command: npm run dev

Hot Reload

For Node.js with nodemon:

FROM node:20-alpine
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
CMD ["npm", "run", "dev"]

Security Best Practices

  1. Don't run as root - Use USER directive
  2. Scan for vulnerabilities - Use docker scout or trivy
  3. Use specific tags - Not latest
  4. Read-only containers - Use --read-only flag
  5. Limit capabilities - Use --cap-drop and --cap-add
  6. Secrets management - Use Docker secrets or environment variables
  7. Multi-stage builds - Minimize attack surface
# Security scanning
docker scout cves myapp:latest

# Run securely
docker run \
  --read-only \
  --cap-drop ALL \
  --user 1000:1000 \
  myapp:latest

Debugging

# Interactive shell
docker run -it --rm myapp:latest sh

# Inspect with dive (if installed)
dive myapp:latest

# Check layers
docker history myapp:latest

# Debug running container
docker exec sh

# Copy files from -it my-container container
docker cp my-container:/app/logs ./logs

Common Patterns

Node.js + Nginx

services:
  app:
    build: ./app
    expose:
      - "3000"
  
  nginx:
    image: nginx:alpine
    ports:
      - "80:80"
    volumes:
      - ./nginx.conf:/etc/nginx/nginx.conf:ro
    depends_on:
      - app

Database + Backup

services:
  db:
    image: postgres:15-alpine
    volumes:
      - db-data:/var/lib/postgresql/data
  
  backup:
    image: postgres:15-alpine
    volumes:
      - ./backups:/backups
    command: >
      sh -c "while true; do
        pg_dump -h db -U postgres mydb > /backups/backup-$$(date +%Y%m%d-%H%M%S).sql;
        sleep 86400;
      done"
    depends_on:
      - db

Tips

  • Use docker system prune -a to clean up unused resources
  • Use --force-rm when building to remove intermediate containers
  • Use -f flag to force operations
  • Use --no-cache for clean builds
  • Tag images before pushing to registries
  • Use docker-compose config to validate compose files