惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

F
Fortinet All Blogs
爱范儿
爱范儿
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
B
Blog
WordPress大学
WordPress大学
Jina AI
Jina AI
GbyAI
GbyAI
aimingoo的专栏
aimingoo的专栏
N
Netflix TechBlog - Medium
腾讯CDC
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
阮一峰的网络日志
阮一峰的网络日志
The GitHub Blog
The GitHub Blog
V
Visual Studio Blog
Google DeepMind News
Google DeepMind News
月光博客
月光博客
博客园 - Franky
Y
Y Combinator Blog
MyScale Blog
MyScale Blog
大猫的无限游戏
大猫的无限游戏
Martin Fowler
Martin Fowler
雷峰网
雷峰网
小众软件
小众软件
H
Hackread – Cybersecurity News, Data Breaches, AI and More

DEV Community

Authentication Security Deep Dive: From Brute Force to Salted Hashing (With Java Examples) Why AI Systems Don’t Fail — They Drift Spilling beans for how i learn for exam😁"Reinforcement Learning Cheat Sheet" I Replaced Chrome with Safari for AI Browser Automation. Here's What Broke (and What Finally Worked) How Python Borrows Other People's Work The $40 Architecture: Processing 1 Billion API Requests with 99.99% Uptime Vibe Coding: A Workflow Guide (From Zero to SaaS) Most webhook security guides protect the wrong side. The scary part is delivery. Headless CMS for TanStack Start: Build a Blog with Cosmic EU Age Verification App "Hacked in 2 Minutes" — What Actually Happened Comfy Cloud’s delete function does not actually remove files Running AI Models on GPU Cloud Servers: A Beginner Guide Event-driven media intelligence with AWS Step Functions and Bedrock I scored 500 AI prompts across 8 quality dimensions — here's what broke How to Call Google Gemini API from Next.js (Free Tier, No Backend Needed) The Portal Protocol: Reclaiming Human Connection in the Age of AI How to Fix Your Team's Scattered Knowledge Problem With a Self-Hosted Forum Intro to tc Cloud Functors: A Graph-First Mental Model for the Modern Cloud Designing Multi-Tenant Backends With Both Ownership and Team Access I Built a Neumorphic CSS Library with 77+ Components — Here's What I Learned PostgreSQL Performance Optimization: Why Connection Pooling Is Critical at Scale Cómo construí un SaaS multi-rubro para gestionar expensas en Argentina con FastAPI + Vue 3 🚀 I Built an Ethical Hacking Scanner Tool – Open Source Project I Replaced /usage and /context in Claude Code With a Single Statusline A Pythonic Way to Handle Emails (IMAP/SMTP) with Auto-Discovery and AI-Ready Design I Collected 8.9 Million Polymarket Price Points — Here's What I Found About How Markets Really Move EcoTrack AI — Carbon Footprint Tracker & Dashboard Everyone's Using AI. No One Agrees How. 5 self-hosted ebook managers worth trying in 2026 Building Your First AI Agent with LangChain: From Chatbot to Autonomous Assistant
Docker Deep Dive: Beyond docker run (2026)
Alex Chen · 2026-05-27 · via DEV Community

Alex Chen

Docker Deep Dive: Beyond docker run (2026)

You know docker run -p 3000:3000. Here's everything else that makes Docker powerful in production.

Dockerfile Best Practices

# ❌ BAD: Bloated image, slow builds, security risks
FROM node:20

RUN apt-get update && apt-get install -y vim curl git
WORKDIR /app
COPY . .
RUN npm install
CMD ["node", "server.js"]

# ✅ GOOD: Optimized for size, speed, and security
FROM node:20-alpine AS base

# Build stage — install deps only (layer caching!)
FROM base AS deps
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm ci --only=production && npm cache clean --force

# Production stage — minimal final image
FROM base AS production
WORKDIR /app

# Create non-root user (security best practice)
RUN addgroup --system --gid 1001 appgroup && \
    adduser --system --uid 1001 appuser

# Copy from build stage
COPY --from=deps /app/node_modules ./node_modules
COPY . .

# Set ownership
RUN chown -R appuser:appgroup /app
USER appuser

EXPOSE 3000

# Health check (Docker can monitor your app!)
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
  CMD wget --no-verbose --tries=1 --spider http://localhost:3000/health || exit 1

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

Enter fullscreen mode Exit fullscreen mode

Key Dockerfile Rules

1. Layer caching is your friend
   → COPY package.json FIRST (before source code)
   → npm install runs only when package.json changes
   → Source code changes don't trigger reinstall!

2. Use .dockerignore (like .gitignore for Docker)
   node_modules          # Rebuild fresh each time
   .git                  # Don't copy repo history
   .env                  # Secrets!
   *.md                  # Documentation not needed at runtime
   .DS_Store             # macOS junk
   coverage/             # Test output
   dist/                 # If you're building inside Docker

3. Alpine images are tiny (~8MB vs ~180MB for full Node)
   Trade-off: Some tools missing (glibc compatibility issues)
   For most Node apps: alpine works perfectly fine

4. Multi-stage builds = smaller production images
   Build stage has all dev tools
   Production stage only gets what's needed
   Result: Image goes from 500MB+ to ~80MB

5. Never run as root
   USER appuser after setup
   Prevents container escape attacks
   Required by many Kubernetes clusters anyway

Enter fullscreen mode Exit fullscreen mode

Docker Compose for Local Development

# docker-compose.yml
version: '3.9'

services:
  app:
    build:
      context: .
      target: development       # Use a different stage for dev
    ports:
      - "3000:3000"
      - "9229:9229"            # Node debugger port
    environment:
      - NODE_ENV=development
      - DATABASE_URL=postgres://dev:dev@db:5432/myapp
      - REDIS_URL=redis://redis:6379
    volumes:
      - .:/app                  # Live reload! Code changes reflect immediately
      - /app/node_modules       # Prevent host node_modules overwriting container's
    depends_on:
      db:
        condition: service_healthy
      redis:
        condition: service_healthy
    restart: unless-stopped     # Auto-restart on crash
    networks:
      - backend

  db:
    image: postgres:16-alpine
    environment:
      POSTGRES_USER: dev
      POSTGRES_PASSWORD: dev
      POSTGRES_DB: myapp
    volumes:
      - pgdata:/var/lib/postgresql/data
    ports:
      - "5432:5432"
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U dev"]
      interval: 5s
      timeout: 3s
      retries: 5
    networks:
      - backend

  redis:
    image: redis:7-alpine
    command: redis-server --appendonly yes
    volumes:
      - redisdata:/data
    ports:
      - "6379:6379"
    healthcheck:
      test: ["CMD", "redis-cli", "ping"]
      interval: 5s
      timeout: 3s
      retries: 5
    networks:
      - backend

volumes:
  pgdata:                       # Named volume (persists across containers)
  redisdata:

networks:
  backend:
    driver: bridge              # Isolated network for services

Enter fullscreen mode Exit fullscreen mode

Essential Compose Commands

# Start everything
docker compose up -d            # Detached mode (background)
docker compose up               # Foreground (see logs live)

# Development workflow
docker compose up --build       # Rebuild before starting
docker compose logs -f app      # Follow logs for one service
docker compose logs -f --tail=50  # Last 50 lines, then follow
docker compose exec app sh      # Shell into running container
docker compose exec app npm run migrate  # Run commands inside container

# Debugging
docker compose ps               # Show all services status
docker compose top              # Show processes in each container
docker compose stats            # Resource usage (CPU, memory, network)

# Cleanup
docker compose down             # Stop and remove containers + networks
docker compose down -v          # Also remove volumes (resets data!)
docker compose down --rmi all   # Also remove images (full reset)

# One-off tasks
docker compose run --rm app npm run test         # Run tests then exit
docker compose run --rm db psql -U dev -d myapp   # Connect to DB directly

Enter fullscreen mode Exit fullscreen mode

Docker Networks Explained

# Default networks:
# bridge   → Default, containers on same host can communicate
# host     → Container uses host's network stack (no isolation)
# none     → No networking (rarely used)

# Custom networks (recommended):
docker network create myapp-net
docker run --network myapp-net ...

# DNS resolution works automatically!
# Container names become hostnames:
# app container can reach db via: postgres://db:5432/myapp

# Network types:
bridge     # Most common, isolated per network
host       # Direct host access (good for performance monitoring)
overlay    # Multi-host (Docker Swarm/Kubernetes)
macvlan    # Container gets its own MAC address (appears as physical device)
ipvlan     # Like macvlan but shares host MAC

Enter fullscreen mode Exit fullscreen mode

Volumes vs Bind Mounts

