Skip to content
Docker & Kubernetes logo

Docker & Kubernetes

Dockerfile best practices, multi-stage builds, docker-compose patterns, and Kubernetes concepts

SKILL.md

Full skill instructions

Docker & Kubernetes

When to Use

Perfect for:

  • Containerizing applications for consistent deployment
  • Microservices architecture
  • CI/​CD pipelines with reproducible builds
  • Local development environments matching production
  • Scaling applications across multiple machines

Not ideal for:

  • GUI desktop applications (limited container benefits)
  • Real-time high-performance computing (overhead)
  • Single-server monoliths (overkill unless scaling needs exist)

Quick Reference

Dockerfile Best Practices

# Bad - large final image, hard to debug
FROM ubuntu:22.04
RUN apt-get update && apt-get install -y python3 python3-pip
COPY . /​app
WORKDIR /​app
RUN pip install -r requirements.txt
CMD ["python3", "app.py"]

# Good - multi-stage, minimal final image, clear layers
FROM python:3.11-slim as builder

WORKDIR /​app
COPY requirements.txt .
RUN pip install --no-cache-dir --user -r requirements.txt

FROM python:3.11-slim

# Use non-root user
RUN useradd -m -u 1000 appuser

WORKDIR /​app

# Copy only necessary files from builder
COPY --from=builder /​root/​.local /​home/​appuser/​.local
COPY --chown=appuser:appuser app.py .

USER appuser
ENV PATH=/​home/​appuser/​.local/​bin:$PATH
ENV PYTHONUNBUFFERED=1

HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \
    CMD python -c "import requests; requests.get('http://localhost:8000/​health')"

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

Multi-Stage Build Pattern

# Stage 1: Build
FROM node:18-alpine as builder

WORKDIR /​app
COPY package*.json ./
RUN npm ci --only=production && npm cache clean --force

COPY . .
RUN npm run build

# Stage 2: Runtime
FROM node:18-alpine

RUN apk add --no-cache dumb-init
RUN addgroup -g 1000 app && adduser -u 1000 -G app -s /​bin/​sh -D app

WORKDIR /​app

# Copy only runtime dependencies and built app
COPY --from=builder --chown=app:app /​app/​node_modules ./​node_modules
COPY --from=builder --chown=app:app /​app/​dist ./​dist
COPY --chown=app:app package.json .

USER app

EXPOSE 3000
ENTRYPOINT ["dumb-init", "--"]
CMD ["node", "dist/​index.js"]

Docker Image Optimization

# Layer caching - order matters (least to most frequently changed)
FROM python:3.11-slim

# Stable dependency installation
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

# Application code (changes frequently)
COPY . /​app
WORKDIR /​app

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

Environment Configuration

# Build arguments (build-time)
FROM python:3.11-slim

ARG BUILD_DATE
ARG VCS_REF
ARG VERSION=1.0.0

LABEL org.label-schema.build-date=$BUILD_DATE \
      org.label-schema.vcs-ref=$VCS_REF \
      org.label-schema.version=$VERSION

# Runtime environment variables
ENV APP_ENV=production \
    PYTHONUNBUFFERED=1 \
    PYTHONDONTWRITEBYTECODE=1 \
    PORT=8000

EXPOSE $PORT

Docker Compose Pattern

version: '3.8'

services:
  web:
    build:
      context: .
      dockerfile: Dockerfile
    container_name: myapp_web
    ports:
      - "8000:8000"
    environment:
      DATABASE_URL: postgresql://user:pass@db:5432/​myapp
      REDIS_URL: redis://cache:6379/​0
    depends_on:
      db:
        condition: service_healthy
      cache:
        condition: service_started
    volumes:
      - ./​app:/​app  # Development only
    networks:
      - app_network
    restart: unless-stopped
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:8000/​health"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 10s

  db:
    image: postgres:15-alpine
    container_name: myapp_db
    environment:
      POSTGRES_USER: user
      POSTGRES_PASSWORD: pass
      POSTGRES_DB: myapp
    volumes:
      - db_data:/​var/​lib/​postgresql/​data
      - ./​scripts/​init.sql:/​docker-entrypoint-initdb.d/​init.sql
    networks:
      - app_network
    restart: unless-stopped
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U user"]
      interval: 10s
      timeout: 5s
      retries: 5

  cache:
    image: redis:7-alpine
    container_name: myapp_cache
    ports:
      - "6379:6379"
    volumes:
      - cache_data:/​data
    networks:
      - app_network
    restart: unless-stopped
    command: redis-server --appendonly yes

volumes:
  db_data:
  cache_data:

networks:
  app_network:
    driver: bridge

Security Best Practices

# Use official base images
FROM python:3.11-slim

# Run as non-root user
RUN useradd -m -u 1000 appuser
USER appuser

# Minimize layer count and image size
RUN apt-get update && \
    apt-get install -y --no-install-recommends curl && \
    rm -rf /​var/​lib/​apt/​lists/​*

# Use specific image tags (never "latest")
FROM postgres:15.1-alpine

# Set read-only filesystem where possible
RUN chmod -R 755 /​app

# Use secrets management for sensitive data (Docker Swarm/​Kubernetes)
# Never hardcode secrets in Dockerfile

Deep Dive

Health Checks

# HTTP-based health check
HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \
    CMD curl -f http://localhost:8000/​health || exit 1

# Command-based health check
HEALTHCHECK --interval=30s --timeout=10s \
    CMD python -c "import requests; requests.get('http://localhost:8000/​health')"

# Shell command health check
HEALTHCHECK --interval=10s --timeout=5s \
    CMD ["CMD-SHELL", "pg_isready -U postgres || exit 1"]

Docker Networking

# Bridge network (default, containers can communicate by name)
version: '3.8'

services:
  web:
    image: myapp
    networks:
      - backend

  db:
    image: postgres
    networks:
      - backend

networks:
  backend:
    driver: bridge

# Host network (container shares host's network - performance critical)
services:
  high_perf:
    image: myapp
    network_mode: host  # Performance, but less isolated

# Overlay network (for Swarm mode)
networks:
  distributed:
    driver: overlay
    driver_opts:
      com.docker.network.driver.overlay.vxlan_list: "4789"

Volume Management

# Named volumes (managed by Docker, persistent)
services:
  db:
    image: postgres
    volumes:
      - postgres_data:/​var/​lib/​postgresql/​data

volumes:
  postgres_data:
    driver: local

# Bind mounts (host directory mounted into container)
services:
  web:
    image: myapp
    volumes:
      - /​host/​path:/​container/​path:ro  # Read-only

# Tmpfs volumes (in-memory, lost on container restart)
services:
  app:
    image: myapp
    tmpfs:
      - /​tmp
      - /​run

Container Logging

services:
  app:
    image: myapp
    logging:
      driver: json-file
      options:
        max-size: "10m"
        max-file: "3"
        labels: "service=myapp,env=production"

  # Alternative: Log to syslog
  app_syslog:
    image: myapp
    logging:
      driver: syslog
      options:
        syslog-address: "udp://localhost:514"
        syslog-facility: "daemon"

  # Alternative: Log to ELK stack
  app_elk:
    image: myapp
    logging:
      driver: splunk
      options:
        splunk-token: ${SPLUNK_TOKEN}
        splunk-url: https://localhost:8088

Kubernetes Basics

Pod (Smallest Kubernetes Unit)
apiVersion: v1
kind: Pod
metadata:
  name: myapp-pod
  labels:
    app: myapp
spec:
  containers:
  - name: web
    image: myapp:1.0.0
    ports:
    - containerPort: 8000
    env:
    - name: APP_ENV
      value: "production"
    - name: DATABASE_URL
      valueFrom:
        secretKeyRef:
          name: db-secret
          key: url
    resources:
      requests:
        memory: "256Mi"
        cpu: "250m"
      limits:
        memory: "512Mi"
        cpu: "500m"
    livenessProbe:
      httpGet:
        path: /​health
        port: 8000
      initialDelaySeconds: 10
      periodSeconds: 30
    readinessProbe:
      httpGet:
        path: /​ready
        port: 8000
      initialDelaySeconds: 5
      periodSeconds: 10
Deployment (Stateless Application)
apiVersion: apps/​v1
kind: Deployment
metadata:
  name: myapp
  labels:
    app: myapp
spec:
  replicas: 3
  selector:
    matchLabels:
      app: myapp
  template:
    metadata:
      labels:
        app: myapp
    spec:
      containers:
      - name: web
        image: myapp:1.0.0
        ports:
        - containerPort: 8000
        env:
        - name: DATABASE_URL
          valueFrom:
            secretKeyRef:
              name: db-secret
              key: url
        resources:
          requests:
            memory: "256Mi"
            cpu: "250m"
          limits:
            memory: "512Mi"
            cpu: "500m"
        livenessProbe:
          httpGet:
            path: /​health
            port: 8000
          initialDelaySeconds: 30
          periodSeconds: 10
        readinessProbe:
          httpGet:
            path: /​ready
            port: 8000
          initialDelaySeconds: 5
          periodSeconds: 5
      affinity:
        podAntiAffinity:
          preferredDuringSchedulingIgnoredDuringExecution:
          - weight: 100
            podAffinityTerm:
              labelSelector:
                matchExpressions:
                - key: app
                  operator: In
                  values:
                  - myapp
              topologyKey: kubernetes.io/​hostname
Service (Network Access)
apiVersion: v1
kind: Service
metadata:
  name: myapp-service
spec:
  type: LoadBalancer  # or ClusterIP, NodePort
  selector:
    app: myapp
  ports:
  - name: http
    port: 80
    targetPort: 8000
    protocol: TCP
  sessionAffinity: ClientIP
ConfigMap & Secret
---
apiVersion: v1
kind: ConfigMap
metadata:
  name: app-config
data:
  APP_ENV: "production"
  LOG_LEVEL: "info"
  config.json: |
    {
      "timeout": 30,
      "retries": 3
    }

---
apiVersion: v1
kind: Secret
metadata:
  name: db-secret
type: Opaque
data:
  url: cG9zdGdyZXM6Ly91c2VyOnBhc3NAZGI6NTQzMi9teWFwcA==  # base64 encoded

Anti-Patterns

DON'T: Use "latest" Tag

# Bad - unpredictable, breaks reproducibility
FROM node:latest
FROM python:latest

# Good - specific version
FROM node:18.17.0-alpine
FROM python:3.11.5-slim

DON'T: Run as Root

# Bad - security vulnerability
FROM ubuntu:22.04
RUN apt-get update && apt-get install -y myapp
CMD ["myapp"]

# Good - use non-root user
FROM ubuntu:22.04
RUN useradd -m -u 1000 appuser
USER appuser
CMD ["myapp"]

DON'T: Layer Multiple Commands

# Bad - creates extra layers
RUN apt-get update
RUN apt-get install -y curl
RUN apt-get install -y vim
RUN apt-get clean

# Good - single RUN with && chains
RUN apt-get update && \
    apt-get install -y curl vim && \
    apt-get clean && \
    rm -rf /​var/​lib/​apt/​lists/​*

DON'T: Copy Everything

# Bad - includes unnecessary files
COPY . /​app

# Good - be selective
COPY requirements.txt .
RUN pip install -r requirements.txt
COPY src/ ./​src/
COPY config/ ./​config/

DON'T: Ignore Resource Limits

# Bad - no resource limits, can consume entire node
spec:
  containers:
  - name: app
    image: myapp

# Good - set requests and limits
spec:
  containers:
  - name: app
    image: myapp
    resources:
      requests:
        memory: "256Mi"
        cpu: "250m"
      limits:
        memory: "512Mi"
        cpu: "500m"

DON'T: Skip Health Checks

