NYC

docker-expert

SKILL.md

Docker Expert

You are an expert in Docker containerization with deep knowledge of Dockerfile optimization, multi-stage builds, container security, networking, and Docker Compose orchestration.

Core Expertise

Docker Fundamentals

  • Images: Building, layering, caching strategies, image optimization
  • Containers: Lifecycle management, resource limits, health checks
  • Registries: Docker Hub, private registries, image tagging strategies
  • Storage: Volumes, bind mounts, tmpfs mounts
  • Networking: Bridge, host, overlay, custom networks
  • Security: User namespaces, capabilities, secrets management

Dockerfile Best Practices

  • Multi-stage builds: Reducing image size and build time
  • Layer optimization: Minimizing layers and cache invalidation
  • Base images: Choosing appropriate base images (Alpine, Distroless, scratch)
  • Build arguments: Parameterized builds
  • Health checks: Container health monitoring
  • Signals: Proper signal handling and graceful shutdown

Docker Compose

  • Service definition: Multi-container applications
  • Dependencies: Service dependencies and startup order
  • Networking: Service discovery and communication
  • Volumes: Persistent data management
  • Environment variables: Configuration management
  • Profiles: Environment-specific configurations

Best Practices

1. Dockerfile Optimization

Multi-stage build for minimal size:

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

COPY . .
RUN npm run build

# Production stage
FROM node:20-alpine
WORKDIR /app

# Copy only production dependencies and built files
COPY --from=builder /app/node_modules ./node_modules
COPY --from=builder /app/dist ./dist
COPY package.json ./

# Run as non-root user
RUN addgroup -g 1001 -S nodejs && \
    adduser -S nodejs -u 1001
USER nodejs

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

Layer caching optimization:

FROM python:3.11-slim

WORKDIR /app

# Install dependencies first (changes less frequently)
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

# Copy application code (changes more frequently)
COPY . .

CMD ["python", "app.py"]

Use .dockerignore:

node_modules
npm-debug.log
.git
.gitignore
README.md
.env
.DS_Store
*.md
dist
coverage
.pytest_cache
__pycache__

2. Security Best Practices

Run as non-root user:

FROM node:20-alpine

# Create app user
RUN addgroup -g 1001 -S nodejs && \
    adduser -S nodejs -u 1001

WORKDIR /app

# Copy and install as root
COPY package*.json ./
RUN npm ci --only=production

# Copy app files
COPY --chown=nodejs:nodejs . .

# Switch to non-root user
USER nodejs

EXPOSE 3000
CMD ["node", "server.js"]

Use distroless images:

# Build stage
FROM golang:1.21-alpine AS builder
WORKDIR /app
COPY . .
RUN CGO_ENABLED=0 GOOS=linux go build -o app

# Production stage with distroless
FROM gcr.io/distroless/static-debian11
COPY --from=builder /app/app /app
ENTRYPOINT ["/app"]

Scan images for vulnerabilities:

# Using Docker Scout
docker scout cves my-image:latest

# Using Trivy
trivy image my-image:latest

3. Resource Management

Set resource limits:

# docker-compose.yml
services:
  app:
    image: my-app:latest
    deploy:
      resources:
        limits:
          cpus: '0.5'
          memory: 512M
        reservations:
          cpus: '0.25'
          memory: 256M

Health checks:

HEALTHCHECK --interval=30s --timeout=3s --start-period=40s --retries=3 \
  CMD wget --quiet --tries=1 --spider http://localhost:3000/health || exit 1

4. Networking

Custom network for service isolation:

services:
  frontend:
    networks:
      - frontend-network

  backend:
    networks:
      - frontend-network
      - backend-network

  database:
    networks:
      - backend-network

networks:
  frontend-network:
  backend-network:

Common Tasks

Task 1: Create Optimized Node.js Image

# Multi-stage build for Node.js application
FROM node:20-alpine AS builder

WORKDIR /app

# Copy package files
COPY package*.json ./

# Install all dependencies (including dev)
RUN npm ci

# Copy source code
COPY . .

# Build application
RUN npm run build

# Prune dev dependencies
RUN npm prune --production

# Production image
FROM node:20-alpine

# Add security updates
RUN apk add --no-cache dumb-init

WORKDIR /app

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

# Copy built application and dependencies
COPY --from=builder --chown=nodejs:nodejs /app/dist ./dist
COPY --from=builder --chown=nodejs:nodejs /app/node_modules ./node_modules
COPY --chown=nodejs:nodejs package.json ./

# Switch to non-root user
USER nodejs

# Expose port
EXPOSE 3000

# Health check
HEALTHCHECK --interval=30s --timeout=3s \
  CMD node healthcheck.js || exit 1

# Use dumb-init to handle signals properly
ENTRYPOINT ["dumb-init", "--"]
CMD ["node", "dist/index.js"]

Task 2: Python Application with Dependencies

FROM python:3.11-slim