# Bind mount: Host path → Container path
# Good for: Development (live code sync), config files
docker run -v $(pwd)/src:/app/src nginx

# Named volume: Managed by Docker, stored in /var/lib/docker/volumes/
# Good for: Data persistence, databases, caches
docker run -v mydata:/data/app nginx

# Read-only bind mount (security!)
docker run -v $(pwd)/config:/etc/app/config:ro nginx

# tmpfs: In-memory only (gone when container stops)
# Good for: Temporary files, secrets, sensitive processing
docker run --tmpfs /tmp:rw,noexec,nosuid,size=100m nginx

# Volume lifecycle:
docker volume create mydata           # Create
docker volume inspect mydata          # See details (where it lives)
docker volume ls                      # List all
docker volume prune                   # Remove unused volumes (frees disk space!)

Enter fullscreen mode Exit fullscreen mode

Useful Docker Commands You Might Not Know

# Container management
docker ps -a                          # All containers (including stopped)
docker stats                          # Real-time resource usage (like top)
docker top <container>                # Processes inside container
docker update --memory=512m <container>  # Update resource limits live!
docker rename old-name new-name       # Rename a container

# Inspecting
docker inspect <container> | jq '.[0].NetworkSettings.IPAddress'  # Get IP
docker inspect <container> --format='{{.State.Status}}'            # Quick status
docker logs <container> --since 1h         # Logs from last hour
docker logs <container> --tail 100 -f      # Tail last 100 lines

# Copying files
docker cp file.txt container:/path/inside/   # Host → Container
docker cp container:/path/file.txt ./local/  # Container → Host

# Cleaning up (run regularly!)
docker system prune                    # Remove stopped containers, unused networks, dangling images
docker system prune -a                 # ALSO remove unused images (not just dangling)
docker volume prune                    # Remove unused volumes
docker builder prune                   # Remove build cache (can be GBs!)

# Image management
docker images --format "table {{.Repository}}\t{{.Tag}}\t{{.Size}}"  # Pretty table
docker history <image>                 # See each layer and its size
docker save myimage | gzip > image.tar.gz  # Export image for transfer
docker load < image.tar.gz             # Import exported image

# Debugging a failing container
docker run --rm -it --entrypoint sh myimage  # Override entrypoint to get shell
docker commit <container> myimage:debug      # Save container state as new image

Enter fullscreen mode Exit fullscreen mode

Docker in CI/CD

# GitHub Actions example
name: Build & Push Docker Image
on:
  push:
    branches: [main]

jobs:
  docker:
    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.DOCKERHUB_USERNAME }}
          password: ${{ secrets.DOCKERHUB_TOKEN }}

      - name: Build and push
        uses: docker/build-push-action@v5
        with:
          context: .
          push: true
          tags: |
            ${{ secrets.DOCKERHUB_USERNAME }}/myapp:${{ github.sha }}
            ${{ secrets.DOCKERHUB_USERNAME }}/myapp:latest
          cache-from: type=gha              # GitHub Actions cache
          cache-to: type=gha,mode=max        # Speed up future builds
          platforms: linux/amd64,linux/arm64 # Multi-architecture support!

Enter fullscreen mode Exit fullscreen mode

Common Docker Problems & Solutions

# Problem: Container exits immediately
# Solution: Check the process! Containers die when their main process exits.
docker logs <container>                     # Always first step
# Fix: Make sure your CMD/ENTRYPOINT runs a long-running process

# Problem: Permission denied errors
# Solution: UID mismatch between host and container
# In Dockerfile: RUN adduser --uid 1001 appuser; USER appuser
# Or: docker run -u $(id -u):$(id -g) ...

# Problem: Disk space full
# Solution: Regular cleanup
docker system df                           # See what's using space
docker system prune -a --volumes           # Nuclear option (frees most space)

# Problem: Networking issues (can't reach other containers)
# Solution: Check they're on the same network
docker network inspect <network-name>
# Ensure both services use the same network in compose

# Problem: Stale layers making rebuilds slow
# Solution: Clear build cache
docker builder prune
# Then rebuild with --no-cache once

# Problem: Timezone wrong inside container
# Solution: Pass TZ environment variable
docker run -e TZ=Asia/Shanghai ...
# Or in Dockerfile: ENV TZ=Asia/Shanghai

Enter fullscreen mode Exit fullscreen mode


What's your favorite Docker tip?

Follow @armorbreak for more practical developer guides.