关于 docker
面向开发者的 Docker 容器化指南,适用于本地开发、CI/CD 和部署场景。通过示例介绍镜像构建、多容器配置、安全措施、故障排查与生产实践。
主要功能
- 01Dockerfile 与镜像构建基础
- 02使用 Compose 配置多容器
- 03多阶段镜像构建
- 04容器安全与资源限制
- 05容器故障排查技巧
适用场景
- 01创建一致的本地开发环境
- 02构建可复现的 CI/CD 工作流
- 03打包服务以便部署
- 04运行临时数据库进行集成测试
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ bobmatnyc/ claude-mpm-skills --skill docker安装后在 Claude Code 中输入/docker确认已加载。
附带文件metadata.json
详细介绍
Docker 容器化技能
概要
Docker 提供容器化功能,可将应用及其依赖打包成隔离、可移植的单元。容器可确保开发、测试和生产环境之间的一致性,消除“在我的机器上能运行”的问题。
适用场景
- 本地开发:确保团队成员使用一致的开发环境
- CI/CD 流水线:可复现的构建和测试环境
- 微服务:可独立扩展的隔离服务
- 生产部署:可在不同云服务商之间移植的应用
- 数据库/服务测试:用于集成测试的临时数据库
- 旧版应用隔离:并行运行彼此不兼容的依赖
快速开始
1. 创建 Dockerfile
FROM node:18-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY . .
EXPOSE 3000
CMD ["node", "server.js"]
2. 构建镜像
docker build -t myapp:1.0 .
3. 运行容器
docker run -p 3000:3000 myapp:1.0
核心概念
镜像与容器
- 镜像:包含应用代码、运行时和依赖的只读模板
- 容器:镜像的运行实例,带有可写层
- 镜像仓库:镜像的存储位置(Docker Hub、GitHub Container Registry)
层与缓存
Dockerfile 中的每条指令都会创建一个层。Docker 会缓存未更改的层,从而加快构建速度。
# GOOD: Dependencies change less frequently than code
FROM python:3.11-slim
COPY requirements.txt .
RUN pip install -r requirements.txt # Cached unless requirements.txt changes
COPY . . # Rebuild only when code changes
# BAD: Invalidates cache on every code change
FROM python:3.11-slim
COPY . . # Changes frequently
RUN pip install -r requirements.txt # Reinstalls on every build
卷
容器重启后仍保留的持久化数据存储。
# Named volume (managed by Docker)
docker run -v mydata:/app/data myapp
# Bind mount (host directory)
docker run -v $(pwd)/data:/app/data myapp
# Anonymous volume (temporary)
docker run -v /app/data myapp
网络
容器通过 Docker 网络进行通信。
# Create network
docker network create mynetwork
# Run containers on network
docker run --network mynetwork --name db postgres
docker run --network mynetwork --name app myapp
# App can connect to db using hostname "db"
Dockerfile 基础
必要指令
# Base image
FROM node:18-alpine
# Metadata
LABEL maintainer="[email protected]"
LABEL version="1.0"
# Set working directory
WORKDIR /app
# Copy files
COPY package*.json ./
COPY src/ ./src/
# Run commands (creates layer)
RUN npm ci --only=production
# Set environment variables
ENV NODE_ENV=production
ENV PORT=3000
# Expose ports (documentation only)
EXPOSE 3000
# Default command
CMD ["node", "src/server.js"]
# Alternative: ENTRYPOINT (not overridden by docker run args)
ENTRYPOINT ["node"]
CMD ["src/server.js"] # Default args for ENTRYPOINT
提升缓存效率的指令顺序
# 1. Base image (rarely changes)
FROM python:3.11-slim
# 2. System dependencies (rarely change)
RUN apt-get update && apt-get install -y \
gcc \
&& rm -rf /var/lib/apt/lists/*
# 3. Application dependencies (change occasionally)
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
# 4. Application code (changes frequently)
COPY . .
# 5. Runtime configuration
ENV PYTHONUNBUFFERED=1
EXPOSE 8000
CMD ["python", "manage.py", "runserver", "0.0.0.0:8000"]
.dockerignore
从构建上下文中排除文件(加快构建速度,减小镜像体积)。
# .dockerignore
node_modules/
npm-debug.log
.git/
.gitignore
*.md
.env
.vscode/
__pycache__/
*.pyc
.pytest_cache/
coverage/
dist/
build/
多阶段构建
将构建阶段与运行阶段分开,以优化镜像体积。
Node.js TypeScript 示例
# Build stage
FROM node:18-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
# Production stage
FROM node:18-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY --from=builder /app/dist ./dist
EXPOSE 3000
CMD ["node", "dist/server.js"]
优势:
- 构建依赖(TypeScript、webpack)不会包含在最终镜像中
- 最终镜像约为 50MB,而包含构建工具时约为 500MB
- 部署更快,攻击面更小
Python 示例
# Build stage
FROM python:3.11 AS builder
WORKDIR /app
COPY requirements.txt .
RUN pip install --user --no-cache-dir -r requirements.txt
# Runtime stage
FROM python:3.11-slim
WORKDIR /app
COPY --from=builder /root/.local /root/.local
COPY . .
ENV PATH=/root/.local/bin:$PATH
CMD ["python", "app.py"]
Go 示例(最小镜像)
# Build stage
FROM golang:1.21-alpine AS builder
WORKDIR /app
COPY go.* ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 GOOS=linux go build -o server
# Runtime stage (scratch = empty base image)
FROM scratch
COPY --from=builder /app/server /server
EXPOSE 8080
ENTRYPOINT ["/server"]
结果:最终镜像约为 10MB,仅包含编译后的二进制文件。
Docker Compose
使用 YAML 定义多容器应用。
基本结构
version: '3.8'
services:
app:
build: .
ports:
- "3000:3000"
environment:
- DATABASE_URL=postgres://db:5432/myapp
depends_on:
- db
volumes:
- ./src:/app/src # Hot reload in development
db:
image: postgres:15-alpine
environment:
POSTGRES_PASSWORD: secret
POSTGRES_DB: myapp
volumes:
- db_data:/var/lib/postgresql/data
ports:
- "5432:5432"
volumes:
db_data:
命令
# Start all services
docker-compose up
# Start in background
docker-compose up -d
# Rebuild images
docker-compose up --build
# Stop services
docker-compose down
# Stop and remove volumes
docker-compose down -v
# View logs
docker-compose logs -f app
# Run one-off command
docker-compose run app npm test
完整技术栈示例
version: '3.8'
services:
# Frontend
web:
build:
context: ./frontend
dockerfile: Dockerfile.dev
ports:
- "3000:3000"
volumes:
- ./frontend/src:/app/src
environment:
- REACT_APP_API_URL=http://localhost:8000
# Backend API
api:
build: ./backend
ports:
- "8000:8000"
environment:
- DATABASE_URL=postgresql://postgres:secret@db:5432/myapp
- REDIS_URL=redis://redis:6379
depends_on:
db:
condition: service_healthy
redis:
condition: service_started
volumes:
- ./backend:/app
command: uvicorn main:app --host 0.0.0.0 --reload
# Database
db:
image: postgres:15-alpine
environment:
POSTGRES_PASSWORD: secret
POSTGRES_DB: myapp
volumes:
- db_data:/var/lib/postgresql/data
- ./init.sql:/docker-entrypoint-initdb.d/init.sql
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres"]
interval: 10s
timeout: 5s
retries: 5
# Cache
redis:
image: redis:7-alpine
ports:
- "6379:6379"
volumes:
- redis_data:/data
# Worker (background jobs)
worker:
build: ./backend
command: celery -A tasks worker --loglevel=info
environment:
- REDIS_URL=redis://redis:6379
depends_on:
- redis
- db
volumes:
db_data:
redis_data:
networks:
default:
name: myapp_network
开发工作流
使用卷实现热重载
Node.js
services:
app:
build: .
volumes:
- ./src:/app/src # Sync source code
- /app/node_modules # Prevent overwriting container's node_modules
command: npm run dev
# Dockerfile.dev
FROM node:18-alpine
WORKDIR /app
COPY package*.json ./
RUN npm install # Include dev dependencies
COPY . .
EXPOSE 3000
CMD ["npm", "run", "dev"]
Python(Django/FastAPI)
services:
web:
build: .
volumes:
- .:/app
command: python manage.py runserver 0.0.0.0:8000
# or for FastAPI:
# command: uvicorn main:app --host 0.0.0.0 --reload
VS Code Dev Containers
.devcontainer/devcontainer.json:
{
"name": "Python Dev Container",
"dockerComposeFile": "../docker-compose.yml",
"service": "app",
"workspaceFolder": "/app",
"customizations": {
"vscode": {
"extensions": [
"ms-python.python",
"ms-python.vscode-pylance"
],
"settings": {
"python.defaultInterpreterPath": "/usr/local/bin/python"
}
}
},
"postCreateCommand": "pip install -r requirements-dev.txt",
"remoteUser": "vscode"
}
本地数据库容器
# PostgreSQL
docker run -d \
--name dev-postgres \
-e POSTGRES_PASSWORD=localdev \
-e POSTGRES_DB=myapp_dev \
-p 5432:5432 \
-v pgdata:/var/lib/postgresql/data \
postgres:15-alpine
# MySQL
docker run -d \
--name dev-mysql \
-e MYSQL_ROOT_PASSWORD=localdev \
-e MYSQL_DATABASE=myapp_dev \
-p 3306:3306 \
-v mysqldata:/var/lib/mysql \
mysql:8
# MongoDB
docker run -d \
--name dev-mongo \
-p 27017:27017 \
-v mongodata:/data/db \
mongo:7
# Redis
docker run -d \
--name dev-redis \
-p 6379:6379 \
redis:7-alpine
生产环境模式
健康检查
FROM node:18-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY . .
# Health check endpoint
HEALTHCHECK --interval=30s --timeout=5s --start-period=10s --retries=3 \
CMD node healthcheck.js
EXPOSE 3000
CMD ["node", "server.js"]
// healthcheck.js
const http = require('http');
const options = {
host: 'localhost',
port: 3000,
path: '/health',
timeout: 2000
};
const request = http.request(options, (res) => {
if (res.statusCode === 200) {
process.exit(0);
} else {
process.exit(1);
}
});
request.on('error', () => process.exit(1));
request.end();
安全最佳实践
FROM python:3.11-slim
# 1. Use non-root user
RUN groupadd -r appuser && useradd -r -g appuser appuser
# 2. Install dependencies as root
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
# 3. Copy application files
COPY --chown=appuser:appuser . .
# 4. Switch to non-root user
USER appuser
# 5. Drop unnecessary privileges
EXPOSE 8000
CMD ["gunicorn", "--bind", "0.0.0.0:8000", "app:app"]
其他安全措施:
- 使用最小化基础镜像(alpine、distroless)
- 扫描镜像中的漏洞:
docker scan myapp:latest - 不要在镜像中包含机密信息(使用环境变量或机密管理器)
- 保持基础镜像为最新版本
- 尽可能使用只读根文件系统
机密信息管理
# Docker Swarm secrets (production)
echo "db_password_here" | docker secret create db_password -
version: '3.8'
services:
app:
image: myapp
secrets:
- db_password
environment:
- DB_PASSWORD_FILE=/run/secrets/db_password
secrets:
db_password:
external: true
替代方案:环境文件
# docker-compose.yml
services:
app:
env_file:
- .env.production # Never commit this file
# .env.production (gitignored)
DATABASE_URL=postgresql://user:pass@db:5432/prod
SECRET_KEY=your-secret-key
资源限制
services:
app:
image: myapp
deploy:
resources:
limits:
cpus: '1.0'
memory: 512M
reservations:
cpus: '0.5'
memory: 256M
restart_policy:
condition: on-failure
delay: 5s
max_attempts: 3
# Command-line resource limits
docker run -d \
--memory="512m" \
--cpus="1.0" \
--restart=unless-stopped \
myapp
特定框架示例
Python:Django
FROM python:3.11-slim
ENV PYTHONUNBUFFERED=1
ENV PYTHONDONTWRITEBYTECODE=1
WORKDIR /app
# Install system dependencies
RUN apt-get update && apt-get install -y \
postgresql-client \
&& rm -rf /var/lib/apt/lists/*
# Install Python dependencies
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
# Copy application
COPY . .
# Collect static files
RUN python manage.py collectstatic --noinput
# Create non-root user
RUN useradd -m -u 1000 django && chown -R django:django /app
USER django
EXPOSE 8000
CMD ["gunicorn", "--bind", "0.0.0.0:8000", "--workers", "4", "myproject.wsgi:application"]
docker-compose.yml:
version: '3.8'
services:
web:
build: .
command: python manage.py runserver 0.0.0.0:8000
volumes:
- .:/app
ports:
- "8000:8000"
environment:
- DEBUG=1
- DATABASE_URL=postgres://postgres:postgres@db:5432/django_dev
depends_on:
- db
db:
image: postgres:15-alpine
environment:
POSTGRES_PASSWORD: postgres
POSTGRES_DB: django_dev
volumes:
- postgres_data:/var/lib/postgresql/data
volumes:
postgres_data:
Python:FastAPI
FROM python:3.11-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
EXPOSE 8000
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000", "--workers", "4"]
Node.js:Next.js
# Multi-stage build for Next.js
FROM node:18-alpine AS deps
WORKDIR /app
COPY package*.json ./
RUN npm ci
FROM node:18-alpine AS builder
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY . .
RUN npm run build
FROM node:18-alpine AS runner
WORKDIR /app
ENV NODE_ENV=production
RUN addgroup -g 1001 -S nodejs
RUN adduser -S nextjs -u 1001
COPY --from=builder /app/public ./public
COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static
USER nextjs
EXPOSE 3000
CMD ["node", "server.js"]
next.config.js(独立输出所必需):
module.exports = {
output: 'standalone',
}
Node.js:Express
FROM node:18-alpine
WORKDIR /app
# Install dependencies
COPY package*.json ./
RUN npm ci --only=production
# Copy application
COPY . .
# Create non-root user
RUN addgroup -S appgroup && adduser -S appuser -G appgroup
USER appuser
EXPOSE 3000
CMD ["node", "server.js"]
TypeScript 构建
# Build stage
FROM node:18-alpine AS builder
WORKDIR /app
COPY package*.json tsconfig.json ./
RUN npm ci
COPY src/ ./src/
RUN npm run build
# Production stage
FROM node:18-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY --from=builder /app/dist ./dist
EXPOSE 3000
CMD ["node", "dist/index.js"]
容器编排基础
Docker Swarm(内置)
# Initialize swarm
docker swarm init
# Deploy stack
docker stack deploy -c docker-compose.yml myapp
# Scale service
docker service scale myapp_web=5
# Update service (zero-downtime)
docker service update --image myapp:2.0 myapp_web
# Remove stack
docker stack rm myapp
Kubernetes 对比
| 特性 | Docker Compose | Docker Swarm | Kubernetes |
|---|---|---|---|
| 复杂度 | 低 | 中 | 高 |
| 使用场景 | 本地开发 | 小型集群 | 大规模生产环境 |
| 设置 | 单个文件 | 内置 | 单独安装 |
| 扩展 | 手动 | 自动 | 自动 + 高级功能 |
| 高可用性 | 否 | 是 | 是 |
| 生态系统 | 有限 | Docker | 庞大 |
何时使用:
- Docker Compose:本地开发、简单部署
- Docker Swarm:小型生产集群,比 K8s 更简单
- Kubernetes:大规模生产环境、多云、复杂编排
CI/CD 集成
GitHub Actions
# .github/workflows/docker.yml
name: Build and Push Docker Image
on:
push:
branches: [main]
pull_request:
branches: [main]
env:
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}
jobs:
build:
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
steps:
- uses: actions/checkout@v3
- name: Log in to Container Registry
uses: docker/login-action@v2
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Extract metadata
id: meta
uses: docker/metadata-action@v4
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
tags: |
type=ref,event=branch
type=semver,pattern={{version}}
type=sha
- name: Build and push
uses: docker/build-push-action@v4
with:
context: .
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=gha
cache-to: type=gha,mode=max
- name: Run tests
run: |
docker run --rm ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ github.sha }} npm test
GitLab CI
# .gitlab-ci.yml
stages:
- build
- test
- deploy
variables:
DOCKER_DRIVER: overlay2
IMAGE_TAG: $CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA
build:
stage: build
image: docker:latest
services:
- docker:dind
script:
- docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
- docker build -t $IMAGE_TAG .
- docker push $IMAGE_TAG
test:
stage: test
script:
- docker run --rm $IMAGE_TAG npm test
deploy:
stage: deploy
script:
- docker pull $IMAGE_TAG
- docker tag $IMAGE_TAG $CI_REGISTRY_IMAGE:latest
- docker push $CI_REGISTRY_IMAGE:latest
only:
- main
调试容器
查看日志
# Stream logs
docker logs -f container_name
# Last 100 lines
docker logs --tail 100 container_name
# Logs since timestamp
docker logs --since 2024-01-01T10:00:00 container_name
# With timestamps
docker logs -t container_name
# Docker Compose logs
docker-compose logs -f service_name
在运行中的容器内执行命令
# Interactive shell
docker exec -it container_name /bin/sh
# or
docker exec -it container_name /bin/bash
# Run single command
docker exec container_name ls -la /app
# Run as different user
docker exec -u root container_name apt-get update
检查容器
# Full container details
docker inspect container_name
# Specific field (IP address)
docker inspect -f '{{.NetworkSettings.IPAddress}}' container_name
# Environment variables
docker inspect -f '{{.Config.Env}}' container_name
# Mounted volumes
docker inspect -f '{{.Mounts}}' container_name
资源使用情况
# Real-time stats
docker stats
# Single container
docker stats container_name
# No streaming (single snapshot)
docker stats --no-stream
网络调试
# List networks
docker network ls
# Inspect network
docker network inspect bridge
# Test connectivity between containers
docker exec container1 ping container2
# Check DNS resolution
docker exec container_name nslookup other_container
调试构建问题
# Build with no cache
docker build --no-cache -t myapp .
# Show build progress
docker build --progress=plain -t myapp .
# Build specific stage
docker build --target builder -t myapp-builder .
# Inspect intermediate layers
docker history myapp:latest
本地 Docker 模式(mcp-browser、mcp-memory)
mcp-browser 开发环境 compose
docker-compose.yml使用端口范围8875-8895运行mcp-server,并提供可选的chrome配置文件。- 代码以只读方式挂载(
./src:/app/src:ro),并使用持久化日志和临时卷。 - 环境变量默认值:
MCP_DEBUG=true、MCP_LOG_LEVEL=DEBUG、MCP_HOST=0.0.0.0、MCP_PORT=8875。 - 可选配置文件:
chrome(浏览器)和tools(开发工具容器)。
mcp-browser Dockerfile.dev
ARG PYTHON_VERSION=3.11,安装watchdog和 Playwright Chromium。- 以可编辑模式安装软件包,并运行
python -m src.dev_runner。 - 使用非 root 用户,并对
/health执行健康检查。
mcp-memory 生产环境 Dockerfile
- 多阶段构建,在
/opt/venv中创建虚拟环境,并使用python:3.11-slim。 - 运行时安装
curl用于健康检查,并设置PYTHONPATH=/app。 - 使用非 root 用户,通过
CMD ["python", "run_api_server.py"]启动,并检查/health。
故障排除
常见问题
“端口已被占用”
# Find process using port
lsof -i :3000
# or
netstat -tulpn | grep 3000
# Kill process
kill -9 <PID>
# Or use different host port
docker run -p 3001:3000 myapp
“无法连接到 Docker 守护进程”
# Check Docker is running
docker info
# Restart Docker Desktop (Mac/Windows)
# or
sudo systemctl restart docker # Linux
# Check permissions (Linux)
sudo usermod -aG docker $USER
# Log out and back in
“设备上没有剩余空间”
# Remove unused containers, images, volumes
docker system prune -a --volumes
# Remove only dangling images
docker image prune
# Remove stopped containers
docker container prune
# Remove unused volumes
docker volume prune
# Check disk usage
docker system df
“构建上下文过大”
# Create .dockerignore
cat > .dockerignore << EOF
node_modules/
.git/
*.log
dist/
coverage/
EOF
# Build with specific context
docker build -f Dockerfile -t myapp ./src
容器立即退出
# Check logs
docker logs container_name
# Run with interactive shell to debug
docker run -it myapp /bin/sh
# Override entrypoint
docker run -it --entrypoint /bin/sh myapp
# Check exit code
docker inspect -f '{{.State.ExitCode}}' container_name
容器内权限被拒绝
# Run as root to debug
docker exec -u root -it container_name /bin/sh
# Fix ownership
docker exec -u root container_name chown -R appuser:appuser /app
# Or rebuild with correct permissions in Dockerfile
性能问题
构建缓慢
# Use BuildKit (faster, better caching)
DOCKER_BUILDKIT=1 docker build -t myapp .
# Multi-stage builds to reduce layers
# Order instructions by change frequency
# Use .dockerignore to exclude unnecessary files
内存使用量过高
# Set memory limits
docker run -m 512m myapp
# Monitor memory
docker stats container_name
# Check for memory leaks in application
卷挂载缓慢(Mac/Windows)
# Use delegated consistency (Mac)
volumes:
- ./src:/app/src:delegated
# Or use named volumes instead of bind mounts
volumes:
- node_modules:/app/node_modules
最佳实践
优化层
- 按更改频率排序:最不常更改的内容放在前面
- 合并 RUN 命令:减少层数
- 在同一层中清理:立即删除临时文件
# GOOD
RUN apt-get update && apt-get install -y \
package1 \
package2 \
&& rm -rf /var/lib/apt/lists/*
# BAD (creates 3 layers, apt cache remains in layer 2)
RUN apt-get update
RUN apt-get install -y package1 package2
RUN rm -rf /var/lib/apt/lists/*
减小镜像体积
- 使用 Alpine 镜像:5MB,而完整 Linux 镜像为 100MB+
- 多阶段构建:从最终镜像中排除构建工具
- 删除不必要的文件:文档、示例、测试
- 使用 .dockerignore:排除开发文件
# Before: 800MB
FROM node:18
COPY . .
RUN npm install
CMD ["node", "server.js"]
# After: 120MB
FROM node:18-alpine
COPY package*.json ./
RUN npm ci --only=production
COPY server.js .
CMD ["node", "server.js"]
安全检查清单
- 使用可信来源提供的官方基础镜像
- 指定准确的镜像版本(而不是
latest) - 以非 root 用户运行
- 扫描镜像以查找漏洞
- 保持基础镜像更新
- 不要将机密嵌入镜像
- 尽可能使用只读根文件系统
- 尽量缩小攻击面(alpine、distroless)
- 启用 Docker Content Trust(镜像签名)
开发环境与生产环境
开发环境:
FROM node:18
WORKDIR /app
COPY package*.json ./
RUN npm install # Include dev dependencies
COPY . .
CMD ["npm", "run", "dev"]
生产环境:
FROM node:18-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
FROM node:18-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY --from=builder /app/dist ./dist
USER node
CMD ["node", "dist/server.js"]
日志记录最佳实践
# Log to stdout/stderr (Docker captures these)
CMD ["node", "server.js"] # Good
# Don't log to files (lost when container stops)
CMD ["node", "server.js", ">", "app.log"] # Bad
// Application logging
console.log('Info message'); // stdout
console.error('Error message'); // stderr
// Use structured logging
console.log(JSON.stringify({
level: 'info',
timestamp: new Date().toISOString(),
message: 'Request processed',
requestId: '123'
}));
环境配置
# Use ARG for build-time variables
ARG NODE_ENV=production
ENV NODE_ENV=$NODE_ENV
# Use ENV for runtime variables
ENV PORT=3000
ENV LOG_LEVEL=info
# Override at runtime
# docker run -e PORT=8080 -e LOG_LEVEL=debug myapp
健康检查
HEALTHCHECK --interval=30s --timeout=3s --start-period=40s --retries=3 \
CMD curl -f http://localhost:3000/health || exit 1
# docker-compose.yml
services:
app:
image: myapp
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:3000/health"]
interval: 30s
timeout: 3s
retries: 3
start_period: 40s
优雅关闭
// Node.js example
process.on('SIGTERM', () => {
console.log('SIGTERM received, closing server...');
server.close(() => {
console.log('Server closed');
process.exit(0);
});
});
# Use exec form to properly handle signals
CMD ["node", "server.js"] # Good
CMD node server.js # Bad (wrapped in /bin/sh, signals not forwarded)
快速参考
基本命令
# Images
docker build -t name:tag .
docker pull image:tag
docker push image:tag
docker images
docker rmi image:tag
# Containers
docker run -d --name container image
docker ps # Running containers
docker ps -a # All containers
docker stop container
docker start container
docker restart container
docker rm container
docker logs -f container
docker exec -it container /bin/sh
# Cleanup
docker system prune -a # Remove all unused resources
docker container prune # Remove stopped containers
docker image prune # Remove dangling images
docker volume prune # Remove unused volumes
# Compose
docker-compose up -d
docker-compose down
docker-compose logs -f
docker-compose exec service /bin/sh
docker-compose build
常用标志
# docker run flags
-d # Detached (background)
-it # Interactive with TTY
-p 8080:80 # Port mapping (host:container)
--name myapp # Container name
-e VAR=value # Environment variable
-v /host:/container # Volume mount
--network name # Connect to network
--rm # Remove container on exit
-m 512m # Memory limit
--cpus 1.0 # CPU limit
Dockerfile 指令
FROM image:tag # Base image
WORKDIR /path # Set working directory
COPY src dst # Copy files
ADD src dst # Copy (with URL/tar support)
RUN command # Execute command
ENV KEY=value # Environment variable
EXPOSE port # Document port
CMD ["executable"] # Default command
ENTRYPOINT ["exec"] # Command prefix
VOLUME /path # Create mount point
USER username # Set user
ARG name=default # Build argument
LABEL key=value # Metadata
HEALTHCHECK CMD command # Health check
概要
Docker 容器化可提供:
- 一致性:从开发到生产环境保持一致
- 隔离性:不同应用的依赖不会相互冲突
- 可移植性:可在任何运行 Docker 的环境中运行(云端、本地、CI)
- 效率:与虚拟机相比更轻量,启动速度更快
- 可扩展性:通过编排轻松实现水平扩展
关键工作流:
- 开发:使用带热重载卷的 docker-compose
- CI/CD:构建、测试并将镜像推送到注册表
- 生产:拉取镜像,并设置资源限制和健康检查后运行
后续步骤:
- 掌握多阶段构建,以优化镜像大小
- 实现健康检查和优雅关停
- 设置 docker-compose,用于本地开发
- 将 Docker 集成到 CI/CD 流水线中
- 探索编排方案(Swarm 或 Kubernetes),以满足生产规模需求
评论
支持 Markdown