# Install system dependencies
RUN apt-get update && \
    apt-get install -y --no-install-recommends \
    gcc \
    && rm -rf /var/lib/apt/lists/*

WORKDIR /app

# Create virtual environment
RUN python -m venv /opt/venv
ENV PATH="/opt/venv/bin:$PATH"

# Install Python dependencies
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

# Copy application
COPY . .

# Create non-root user
RUN useradd -m -u 1001 appuser && \
    chown -R appuser:appuser /app
USER appuser

EXPOSE 8000

CMD ["gunicorn", "--bind", "0.0.0.0:8000", "app:app"]

Task 3: Multi-Service Application with Docker Compose

version: '3.9'

services:
  # Frontend service
  frontend:
    build:
      context: ./frontend
      dockerfile: Dockerfile
    ports:
      - '3000:3000'
    environment:
      - API_URL=http://backend:4000
    depends_on:
      backend:
        condition: service_healthy
    networks:
      - app-network
    restart: unless-stopped

  # Backend service
  backend:
    build:
      context: ./backend
      dockerfile: Dockerfile
    ports:
      - '4000:4000'
    environment:
      - DATABASE_URL=postgresql://user:password@database:5432/mydb
      - REDIS_URL=redis://cache:6379
    depends_on:
      database:
        condition: service_healthy
      cache:
        condition: service_started
    networks:
      - app-network
      - db-network
    healthcheck:
      test: ['CMD', 'curl', '-f', 'http://localhost:4000/health']
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 40s
    restart: unless-stopped

  # PostgreSQL database
  database:
    image: postgres:16-alpine
    environment:
      - POSTGRES_USER=user
      - POSTGRES_PASSWORD=password
      - POSTGRES_DB=mydb
    volumes:
      - postgres-data:/var/lib/postgresql/data
      - ./init.sql:/docker-entrypoint-initdb.d/init.sql
    networks:
      - db-network
    healthcheck:
      test: ['CMD-SHELL', 'pg_isready -U user']
      interval: 10s
      timeout: 5s
      retries: 5
    restart: unless-stopped

  # Redis cache
  cache:
    image: redis:7-alpine
    command: redis-server --appendonly yes
    volumes:
      - redis-data:/data
    networks:
      - app-network
    restart: unless-stopped

networks:
  app-network:
    driver: bridge
  db-network:
    driver: bridge

volumes:
  postgres-data:
  redis-data:

Task 4: Development Environment with Hot Reload

version: '3.9'

services:
  app:
    build:
      context: .
      target: development
    volumes:
      - .:/app
      - /app/node_modules
    ports:
      - '3000:3000'
      - '9229:9229' # Node.js debugger
    environment:
      - NODE_ENV=development
    command: npm run dev

Dockerfile with development target:

FROM node:20-alpine AS base
WORKDIR /app
COPY package*.json ./

FROM base AS development
RUN npm install
COPY . .
CMD ["npm", "run", "dev"]

FROM base AS production
RUN npm ci --only=production
COPY . .
CMD ["node", "dist/index.js"]

Task 5: Build and Deploy

# Build image
docker build -t my-app:latest .

# Build with specific target
docker build --target production -t my-app:prod .

# Build with build args
docker build --build-arg NODE_ENV=production -t my-app:latest .

# Tag for registry
docker tag my-app:latest registry.example.com/my-app:1.0.0

# Push to registry
docker push registry.example.com/my-app:1.0.0

# Run container
docker run -d \
  --name my-app \
  --restart unless-stopped \
  -p 3000:3000 \
  -e NODE_ENV=production \
  my-app:latest

# Using Docker Compose
docker-compose up -d
docker-compose ps
docker-compose logs -f
docker-compose down

Anti-Patterns to Avoid

❌ Don't Run as Root

# Bad
FROM node:20
WORKDIR /app
COPY . .
CMD ["node", "server.js"]  # Runs as root

# Good
FROM node:20
WORKDIR /app
COPY . .
RUN useradd -m appuser
USER appuser
CMD ["node", "server.js"]

❌ Don't Install Unnecessary Packages

# Bad
FROM ubuntu:22.04
RUN apt-get update && apt-get install -y \
    curl wget vim emacs nano  # Unnecessary in production

# Good
FROM ubuntu:22.04
RUN apt-get update && apt-get install -y --no-install-recommends \
    ca-certificates \
    && rm -rf /var/lib/apt/lists/*

❌ Don't Use Latest Tag in Production

# Bad
FROM node:latest  # Unpredictable

# Good
FROM node:20.10.0-alpine3.18  # Specific version

❌ Don't Embed Secrets in Images

# Bad
COPY .env .
ENV API_KEY=secret123  # Hard-coded secret

# Good
# Use secrets or environment variables at runtime
docker run -e API_KEY=$API_KEY my-app
# Or use Docker secrets (Swarm/Kubernetes)

Advanced Patterns

BuildKit Cache Mounts

# syntax=docker/dockerfile:1

FROM golang:1.21-alpine

WORKDIR /app

# Cache go modules
RUN --mount=type=cache,target=/go/pkg/mod \
    --mount=type=bind,source=go.sum,target=go.sum \
    --mount=type=bind,source=go.mod,target=go.mod \
    go mod download

COPY . .

# Cache build artifacts
RUN --mount=type=cache,target=/go/pkg/mod \
    --mount=type=cache,target=/root/.cache/go-build \
    go build -o /app/server .

CMD ["/app/server"]

Docker Compose with Profiles

services:
  app:
    profiles: ['production', 'development']
    # ...

  test-db:
    profiles: ['development']
    # Only runs in development
    image: postgres:16-alpine

  monitoring:
    profiles: ['production']
    # Only runs in production
    image: prometheus
# Run with specific profile
docker-compose --profile development up
docker-compose --profile production up

Checklist

When creating Docker images:

  • Use multi-stage builds to reduce image size
  • Run containers as non-root user
  • Use specific image tags, not latest
  • Add .dockerignore file
  • Optimize layer caching
  • Set health checks
  • Define resource limits
  • Use distroless or minimal base images
  • Scan images for vulnerabilities
  • Handle signals properly (SIGTERM)
  • Set proper restart policies
  • Use secrets management (not environment variables)
  • Document exposed ports and volumes
  • Test images before deploying

Resources

Weekly Installs
43
First Seen
Jan 24, 2026
Installed on
opencode33
claude-code32
gemini-cli30
antigravity26
codex24
github-copilot21