选择合适的基础镜像:
# ❌ 不推荐: 使用大镜像
FROM ubuntu:latest
# ✅ 推荐: 使用Alpine镜像
FROM alpine:3.18
# ✅ 推荐: 使用特定版本
FROM node:18-alpine
# ✅ 推荐: 使用官方镜像
FROM nginx:1.25-alpine
# ✅ 推荐: 使用多阶段构建
FROM node:18-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
FROM node:18-alpine
WORKDIR /app
COPY --from=builder /app/node_modules ./node_modules
COPY . .
CMD ["npm", "start"]
基础镜像对比:
基础镜像大小对比:
┌──────────────────┬──────────────┬──────────────┐
│ 镜像 │ 大小 │ 适用场景 │
├──────────────────┼──────────────┼──────────────┤
│ alpine │ 5MB │ 最小化镜像 │
│ debian:slim │ 80MB │ 需要glibc │
│ ubuntu │ 77MB │ 完整环境 │
│ centos │ 231MB │ 企业环境 │
│ busybox │ 1.2MB │ 极简环境 │
└──────────────────┴──────────────┴──────────────┘
选择原则:
✅ 优先选择Alpine镜像
✅ 使用特定版本标签
✅ 使用官方维护的镜像
✅ 定期更新基础镜像
✅ 考虑安全性和大小
优化Dockerfile指令:
# ❌ 不推荐: 每个RUN指令一层
FROM alpine:3.18
RUN apk add --no-cache nodejs
RUN apk add --no-cache npm
RUN apk add --no-cache git
# ✅ 推荐: 合并RUN指令
FROM alpine:3.18
RUN apk add --no-cache \
nodejs \
npm \
git
# ❌ 不推荐: 在前面复制文件
FROM alpine:3.18
COPY . /app
RUN apk add --no-cache nodejs
# ✅ 推荐: 先安装依赖,后复制文件
FROM alpine:3.18
RUN apk add --no-cache nodejs
COPY . /app
# ❌ 不推荐: 不清理缓存
FROM alpine:3.18
RUN apk add nodejs
# ✅ 推荐: 清理缓存
FROM alpine:3.18
RUN apk add --no-cache nodejs && \
rm -rf /var/cache/apk/*
# ❌ 不推荐: 使用ADD下载文件
FROM alpine:3.18
ADD https://example.com/file.tar.gz /tmp/
# ✅ 推荐: 使用curl下载并清理
FROM alpine:3.18
RUN apk add --no-cache curl && \
curl -fsSL https://example.com/file.tar.gz | tar xzf - -C /tmp/ && \
apk del curl
指令优化原则:
Dockerfile优化原则:
┌──────────────────┬──────────────┬──────────────┐
│ 原则 │ 说明 │ 效果 │
├──────────────────┼──────────────┼──────────────┤
│ 合并指令 │ 减少镜像层 │ 减小镜像大小 │
│ 顺序优化 │ 变化少的在前 │ 利用缓存 │
│ 清理缓存 │ 删除临时文件 │ 减小镜像大小 │
│ 使用COPY │ 不用ADD │ 明确意图 │
│ 多阶段构建 │ 分离构建环境 │ 减小镜像大小 │
└──────────────────┴──────────────┴──────────────┘
指令顺序建议:
1. FROM: 基础镜像
2. LABEL: 元数据标签
3. ENV: 环境变量
4. RUN: 安装依赖
5. COPY: 复制文件
6. EXPOSE: 暴露端口
7. VOLUME: 数据卷
8. CMD/ENTRYPOINT: 启动命令
使用多阶段构建:
# 构建阶段
FROM golang:1.21-alpine AS builder
WORKDIR /build
# 安装依赖
RUN apk add --no-cache git
# 复制go.mod和go.sum
COPY go.mod go.sum ./
RUN go mod download
# 复制源代码
COPY . .
# 构建应用
RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o main .
# 运行阶段
FROM alpine:3.18
WORKDIR /app
# 安装ca证书
RUN apk --no-cache add ca-certificates
# 从构建阶段复制二进制文件
COPY --from=builder /build/main .
# 暴露端口
EXPOSE 8080
# 运行应用
CMD ["./main"]
多阶段构建优势:
多阶段构建优势:
✅ 减小最终镜像大小
✅ 分离构建和运行环境
✅ 提高安全性
✅ 简化构建过程
镜像大小对比:
单阶段构建: 800MB
多阶段构建: 15MB
减少: 98%
标签命名最佳实践:
# ❌ 不推荐: 使用latest标签
docker build -t myapp:latest .
# ✅ 推荐: 使用具体版本号
docker build -t myapp:1.0.0 .
# ✅ 推荐: 使用多个标签
docker build -t myapp:1.0.0 -t myapp:1.0 -t myapp:latest .
# ✅ 推荐: 包含构建信息
docker build -t myapp:1.0.0-20240101 .
# ✅ 推荐: 包含Git提交信息
docker build -t myapp:1.0.0-$(git rev-parse --short HEAD) .
标签命名规范:
标签命名规范:
┌──────────────────┬──────────────┬──────────────┐
│ 标签类型 │ 示例 │ 说明 │
├──────────────────┼──────────────┼──────────────┤
│ 版本号 │ 1.0.0 │ 语义化版本 │
│ 主版本号 │ 1 │ 主版本 │
│ 次版本号 │ 1.0 │ 次版本 │
│ 构建号 │ 1.0.0-123 │ 包含构建号 │
│ Git提交 │ 1.0.0-a1b2c3d│ 包含提交ID │
│ 环境标识 │ 1.0.0-prod │ 环境标识 │
│ latest │ latest │ 最新版本 │
└──────────────────┴──────────────┴──────────────┘
标签使用建议:
✅ 避免在生产环境使用latest
✅ 使用语义化版本号
✅ 记录镜像构建信息
✅ 定期更新基础镜像
✅ 删除旧版本镜像
镜像仓库最佳实践:
# 推送镜像到仓库
docker tag myapp:1.0.0 registry.example.com/myapp:1.0.0
docker push registry.example.com/myapp:1.0.0
# 推送多个标签
docker push registry.example.com/myapp:1.0
docker push registry.example.com/myapp:latest
# 使用镜像签名
docker trust sign registry.example.com/myapp:1.0.0
# 验证镜像签名
docker trust inspect registry.example.com/myapp:1.0.0
# 扫描镜像漏洞
docker scan registry.example.com/myapp:1.0.0
设置合理的资源限制:
# ✅ 推荐: 设置CPU和内存限制
docker run -d \
--name myapp \
--cpus="1.5" \
--memory="512m" \
--memory-swap="1g" \
--memory-reservation="256m" \
myapp:1.0.0
# ✅ 推荐: 设置IO限制
docker run -d \
--name myapp \
--device-read-bps=/dev/sda:10mb \
--device-write-bps=/dev/sda:10mb \
myapp:1.0.0
# ✅ 推荐: 使用Docker Compose
# docker-compose.yml
version: '3.8'
services:
myapp:
image: myapp:1.0.0
deploy:
resources:
limits:
cpus: '1.5'
memory: 512M
reservations:
cpus: '0.5'
memory: 256M
资源限制建议:
资源限制建议:
┌──────────────────┬──────────────┬──────────────┐
│ 资源类型 │ 建议配置 │ 说明 │
├──────────────────┼──────────────┼──────────────┤
│ CPU限制 │ 根据应用需求 │ 避免CPU竞争 │
│ 内存限制 │ 应用内存+50% │ 避免OOM │
│ Swap限制 │ 内存限制2倍 │ 控制Swap使用│
│ IO限制 │ 根据磁盘性能 │ 避免IO竞争 │
│ 进程数限制 │ 根据应用需求 │ 防止fork炸弹│
└──────────────────┴──────────────┴──────────────┘
资源监控:
✅ 监控容器资源使用
✅ 设置资源告警
✅ 定期调整资源限制
✅ 记录资源使用趋势
配置合理的重启策略:
# ✅ 推荐: 生产环境使用always
docker run -d \
--name myapp \
--restart=always \
myapp:1.0.0
# ✅ 推荐: 失败时重启
docker run -d \
--name myapp \
--restart=on-failure:5 \
myapp:1.0.0
# ✅ 推荐: 除非手动停止
docker run -d \
--name myapp \
--restart=unless-stopped \
myapp:1.0.0
# ✅ 推荐: 使用Docker Compose
# docker-compose.yml
version: '3.8'
services:
myapp:
image: myapp:1.0.0
restart: unless-stopped
重启策略对比:
重启策略对比:
┌──────────────────┬──────────────┬──────────────┐
│ 策略 │ 行为 │ 适用场景 │
├──────────────────┼──────────────┼──────────────┤
│ no │ 不重启 │ 开发环境 │
│ on-failure │ 失败时重启 │ 测试环境 │
│ always │ 总是重启 │ 生产环境 │
│ unless-stopped │ 除非手动停止 │ 生产环境 │
└──────────────────┴──────────────┴──────────────┘
重启策略建议:
✅ 生产环境使用unless-stopped或always
✅ 设置重启延迟
✅ 配置健康检查
✅ 监控重启次数
配置健康检查:
# Dockerfile中配置健康检查
FROM nginx:1.25-alpine
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
CMD curl -f http://localhost/ || exit 1
CMD ["nginx", "-g", "daemon off;"]
# 运行时配置健康检查
docker run -d \
--name myapp \
--health-cmd="curl -f http://localhost/ || exit 1" \
--health-interval=30s \
--health-timeout=3s \
--health-start-period=5s \
--health-retries=3 \
myapp:1.0.0
# 查看健康状态
docker inspect --format='{{.State.Health.Status}}' myapp
# 查看健康检查历史
docker inspect --format='{{json .State.Health}}' myapp | jq
健康检查建议:
健康检查配置建议:
┌──────────────────┬──────────────┬──────────────┐
│ 参数 │ 建议值 │ 说明 │
├──────────────────┼──────────────┼──────────────┤
│ interval │ 30s │ 检查间隔 │
│ timeout │ 3s │ 超时时间 │
│ start-period │ 5-60s │ 启动时间 │
│ retries │ 3 │ 重试次数 │
└──────────────────┴──────────────┴──────────────┘
健康检查建议:
✅ 检查应用核心功能
✅ 设置合理的超时时间
✅ 考虑应用启动时间
✅ 监控健康检查结果
配置日志驱动:
# ✅ 推荐: 使用json-file驱动并限制大小
docker run -d \
--name myapp \
--log-driver json-file \
--log-opt max-size=10m \
--log-opt max-file=3 \
myapp:1.0.0
# ✅ 推荐: 使用syslog驱动
docker run -d \
--name myapp \
--log-driver syslog \
--log-opt syslog-address=tcp://192.168.1.100:514 \
myapp:1.0.0
# ✅ 推荐: 使用fluentd驱动
docker run -d \
--name myapp \
--log-driver fluentd \
--log-opt fluentd-address=localhost:24224 \
--log-opt tag="docker.{{.Name}}" \
myapp:1.0.0
# ✅ 推荐: 全局配置
# /etc/docker/daemon.json
{
"log-driver": "json-file",
"log-opts": {
"max-size": "10m",
"max-file": "3"
}
}
日志配置建议:
日志配置建议:
┌──────────────────┬──────────────┬──────────────┐
│ 配置项 │ 建议值 │ 说明 │
├──────────────────┼──────────────┼──────────────┤
│ max-size │ 10m │ 单文件大小 │
│ max-file │ 3 │ 文件数量 │
│ 日志格式 │ JSON │ 结构化日志 │
│ 日志级别 │ INFO │ 生产环境 │
└──────────────────┴──────────────┴──────────────┘
日志管理建议:
✅ 限制日志文件大小
✅ 使用结构化日志
✅ 集中收集日志
✅ 定期归档日志
✅ 监控日志异常
应用日志最佳实践:
# Python应用日志示例
import logging
import json
import sys
class JSONFormatter(logging.Formatter):
def format(self, record):
log_entry = {
'timestamp': self.formatTime(record),
'level': record.levelname,
'message': record.getMessage(),
'logger': record.name,
'module': record.module,
'line': record.lineno
}
if record.exc_info:
log_entry['exception'] = self.formatException(record.exc_info)
return json.dumps(log_entry)
# 配置日志
logging.basicConfig(
level=logging.INFO,
stream=sys.stdout,
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
)
logger = logging.getLogger(__name__)
# 使用日志
logger.info("Application started", extra={'version': '1.0.0'})
logger.error("Failed to connect database", exc_info=True)
使用镜像扫描工具:
# 使用Docker Scan扫描镜像
docker scan myapp:1.0.0
# 输出
✗ Low severity vulnerability found in openssl/libssl1.1
In openssl: CVE-2023-XXXX
More info: https://avd.aquasec.com/nvd/cve-2023-xxxx
✗ Medium severity vulnerability found in curl/libcurl4
In curl: CVE-2023-YYYY
More info: https://avd.aquasec.com/nvd/cve-2023-yyyy
# 使用Trivy扫描镜像
trivy image myapp:1.0.0
# 使用Clair扫描镜像
clair-scanner myapp:1.0.0
# 使用Anchore扫描镜像
anchore-cli image add myapp:1.0.0
anchore-cli image vuln myapp:1.0.0 all
镜像安全建议:
镜像安全建议:
✅ 使用可信的基础镜像
✅ 定期扫描镜像漏洞
✅ 及时修复漏洞
✅ 使用镜像签名
✅ 最小化镜像内容
✅ 不在镜像中存储敏感信息
✅ 使用多阶段构建
✅ 定期更新基础镜像
使用非root用户运行:
# ✅ 推荐: 使用非root用户
FROM alpine:3.18
# 创建用户和组
RUN addgroup -g 1000 appgroup && \
adduser -u 1000 -G appgroup -D appuser
# 设置工作目录
WORKDIR /app
# 复制文件并设置权限
COPY --chown=appuser:appgroup . .
# 切换用户
USER appuser
# 启动应用
CMD ["./app"]
# 运行时指定用户
docker run -d \
--name myapp \
--user 1000:1000 \
myapp:1.0.0
# 只读文件系统
docker run -d \
--name myapp \
--read-only \
--tmpfs /tmp \
myapp:1.0.0
权限控制建议:
权限控制建议:
┌──────────────────┬──────────────┬──────────────┐
│ 措施 │ 说明 │ 效果 │
├──────────────────┼──────────────┼──────────────┤
│ 非root用户 │ 使用普通用户 │ 减少权限 │
│ 只读文件系统 │ 只读挂载 │ 防止篡改 │
│ 删除能力 │ 删除不必要能力│ 最小权限 │
│ 禁用特权 │ 不使用特权模式│ 提高安全 │
│ 只读根文件系统 │ --read-only │ 防止修改 │
└──────────────────┴──────────────┴──────────────┘
能力控制:
# 删除所有能力
docker run -d --name myapp --cap-drop=ALL myapp:1.0.0
# 只添加需要的能力
docker run -d --name myapp --cap-drop=ALL --cap-add=NET_BIND_SERVICE myapp:1.0.0
网络隔离最佳实践:
# ✅ 推荐: 使用自定义网络
docker network create --driver bridge mynetwork
# ✅ 推荐: 限制容器间通信
docker network create --driver bridge --internal internal-network
# ✅ 推荐: 使用网络策略
# 在Kubernetes中使用NetworkPolicy
# ✅ 推荐: 不暴露不必要的端口
docker run -d \
--name myapp \
--network mynetwork \
myapp:1.0.0
# ✅ 推荐: 使用反向代理
docker run -d \
--name nginx \
-p 80:80 \
--network mynetwork \
nginx:latest
网络安全建议:
网络安全建议:
✅ 使用自定义网络
✅ 限制容器间通信
✅ 不暴露不必要的端口
✅ 使用反向代理
✅ 配置防火墙规则
✅ 使用TLS加密通信
✅ 定期审计网络配置
管理敏感信息:
# ❌ 不推荐: 使用环境变量传递敏感信息
docker run -d \
--name myapp \
-e DB_PASSWORD=secret123 \
myapp:1.0.0
# ✅ 推荐: 使用Docker Secrets
echo "secret123" | docker secret create db_password -
docker service create \
--name myapp \
--secret db_password \
myapp:1.0.0
# ✅ 推荐: 使用文件挂载
docker run -d \
--name myapp \
-v /host/secrets:/run/secrets:ro \
myapp:1.0.0
# ✅ 推荐: 使用Kubernetes Secrets
kubectl create secret generic db-password --from-literal=password=secret123
敏感信息管理建议:
敏感信息管理建议:
✅ 不在镜像中存储敏感信息
✅ 不使用环境变量传递敏感信息
✅ 使用Secrets管理敏感信息
✅ 加密存储敏感信息
✅ 定期轮换密钥
✅ 审计敏感信息访问
镜像优化技巧:
# ✅ 推荐: 使用Alpine基础镜像
FROM alpine:3.18
# ✅ 推荐: 合并RUN指令
RUN apk add --no-cache \
nodejs \
npm && \
rm -rf /var/cache/apk/*
# ✅ 推荐: 使用多阶段构建
FROM node:18-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
FROM node:18-alpine
WORKDIR /app
COPY --from=builder /app/node_modules ./node_modules
COPY . .
CMD ["npm", "start"]
# ✅ 推荐: 使用.dockerignore
# .dockerignore
node_modules
npm-debug.log
Dockerfile
.dockerignore
.git
.gitignore
README.md
.env
镜像优化建议:
镜像优化建议:
┌──────────────────┬──────────────┬──────────────┐
│ 优化方法 │ 效果 │ 说明 │
├──────────────────┼──────────────┼──────────────┤
│ 使用Alpine │ 减小80% │ 最小化基础 │
│ 多阶段构建 │ 减小50-90% │ 分离构建环境 │
│ 合并指令 │ 减小10-20% │ 减少镜像层 │
│ 清理缓存 │ 减小5-10% │ 删除临时文件 │
│ .dockerignore │ 减小10-30% │ 排除无用文件 │
└──────────────────┴──────────────┴──────────────┘
镜像大小对比:
Ubuntu基础镜像: 77MB
Alpine基础镜像: 5MB
减少: 93%
优化构建缓存:
# ❌ 不推荐: 频繁变化的文件在前
FROM alpine:3.18
COPY . /app
RUN apk add --no-cache nodejs
# ✅ 推荐: 变化少的在前
FROM alpine:3.18
RUN apk add --no-cache nodejs
COPY package*.json ./
RUN npm install
COPY . .
# ✅ 推荐: 使用BuildKit
# DOCKER_BUILDKIT=1 docker build -t myapp:1.0.0 .
# ✅ 推荐: 使用缓存挂载
# syntax=docker/dockerfile:1
FROM alpine:3.18
RUN --mount=type=cache,target=/var/cache/apk \
apk add --no-cache nodejs
资源优化配置:
# ✅ 推荐: 设置资源限制
docker run -d \
--name myapp \
--cpus="1.5" \
--memory="512m" \
--memory-swap="1g" \
--memory-swappiness=0 \
--oom-kill-disable=false \
myapp:1.0.0
# ✅ 推荐: 使用CPU亲和性
docker run -d \
--name myapp \
--cpuset-cpus="0,1" \
myapp:1.0.0
# ✅ 推荐: 使用IO限制
docker run -d \
--name myapp \
--device-read-bps=/dev/sda:10mb \
--device-write-bps=/dev/sda:10mb \
myapp:1.0.0
# ✅ 推荐: 使用tmpfs
docker run -d \
--name myapp \
--mount type=tmpfs,destination=/tmp,tmpfs-size=100m \
myapp:1.0.0
网络优化配置:
# ✅ 推荐: 使用host网络模式(高性能)
docker run -d \
--name myapp \
--network host \
myapp:1.0.0
# ✅ 推荐: 优化MTU
docker network create \
--driver bridge \
--opt com.docker.network.driver.mtu=1500 \
mynetwork
# ✅ 推荐: 优化DNS
docker run -d \
--name myapp \
--dns 8.8.8.8 \
--dns 8.8.4.4 \
--dns-opt ndots:1 \
myapp:1.0.0
# ✅ 推荐: 优化TCP参数
docker run -d \
--name myapp \
--sysctl net.core.somaxconn=65535 \
--sysctl net.ipv4.tcp_max_syn_backlog=65535 \
myapp:1.0.0
镜像构建最佳实践:
├─ 使用Alpine基础镜像
├─ 合并RUN指令
├─ 使用多阶段构建
├─ 优化构建缓存
├─ 使用.dockerignore
└─ 清理临时文件
容器运行最佳实践:
├─ 设置资源限制
├─ 配置重启策略
├─ 配置健康检查
├─ 管理日志
└─ 使用非root用户
安全最佳实践:
├─ 镜像安全扫描
├─ 使用非root用户
├─ 最小权限原则
├─ 网络隔离
└─ 敏感信息管理
性能优化最佳实践:
├─ 减小镜像大小
├─ 优化构建缓存
├─ 资源优化配置
└─ 网络优化配置
镜像构建检查清单:
✅ 使用Alpine或最小化基础镜像
✅ 使用特定版本标签
✅ 合并RUN指令
✅ 清理缓存和临时文件
✅ 使用多阶段构建
✅ 配置.dockerignore
✅ 设置非root用户
✅ 扫描镜像漏洞
容器运行检查清单:
✅ 设置CPU和内存限制
✅ 配置重启策略
✅ 配置健康检查
✅ 限制日志大小
✅ 使用自定义网络
✅ 不暴露不必要的端口
✅ 使用只读文件系统
✅ 删除不必要的能力
下一章: Docker CI/CD
将学习:
FROM ubuntu:latest
RUN apt-get update
RUN apt-get install -y nodejs
RUN apt-get install -y npm
COPY . /app
CMD ["npm", "start"]
安全配置: 为一个Nginx容器配置安全最佳实践。
资源限制: 为一个应用容器设置合理的资源限制。
多阶段构建: 使用多阶段构建优化一个Go应用的镜像。
健康检查: 为一个Web应用配置健康检查。
日志管理: 配置容器的日志管理策略。
完整最佳实践: 对一个完整的Docker应用应用最佳实践,要求:
最佳实践文档: 编写一份Docker最佳实践文档,包含: