docker
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseDocker Expert
Docker专家
When to Use
适用场景
- Creating or reviewing Dockerfiles
- Optimizing image size or build performance
- Hardening container security
- Setting up Docker Compose for multi-service apps
- Debugging container networking, volumes, or runtime issues
- Containerizing applications (Node.js, Python, Go, Java, Rust)
Out of scope (recommend dedicated skills):
- Kubernetes orchestration → kubernetes expert
- CI/CD pipelines → github-actions expert
- Cloud-specific container services (ECS, Cloud Run) → devops expert
- 创建或审核Dockerfile
- 优化镜像大小或构建性能
- 容器安全加固
- 为多服务应用配置Docker Compose
- 调试容器网络、卷或运行时问题
- 应用容器化(Node.js、Python、Go、Java、Rust)
超出范围(推荐使用专属技能):
- Kubernetes编排 → Kubernetes专家
- CI/CD流水线 → GitHub Actions专家
- 云厂商专属容器服务(ECS、Cloud Run)→ DevOps专家
Core Principles
核心原则
- Layer caching — order layers from least to most frequently changing
- Security-first — non-root users, minimal attack surface, no secrets in layers
- Minimal images — only include what's needed at runtime
- Reproducibility — pin versions, avoid tag, use lockfiles
latest
- 分层缓存 — 按变更频率从低到高排列分层
- 安全优先 — 使用非Root用户、最小化攻击面、不在分层中存储密钥
- 镜像最小化 — 仅包含运行时所需内容
- 可重复性 — 固定版本、避免使用标签、使用锁定文件
latest
Base Image Selection
基础镜像选择
Recommended hierarchy (most to least preferred):
| Base Image | Size | Shell | Use Case |
|---|---|---|---|
| ~10-30MB | Yes | Zero-CVE goal, SBOM included |
| ~7MB | Yes | General-purpose minimal |
| ~2-5MB | No | Hardened production, no debug |
| ~70-100MB | Yes | When Alpine compatibility is an issue |
| 0MB | No | Static binaries (Go, Rust) |
Rules:
- Always pin exact versions: not
node:22.14.0-alpine3.21node:alpine - Never use — breaks reproducibility
latest - Match base to actual runtime needs
推荐优先级(从高到低):
| 基础镜像 | 大小 | 终端 | 适用场景 |
|---|---|---|---|
| ~10-30MB | 支持 | 零CVE目标,包含SBOM |
| ~7MB | 支持 | 通用型最小镜像 |
| ~2-5MB | 不支持 | 加固型生产镜像,无调试工具 |
| ~70-100MB | 支持 | 当Alpine兼容性存在问题时使用 |
| 0MB | 不支持 | 静态二进制文件(Go、Rust) |
规则:
- 始终固定精确版本:使用而非
node:22.14.0-alpine3.21node:alpine - 绝不使用标签 — 会破坏可重复性
latest - 根据实际运行时需求选择基础镜像
Dockerfile Best Practices
Dockerfile最佳实践
Layer Ordering
分层顺序
dockerfile
undefineddockerfile
undefined1. Base image + system deps (rarely change)
1. 基础镜像 + 系统依赖(极少变更)
FROM node:22-alpine
RUN apk add --no-cache dumb-init
FROM node:22-alpine
RUN apk add --no-cache dumb-init
2. Dependencies (change occasionally)
2. 应用依赖(偶尔变更)
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm ci --only=production
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm ci --only=production
3. Application code (changes frequently)
3. 应用代码(频繁变更)
COPY . .
COPY . .
4. Metadata + runtime config
4. 元数据 + 运行时配置
USER node
EXPOSE 3000
CMD ["dumb-init", "node", "server.js"]
undefinedUSER node
EXPOSE 3000
CMD ["dumb-init", "node", "server.js"]
undefined.dockerignore
.dockerignore配置
Always create one to reduce build context:
.git
node_modules
__pycache__
*.pyc
.vscode
.idea
.DS_Store
*.log
coverage/
.env
.env.local
dist/
build/
README.md
docs/始终创建该文件以减小构建上下文:
.git
node_modules
__pycache__
*.pyc
.vscode
.idea
.DS_Store
*.log
coverage/
.env
.env.local
dist/
build/
README.md
docs/BuildKit Cache Mounts
BuildKit缓存挂载
Speed up dependency installation:
dockerfile
undefined加速依赖安装:
dockerfile
undefinedNode.js
Node.js
RUN --mount=type=cache,target=/root/.npm
npm ci
npm ci
RUN --mount=type=cache,target=/root/.npm
npm ci
npm ci
Python
Python
RUN --mount=type=cache,target=/root/.cache/pip
pip install -r requirements.txt
pip install -r requirements.txt
RUN --mount=type=cache,target=/root/.cache/pip
pip install -r requirements.txt
pip install -r requirements.txt
Go
Go
RUN --mount=type=cache,target=/go/pkg/mod
go build -o /app .
go build -o /app .
Enable with `DOCKER_BUILDKIT=1` or Docker Desktop (on by default).RUN --mount=type=cache,target=/go/pkg/mod
go build -o /app .
go build -o /app .
通过`DOCKER_BUILDKIT=1`启用,或使用Docker Desktop(默认启用)。Multi-Stage Build Patterns
多阶段构建模式
Node.js
Node.js
dockerfile
FROM node:22-alpine AS deps
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm ci
FROM node:22-alpine AS build
WORKDIR /app
COPY /app/node_modules ./node_modules
COPY . .
RUN npm run build
FROM node:22-alpine AS runtime
RUN addgroup -g 1001 -S app && adduser -S app -u 1001
WORKDIR /app
COPY /app/dist ./dist
COPY /app/node_modules ./node_modules
COPY package.json ./
USER app
EXPOSE 3000
HEALTHCHECK \
CMD wget -qO- http://localhost:3000/health || exit 1
CMD ["node", "dist/index.js"]dockerfile
FROM node:22-alpine AS deps
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm ci
FROM node:22-alpine AS build
WORKDIR /app
COPY /app/node_modules ./node_modules
COPY . .
RUN npm run build
FROM node:22-alpine AS runtime
RUN addgroup -g 1001 -S app && adduser -S app -u 1001
WORKDIR /app
COPY /app/dist ./dist
COPY /app/node_modules ./node_modules
COPY package.json ./
USER app
EXPOSE 3000
HEALTHCHECK \
CMD wget -qO- http://localhost:3000/health || exit 1
CMD ["node", "dist/index.js"]Python
Python
dockerfile
FROM python:3.13-slim AS build
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir --prefix=/install -r requirements.txt
FROM python:3.13-slim AS runtime
RUN useradd -r -u 1001 app
WORKDIR /app
COPY /install /usr/local
COPY . .
USER app
EXPOSE 8000
CMD ["python", "-m", "uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]dockerfile
FROM python:3.13-slim AS build
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir --prefix=/install -r requirements.txt
FROM python:3.13-slim AS runtime
RUN useradd -r -u 1001 app
WORKDIR /app
COPY /install /usr/local
COPY . .
USER app
EXPOSE 8000
CMD ["python", "-m", "uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]Go
Go
dockerfile
FROM golang:1.24-alpine AS build
WORKDIR /src
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 go build -ldflags="-s -w" -o /app .
FROM scratch
COPY /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/
COPY /app /app
USER 65534:65534
EXPOSE 8080
ENTRYPOINT ["/app"]dockerfile
FROM golang:1.24-alpine AS build
WORKDIR /src
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 go build -ldflags="-s -w" -o /app .
FROM scratch
COPY /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/
COPY /app /app
USER 65534:65534
EXPOSE 8080
ENTRYPOINT ["/app"]Java
Java
dockerfile
FROM eclipse-temurin:21-jdk-alpine AS build
WORKDIR /app
COPY . .
RUN ./gradlew build --no-daemon
FROM eclipse-temurin:21-jre-alpine AS runtime
RUN addgroup -g 1001 -S app && adduser -S app -u 1001
WORKDIR /app
COPY /app/build/libs/*.jar app.jar
USER app
EXPOSE 8080
HEALTHCHECK \
CMD wget -qO- http://localhost:8080/actuator/health || exit 1
CMD ["java", "-jar", "app.jar"]dockerfile
FROM eclipse-temurin:21-jdk-alpine AS build
WORKDIR /app
COPY . .
RUN ./gradlew build --no-daemon
FROM eclipse-temurin:21-jre-alpine AS runtime
RUN addgroup -g 1001 -S app && adduser -S app -u 1001
WORKDIR /app
COPY /app/build/libs/*.jar app.jar
USER app
EXPOSE 8080
HEALTHCHECK \
CMD wget -qO- http://localhost:8080/actuator/health || exit 1
CMD ["java", "-jar", "app.jar"]Rust
Rust
dockerfile
FROM rust:1.84-alpine AS build
RUN apk add --no-cache musl-dev
WORKDIR /app
COPY Cargo.toml Cargo.lock ./
RUN mkdir src && echo "fn main() {}" > src/main.rs && cargo build --release && rm -rf src
COPY src ./src
RUN cargo build --release
FROM scratch
COPY /app/target/release/app /app
USER 65534:65534
EXPOSE 8080
ENTRYPOINT ["/app"]dockerfile
FROM rust:1.84-alpine AS build
RUN apk add --no-cache musl-dev
WORKDIR /app
COPY Cargo.toml Cargo.lock ./
RUN mkdir src && echo "fn main() {}" > src/main.rs && cargo build --release && rm -rf src
COPY src ./src
RUN cargo build --release
FROM scratch
COPY /app/target/release/app /app
USER 65534:65534
EXPOSE 8080
ENTRYPOINT ["/app"]Security Hardening
安全加固
Non-Root Users
非Root用户
dockerfile
undefineddockerfile
undefinedAlpine
Alpine
RUN addgroup -g 1001 -S app && adduser -S app -u 1001 -G app
USER app
RUN addgroup -g 1001 -S app && adduser -S app -u 1001 -G app
USER app
Debian/Ubuntu
Debian/Ubuntu
RUN groupadd -g 1001 app && useradd -r -u 1001 -g app app
USER app
RUN groupadd -g 1001 app && useradd -r -u 1001 -g app app
USER app
Distroless/scratch (numeric only)
Distroless/scratch(仅支持数字ID)
USER 65534:65534
undefinedUSER 65534:65534
undefinedSecrets Management
密钥管理
dockerfile
undefineddockerfile
undefinedBuildKit secrets (never stored in layers)
BuildKit密钥(绝不会存储在分层中)
RUN --mount=type=secret,id=api_key
API_KEY=$(cat /run/secrets/api_key) &&
./configure --api-key="$API_KEY"
API_KEY=$(cat /run/secrets/api_key) &&
./configure --api-key="$API_KEY"
```bashRUN --mount=type=secret,id=api_key
API_KEY=$(cat /run/secrets/api_key) &&
./configure --api-key="$API_KEY"
API_KEY=$(cat /run/secrets/api_key) &&
./configure --api-key="$API_KEY"
```bashBuild with secret
使用密钥构建镜像
docker build --secret id=api_key,src=./api_key.txt .
**Never do:**
```dockerfile
ENV API_KEY=secret123 # Visible in image history
COPY .env /app/.env # Baked into layer
ARG PASSWORD=hunter2 # Visible in build historydocker build --secret id=api_key,src=./api_key.txt .
**绝对禁止:**
```dockerfile
ENV API_KEY=secret123 # 在镜像历史中可见
COPY .env /app/.env # 被固化到分层中
ARG PASSWORD=hunter2 # 在构建历史中可见Runtime Hardening
运行时加固
bash
docker run \
--user 1001:1001 \
--cap-drop=ALL \
--cap-add=NET_BIND_SERVICE \
--read-only \
--tmpfs /tmp:noexec,nosuid \
--security-opt="no-new-privileges:true" \
--memory="512m" \
--cpus="1.0" \
my-imagebash
docker run \
--user 1001:1001 \
--cap-drop=ALL \
--cap-add=NET_BIND_SERVICE \
--read-only \
--tmpfs /tmp:noexec,nosuid \
--security-opt="no-new-privileges:true" \
--memory="512m" \
--cpus="1.0" \
my-imageVulnerability Scanning
漏洞扫描
bash
undefinedbash
undefinedDocker Scout
Docker Scout
docker scout quickview my-image
docker scout cves my-image
docker scout quickview my-image
docker scout cves my-image
Trivy
Trivy
trivy image my-image
trivy image my-image
Grype
Grype
grype my-image
undefinedgrype my-image
undefinedDocker Compose
Docker Compose
Production-Ready Pattern
生产就绪模式
yaml
services:
app:
build:
context: .
target: runtime
depends_on:
db:
condition: service_healthy
redis:
condition: service_started
networks:
- frontend
- backend
healthcheck:
test: ["CMD", "wget", "-qO-", "http://localhost:3000/health"]
interval: 30s
timeout: 10s
retries: 3
start_period: 40s
deploy:
resources:
limits:
cpus: "1.0"
memory: 512M
reservations:
cpus: "0.5"
memory: 256M
restart: unless-stopped
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"
db:
image: postgres:17-alpine
environment:
POSTGRES_DB_FILE: /run/secrets/db_name
POSTGRES_USER_FILE: /run/secrets/db_user
POSTGRES_PASSWORD_FILE: /run/secrets/db_password
secrets:
- db_name
- db_user
- db_password
volumes:
- postgres_data:/var/lib/postgresql/data
networks:
- backend
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres"]
interval: 10s
timeout: 5s
retries: 5
redis:
image: redis:7-alpine
command: redis-server --maxmemory 128mb --maxmemory-policy allkeys-lru
volumes:
- redis_data:/data
networks:
- backend
networks:
frontend:
driver: bridge
backend:
driver: bridge
internal: true # No external access
volumes:
postgres_data:
redis_data:
secrets:
db_name:
file: ./secrets/db_name.txt
db_user:
file: ./secrets/db_user.txt
db_password:
file: ./secrets/db_password.txtyaml
services:
app:
build:
context: .
target: runtime
depends_on:
db:
condition: service_healthy
redis:
condition: service_started
networks:
- frontend
- backend
healthcheck:
test: ["CMD", "wget", "-qO-", "http://localhost:3000/health"]
interval: 30s
timeout: 10s
retries: 3
start_period: 40s
deploy:
resources:
limits:
cpus: "1.0"
memory: 512M
reservations:
cpus: "0.5"
memory: 256M
restart: unless-stopped
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"
db:
image: postgres:17-alpine
environment:
POSTGRES_DB_FILE: /run/secrets/db_name
POSTGRES_USER_FILE: /run/secrets/db_user
POSTGRES_PASSWORD_FILE: /run/secrets/db_password
secrets:
- db_name
- db_user
- db_password
volumes:
- postgres_data:/var/lib/postgresql/data
networks:
- backend
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres"]
interval: 10s
timeout: 5s
retries: 5
redis:
image: redis:7-alpine
command: redis-server --maxmemory 128mb --maxmemory-policy allkeys-lru
volumes:
- redis_data:/data
networks:
- backend
networks:
frontend:
driver: bridge
backend:
driver: bridge
internal: true # 无外部访问权限
volumes:
postgres_data:
redis_data:
secrets:
db_name:
file: ./secrets/db_name.txt
db_user:
file: ./secrets/db_user.txt
db_password:
file: ./secrets/db_password.txtNetwork Isolation
网络隔离
yaml
networks:
frontend: # Web-facing services
backend:
internal: true # Database, cache — no external access
services:
proxy:
networks: [frontend]
api:
networks: [frontend, backend]
db:
networks: [backend] # Only reachable from apiyaml
networks:
frontend: # 面向Web的服务
backend:
internal: true # 数据库、缓存 — 无外部访问权限
services:
proxy:
networks: [frontend]
api:
networks: [frontend, backend]
db:
networks: [backend] # 仅能从api服务访问Dev vs Prod Overrides
开发与生产环境配置覆盖
yaml
undefinedyaml
undefinedcompose.yml (base)
compose.yml(基础配置)
services:
app:
build: .
services:
app:
build: .
compose.override.yml (dev, loaded automatically)
compose.override.yml(开发环境,自动加载)
services:
app:
build:
target: development
volumes:
- .:/app
- /app/node_modules
ports:
- "9229:9229" # Debug
environment:
- NODE_ENV=development
command: npm run dev
services:
app:
build:
target: development
volumes:
- .:/app
- /app/node_modules
ports:
- "9229:9229" # 调试端口
environment:
- NODE_ENV=development
command: npm run dev
compose.prod.yml
compose.prod.yml(生产环境)
services:
app:
build:
target: runtime
environment:
- NODE_ENV=production
restart: unless-stopped
```bashservices:
app:
build:
target: runtime
environment:
- NODE_ENV=production
restart: unless-stopped
```bashDev (auto-loads compose.override.yml)
开发环境(自动加载compose.override.yml)
docker compose up
docker compose up
Prod
生产环境
docker compose -f compose.yml -f compose.prod.yml up -d
undefineddocker compose -f compose.yml -f compose.prod.yml up -d
undefinedImage Optimization
镜像优化
Size Reduction Techniques
大小缩减技巧
- Multi-stage builds — don't ship build tools
- Minimal base images — Alpine or distroless
- Combine RUN commands — cleanup in same layer
- Copy selectively — only needed artifacts
dockerfile
undefined- 多阶段构建 — 不包含构建工具
- 最小化基础镜像 — 使用Alpine或distroless
- 合并RUN命令 — 在同一分层中清理无用内容
- 选择性复制 — 仅复制所需产物
dockerfile
undefinedBad — 3 layers, cleanup doesn't reduce size
错误示例 — 3个分层,清理操作无法减小镜像大小
RUN apt-get update
RUN apt-get install -y curl
RUN rm -rf /var/lib/apt/lists/*
RUN apt-get update
RUN apt-get install -y curl
RUN rm -rf /var/lib/apt/lists/*
Good — 1 layer, cleanup is effective
正确示例 — 1个分层,清理操作有效
RUN apt-get update &&
apt-get install -y --no-install-recommends curl &&
rm -rf /var/lib/apt/lists/*
apt-get install -y --no-install-recommends curl &&
rm -rf /var/lib/apt/lists/*
undefinedRUN apt-get update &&
apt-get install -y --no-install-recommends curl &&
rm -rf /var/lib/apt/lists/*
apt-get install -y --no-install-recommends curl &&
rm -rf /var/lib/apt/lists/*
undefinedCMD: Exec Form vs Shell Form
CMD:执行格式 vs Shell格式
dockerfile
CMD ["node", "server.js"] # Exec form — PID 1, receives signals directly
CMD node server.js # Shell form — spawns /bin/sh, signal issuesAlways prefer exec form.
dockerfile
CMD ["node", "server.js"] # 执行格式 — PID为1,直接接收信号
CMD node server.js # Shell格式 — 生成/bin/sh进程,存在信号处理问题始终优先使用执行格式。
Development Workflow
开发工作流
Hot Reload Setup
热重载配置
yaml
services:
app:
build:
target: development
volumes:
- .:/app # Source code
- /app/node_modules # Prevent overwrite
ports:
- "3000:3000"
- "9229:9229" # Debug port
environment:
- NODE_ENV=development
- DEBUG=app:*
command: npm run devyaml
services:
app:
build:
target: development
volumes:
- .:/app # 源代码
- /app/node_modules # 防止覆盖依赖
ports:
- "3000:3000"
- "9229:9229" # 调试端口
environment:
- NODE_ENV=development
- DEBUG=app:*
command: npm run devDebugging
调试配置
yaml
services:
app:
# Node.js inspect
command: node --inspect=0.0.0.0:9229 server.js
ports:
- "9229:9229"
# Python debugpy
# command: python -m debugpy --listen 0.0.0.0:5678 main.py
# ports:
# - "5678:5678"yaml
services:
app:
# Node.js调试
command: node --inspect=0.0.0.0:9229 server.js
ports:
- "9229:9229"
# Python debugpy调试
# command: python -m debugpy --listen 0.0.0.0:5678 main.py
# ports:
# - "5678:5678"Platform-Specific
平台专属配置
Linux
Linux
json
// /etc/docker/daemon.json
{
"userns-remap": "default",
"storage-driver": "overlay2",
"live-restore": true,
"log-driver": "json-file",
"log-opts": {
"max-size": "10m",
"max-file": "3"
}
}- Use user namespace remapping for added security
- Configure SELinux/AppArmor profiles for production
- Use storage driver
overlay2
json
// /etc/docker/daemon.json
{
"userns-remap": "default",
"storage-driver": "overlay2",
"live-restore": true,
"log-driver": "json-file",
"log-opts": {
"max-size": "10m",
"max-file": "3"
}
}- 使用用户命名空间映射提升安全性
- 为生产环境配置SELinux/AppArmor策略
- 使用存储驱动
overlay2
macOS
macOS
yaml
volumes:
- ./src:/app/src:delegated # Better write performance
- ./build:/app/build:cached # Container writes cached- Allocate sufficient resources in Docker Desktop
- Use /
:delegatedfor bind mount performance:cached - Consider or
mutagenfor file syncdocker compose watch - Multi-platform builds for ARM (Apple Silicon)
yaml
volumes:
- ./src:/app/src:delegated # 更好的写入性能
- ./build:/app/build:cached # 容器写入内容被缓存- 在Docker Desktop中分配足够的资源
- 使用/
:delegated提升绑定挂载性能:cached - 考虑使用或
mutagen进行文件同步docker compose watch - 为ARM架构(Apple Silicon)构建多平台镜像
Windows
Windows
- Prefer WSL2 backend for best performance
- Handle line endings: add with
.gitattributes* text=auto eol=lf - Use forward slashes in Dockerfiles and compose files
- Ensure drives are shared in Docker Desktop settings
- Be aware of file permission differences
gitattributes
undefined- 优先使用WSL2后端以获得最佳性能
- 处理行尾符:添加文件并配置
.gitattributes* text=auto eol=lf - 在Dockerfile和Compose文件中使用正斜杠
- 确保在Docker Desktop设置中共享相关驱动器
- 注意文件权限差异
gitattributes
undefined.gitattributes — prevent CRLF issues in containers
.gitattributes — 避免容器中出现CRLF问题
- text=auto eol=lf *.sh text eol=lf Dockerfile text eol=lf
undefined- text=auto eol=lf *.sh text eol=lf Dockerfile text eol=lf
undefinedProduction Checklist
生产环境检查清单
- Pinned base image version (no )
latest - Multi-stage build separates build and runtime
- Runs as non-root user
- No secrets in layers or ENV
- configured
.dockerignore - Health check implemented
- Resource limits set (CPU, memory)
- Logging configured with rotation
- Vulnerability scan passed
- Signals handled correctly (exec form CMD, or /
dumb-init)tini - Read-only filesystem where possible
- Capabilities dropped ()
--cap-drop=ALL
- 固定基础镜像版本(不使用)
latest - 使用多阶段构建分离构建与运行时
- 以非Root用户运行
- 分层或ENV中不包含密钥
- 配置了
.dockerignore - 实现了健康检查
- 设置了资源限制(CPU、内存)
- 配置了日志轮转
- 通过漏洞扫描
- 正确处理信号(使用执行格式CMD,或/
dumb-init)tini - 尽可能使用只读文件系统
- 移除不必要的权限()
--cap-drop=ALL
Anti-Patterns
反模式
| Don't | Do Instead |
|---|---|
| Run as root | |
Use | Pin exact versions |
| |
| Mount Docker socket | Use Docker-in-Docker or alternatives |
| Hardcode secrets in ENV/ARG | BuildKit secrets or runtime mounts |
| Skip health checks | |
| Ignore resource limits | Set |
| Copy entire context | Use |
| Install unnecessary packages | |
| Use shell form CMD | Use exec form |
| 禁止操作 | 正确做法 |
|---|---|
| 以Root用户运行 | 使用 |
使用 | 固定精确版本 |
使用 | 仅添加必要的权限( |
| 挂载Docker套接字 | 使用Docker-in-Docker或替代方案 |
| 在ENV/ARG中硬编码密钥 | 使用BuildKit密钥或运行时挂载 |
| 跳过健康检查 | 在Dockerfile或Compose中配置 |
| 忽略资源限制 | 设置 |
| 复制整个构建上下文 | 使用 |
| 安装不必要的软件包 | 使用 |
| 使用Shell格式CMD | 使用执行格式 |
Diagnostics
诊断排查
Slow Builds
构建缓慢
- Check layer ordering (deps before source)
- Enable BuildKit ()
DOCKER_BUILDKIT=1 - Use cache mounts for package managers
- Review (large build context?)
.dockerignore
- 检查分层顺序(依赖项置于源代码之前)
- 启用BuildKit()
DOCKER_BUILDKIT=1 - 为包管理器使用缓存挂载
- 检查(构建上下文过大?)
.dockerignore
Large Images
镜像过大
- Use multi-stage builds
- Switch to Alpine or distroless
- Combine RUN commands with cleanup
- Check to find large layers
docker history <image>
- 使用多阶段构建
- 切换到Alpine或distroless基础镜像
- 合并RUN命令并清理
- 使用查找大分层
docker history <image>
Networking Issues
网络问题
- Verify service names for DNS resolution
- Check network assignments in Compose
- Use to debug
docker network inspect - Ensure health checks pass before dependent services start
- 验证服务名称以确保DNS解析正常
- 检查Compose中的网络分配
- 使用进行调试
docker network inspect - 确保依赖服务启动前健康检查已通过
Container Crashes
容器崩溃
- Check logs:
docker logs <container> - Verify signal handling (PID 1 must handle SIGTERM)
- Check resource limits (OOM kills)
- Validate health check endpoints exist
- 查看日志:
docker logs <container> - 验证信号处理(PID 1必须处理SIGTERM)
- 检查资源限制(OOM终止)
- 验证健康检查端点是否存在