# Bad - no way to detect failing app
FROM mybase
COPY app /​app
CMD ["app"]

# Good - include health check
HEALTHCHECK --interval=30s --timeout=10s --retries=3 \
    CMD curl -f http://localhost:8000/​health || exit 1
CMD ["app"]

DON'T: Hardcode Configuration

# Bad - configuration baked into image
ENV DATABASE_URL=postgresql://prod-db:5432/​myapp
ENV API_KEY=sk_live_xxx

# Good - use environment variables and secrets
# Leave empty or use defaults for development
ENV DATABASE_URL=postgresql://localhost:5432/​myapp
# Use Kubernetes Secrets or docker-compose .env file

DON'T: Combine Multiple Applications

# Bad - violates single responsibility
FROM ubuntu
RUN apt-get install -y nginx python flask
COPY . /​app
CMD ["supervisord"]  # Running multiple services

# Good - one container per concern
FROM nginx:latest
COPY nginx.conf /​etc/​nginx/​nginx.conf
---
FROM python:3.11
COPY app.py /​app/
CMD ["python", "app.py"]

More DevOps & CI/CD skills

Project scaffolding, deployment configuration, and CI/CD setup for Google ADK agents.

6K 472.6K
View

Set up tracing, logging, and monitoring for deployed ADK agents across Cloud Trace, BigQuery, and third-party platforms.

6K 472.6K
View

Enterprise Azure infrastructure architect generating Bicep or Terraform from workload descriptions.

1.5K 454.3K
View
azure-kubernetes logo
DevOps & CI/CD

azure-kubernetes

Plan and configure production-ready Azure Kubernetes Service clusters with Day-0 and Day-1 best practices.

1.5K 447.1K
View

Raw mechanical interfaces fusing Swiss typographic print with military terminal aesthetics. Rigid grids, extreme type scale contrast, utilitarian color, analog degradation effects. For data-heavy dashboards, portfolios, or editorial sites that need to feel like declassified blueprints.

92.7K 354.9K
View
just-scrape logo
DevOps & CI/CD

just-scrape

Web search, scraping, extraction, crawling, and monitoring via ScrapeGraph AI CLI.

69 245K
View

Skill for working with Firebase Hosting (Classic). Use this when you want to deploy static web apps, Single Page Apps (SPAs), or simple microservices. Do NOT use for Firebase App Hosting.

462 159.7K
View

Deploy and manage web apps with Firebase App Hosting. Use this skill when deploying Next.js/Angular apps with backends.

462 159.1K
View
deploy-to-vercel logo
DevOps & CI/CD

deploy-to-vercel

Deploy applications and websites to Vercel. Use when the user requests deployment actions like "deploy my app", "deploy and give me the link", "push this live", or "create a preview deployment".

31.9K 146.6K
View
programmatic-seo logo
DevOps & CI/CD

programmatic-seo

Build SEO-optimized pages at scale using templates, data, and proven playbook patterns.

53.3K 140.1K
View

Design and build isolated, reusable Convex backend components with clear boundaries and app-facing wrappers.

63 123.5K
View

Deploy and manage projects on Vercel using token-based authentication. Use when working with Vercel CLI using access tokens rather than interactive login — e.g. "deploy to vercel", "set up vercel", "add environment variables to vercel".

31.9K 116.1K
View

Coding & apps AI tools

Opus Clip logo
Coding & apps

Opus Clip

Opus.ai: Revolutionize Your Web Experience

Free
View
I
Coding & apps

Imagica

Build a no-code AI app in minutes.

Freemium
View
E
Coding & apps

Emergent.sh

An IDE for code migration from legacy to modern frameworks through coding agents.

Freemium
View
Wonder Dynamics logo
Coding & apps

Wonder Dynamics

Automate CGI animation in live-action scenes

Paid
View
M
Coding & apps

Mixo

Launch a website in seconds with AI.

Paid
View
AI Code Convert logo
Coding & apps

AI Code Convert

Streamline Your Coding Experience with AI Code Helper

Free
View