06:Docker安全加固与性能优化

06. Docker 安全加固与性能优化

6.1 Docker 安全威胁模型

6.1.1 容器安全威胁

复制代码
┌─────────────────────────────────────────────────────┐
│                 容器安全威胁                          │
├─────────────────────────────────────────────────────┤
│ 1. 恶意镜像                                          │
│    - 包含后门、恶意软件的镜像                          │
│    - 过时的软件包含已知漏洞                            │
│                                                     │
│ 2. 容器逃逸                                          │
│    - 突破容器隔离访问宿主机                            │
│    - 利用内核漏洞                                     │
│                                                     │
│ 3. 权限提升                                          │
│    - 容器以 root 运行                                │
│    - 过度的 capabilities                             │
│                                                     │
│ 4. 敏感数据泄露                                      │
│    - 密码、密钥硬编码在镜像中                          │
│    - 日志中暴露敏感信息                                │
│                                                     │
│ 5. 资源滥用                                          │
│    - 拒绝服务攻击                                     │
│    - 挖矿程序                                        │
└─────────────────────────────────────────────────────┘

6.2 镜像安全

6.2.1 使用可信镜像

dockerfile 复制代码
# 推荐做法 - 使用最小化镜像
FROM python:3.11-alpine
# 或
FROM gcr.io/distroless/python3

镜像来源优先级:

  1. 官方镜像(Docker Official Images)
  2. 验证发布者的镜像(Verified Publisher)
  3. 公司/团队的私有镜像仓库
  4. 社区镜像(谨慎使用)

6.2.2 镜像扫描

使用 Docker Scan:

bash 复制代码
# 扫描本地镜像
docker scan myapp:latest

# 扫描时排除低危漏洞
docker scan --severity high myapp:latest

# 详细输出
docker scan --json myapp:latest

# 扫描 Dockerfile
docker scan --file Dockerfile myapp:latest

使用 Trivy(推荐):

bash 复制代码
# 安装 Trivy
# macOS
brew install trivy

# Linux
wget -qO - https://aquasecurity.github.io/trivy-repo/deb/public.key | sudo apt-key add -
echo "deb https://aquasecurity.github.io/trivy-repo/deb $(lsb_release -sc) main" | sudo tee -a /etc/apt/sources.list.d/trivy.list
sudo apt-get update
sudo apt-get install trivy

# 扫描镜像
trivy image python:3.11

# 只显示严重和高危漏洞
trivy image --severity CRITICAL,HIGH nginx:latest

# 扫描并生成报告
trivy image --format json --output report.json myapp:latest

# 扫描 Dockerfile
trivy config Dockerfile

集成到 CI/CD:

yaml 复制代码
# GitLab CI 示例
scan-image:
  stage: security
  image: aquasec/trivy:latest
  script:
    - trivy image --exit-code 1 --severity CRITICAL $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
  allow_failure: false

6.2.3 最小化镜像

使用多阶段构建:

dockerfile 复制代码
# 构建阶段
FROM golang:1.21 AS builder

WORKDIR /app
COPY go.mod go.sum ./
RUN go mod download

COPY . .
RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o main .

# 运行阶段 - 使用极小镜像
FROM scratch

# 只复制必要文件
COPY --from=builder /app/main /main
COPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/

EXPOSE 8080
ENTRYPOINT ["/main"]

# 结果:从 800MB 减小到 10MB

使用 Distroless 镜像:

dockerfile 复制代码
# Node.js 应用
FROM node:18 AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY . .

FROM gcr.io/distroless/nodejs18-debian11
COPY --from=builder /app /app
WORKDIR /app
CMD ["server.js"]

# 优势:
# - 没有 shell(防止反弹shell攻击)
# - 没有包管理器
# - 极小的攻击面

6.2.4 不在镜像中存储秘密

dockerfile 复制代码
# ❌ 错误做法
FROM node:18
WORKDIR /app
COPY . .

# 危险!密码被写入镜像层
RUN echo "DATABASE_PASSWORD=secret123" > .env
RUN npm install

# ✅ 正确做法 - 使用构建参数(仅构建时可用)
FROM node:18
WORKDIR /app

# ARG 不会保存在最终镜像中
ARG NPM_TOKEN
RUN echo "//registry.npmjs.org/:_authToken=${NPM_TOKEN}" > .npmrc && \
    npm install && \
    rm -f .npmrc  # 立即删除

COPY . .

# ✅ 运行时使用环境变量或 secrets
# docker run -e DATABASE_PASSWORD=secret myapp

使用 Docker Secrets(Swarm/Kubernetes):

bash 复制代码
# 创建 secret
echo "my-secret-password" | docker secret create db_password -

# 在 docker-compose.yml 中使用
services:
  db:
    image: mysql:8.0
    secrets:
      - db_password
    environment:
      MYSQL_ROOT_PASSWORD_FILE: /run/secrets/db_password

secrets:
  db_password:
    external: true

6.3 容器运行时安全

6.3.1 以非 root 用户运行

dockerfile 复制代码
# ✅ 创建并使用非特权用户
FROM python:3.11-slim

# 创建用户
RUN groupadd -r appuser && useradd -r -g appuser appuser

WORKDIR /app

# 以 root 安装依赖
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

# 更改文件所有权
COPY --chown=appuser:appuser . .

# 切换到非 root 用户
USER appuser

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

运行时指定用户:

bash 复制代码
# 使用 UID
docker run --user 1000:1000 myapp

# 使用用户名
docker run --user appuser myapp

# docker-compose.yml
services:
  app:
    image: myapp
    user: "1000:1000"

6.3.2 限制容器 Capabilities

什么是 Capabilities?

  • Linux 将 root 权限细分为多个独立能力
  • Docker 默认授予容器部分 capabilities
  • 应该遵循最小权限原则

查看容器的 capabilities:

bash 复制代码
docker run --rm -it alpine sh -c 'apk add -U libcap; capsh --print'

移除不必要的 capabilities:

bash 复制代码
# 移除所有 capabilities,只添加需要的
docker run --cap-drop=ALL --cap-add=NET_BIND_SERVICE nginx

# docker-compose.yml
services:
  web:
    image: nginx
    cap_drop:
      - ALL
    cap_add:
      - NET_BIND_SERVICE
      - CHOWN

常用 Capabilities:

复制代码
NET_BIND_SERVICE  - 绑定小于 1024 的端口
CHOWN             - 更改文件所有权
DAC_OVERRIDE      - 绕过文件权限检查
SETUID/SETGID     - 设置 UID/GID
SYS_ADMIN         - 执行系统管理任务(危险!避免使用)

6.3.3 使用只读文件系统

bash 复制代码
# 只读根文件系统
docker run --read-only nginx

# 需要写入的目录使用 tmpfs
docker run --read-only --tmpfs /tmp --tmpfs /run nginx

# docker-compose.yml
services:
  app:
    image: myapp
    read_only: true
    tmpfs:
      - /tmp
      - /var/cache

6.3.4 限制系统调用(Seccomp)

默认 Seccomp 配置文件已经很安全,通常不需要修改。

自定义 Seccomp 配置:

json 复制代码
{
  "defaultAction": "SCMP_ACT_ERRNO",
  "architectures": ["SCMP_ARCH_X86_64"],
  "syscalls": [
    {
      "names": ["read", "write", "open", "close", "stat"],
      "action": "SCMP_ACT_ALLOW"
    }
  ]
}
bash 复制代码
# 使用自定义配置
docker run --security-opt seccomp=custom-seccomp.json myapp

# 禁用 seccomp(不推荐)
docker run --security-opt seccomp=unconfined myapp

6.3.5 AppArmor / SELinux

AppArmor(Ubuntu/Debian):

bash 复制代码
# 查看 AppArmor 状态
sudo aa-status

# 使用自定义 AppArmor 配置文件
docker run --security-opt apparmor=docker-default nginx

# 加载自定义配置文件
sudo apparmor_parser -r -W /path/to/profile

SELinux(RHEL/CentOS):

bash 复制代码
# 启用 SELinux
docker run --security-opt label=type:container_t myapp

# 禁用 SELinux(不推荐)
docker run --security-opt label=disable myapp

6.4 网络安全

6.4.1 网络隔离

yaml 复制代码
# docker-compose.yml
version: '3.8'

services:
  # 前端 - 只在前端网络
  web:
    image: nginx
    networks:
      - frontend
    ports:
      - "80:80"

  # API - 连接两个网络
  api:
    image: myapi
    networks:
      - frontend
      - backend

  # 数据库 - 只在后端网络(外部无法访问)
  db:
    image: postgres
    networks:
      - backend
    # 不暴露端口到主机

networks:
  frontend:
    driver: bridge
  backend:
    driver: bridge
    internal: true  # 内部网络,无法访问外网

6.4.2 限制容器间通信

bash 复制代码
# 创建禁止容器间通信的网络
docker network create --driver bridge --opt com.docker.network.bridge.enable_icc=false isolated-network

# 使用该网络
docker run --network isolated-network myapp

6.4.3 使用加密通信

dockerfile 复制代码
# 配置 HTTPS
FROM nginx:alpine

# 复制 SSL 证书
COPY ssl/cert.pem /etc/nginx/ssl/
COPY ssl/key.pem /etc/nginx/ssl/

# NGINX 配置
COPY nginx.conf /etc/nginx/nginx.conf

EXPOSE 443

nginx.conf:

nginx 复制代码
server {
    listen 443 ssl;
    server_name example.com;

    ssl_certificate /etc/nginx/ssl/cert.pem;
    ssl_certificate_key /etc/nginx/ssl/key.pem;

    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers HIGH:!aNULL:!MD5;
    ssl_prefer_server_ciphers on;

    location / {
        proxy_pass http://app:8080;
    }
}

6.5 资源限制

6.5.1 CPU 限制

bash 复制代码
# 限制 CPU 使用率为 50%
docker run --cpus="0.5" myapp

# 限制到特定 CPU 核心
docker run --cpuset-cpus="0,1" myapp

# CPU shares(相对权重,默认 1024)
docker run --cpu-shares=512 myapp

# docker-compose.yml
services:
  app:
    image: myapp
    deploy:
      resources:
        limits:
          cpus: '0.5'
        reservations:
          cpus: '0.25'

6.5.2 内存限制

bash 复制代码
# 限制内存为 512MB
docker run -m 512m myapp

# 内存 + Swap 限制
docker run -m 512m --memory-swap 1g myapp

# 禁用 Swap
docker run -m 512m --memory-swap 512m myapp

# OOM 时不杀死容器(不推荐)
docker run -m 512m --oom-kill-disable myapp

# docker-compose.yml
services:
  app:
    image: myapp
    mem_limit: 512m
    memswap_limit: 1g
    deploy:
      resources:
        limits:
          memory: 512M
        reservations:
          memory: 256M

6.5.3 存储限制

bash 复制代码
# 限制容器可写层大小
docker run --storage-opt size=10G myapp

# 限制 tmpfs 大小
docker run --tmpfs /tmp:rw,size=100m,mode=1777 myapp

6.5.4 进程数限制

bash 复制代码
# 限制容器内最大进程数
docker run --pids-limit 100 myapp

# docker-compose.yml
services:
  app:
    image: myapp
    pids_limit: 100

6.5.5 I/O 限制

bash 复制代码
# 限制读写速率(bytes/second)
docker run --device-read-bps /dev/sda:1mb myapp
docker run --device-write-bps /dev/sda:1mb myapp

# 限制 IOPS
docker run --device-read-iops /dev/sda:1000 myapp
docker run --device-write-iops /dev/sda:1000 myapp

6.6 性能优化

6.6.1 镜像优化

减小镜像体积:

dockerfile 复制代码
# 1. 使用 Alpine 基础镜像
FROM node:18-alpine  # 而不是 node:18

# 2. 合并 RUN 命令
RUN apt-get update && \
    apt-get install -y package1 package2 && \
    apt-get clean && \
    rm -rf /var/lib/apt/lists/*

# 3. 使用 .dockerignore
# .dockerignore:
node_modules
*.log
.git
.env
README.md

# 4. 清理缓存
RUN pip install --no-cache-dir -r requirements.txt
RUN npm ci --only=production && npm cache clean --force

# 5. 多阶段构建
FROM node:18 AS builder
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
RUN npm run build

FROM nginx:alpine
COPY --from=builder /app/build /usr/share/nginx/html

镜像体积对比:

复制代码
ubuntu:latest         77MB
alpine:latest         7MB
scratch              0MB (空镜像)

node:18              1GB
node:18-alpine       170MB

python:3.11          1GB
python:3.11-slim     130MB
python:3.11-alpine   50MB

6.6.2 构建缓存优化

dockerfile 复制代码
# ✅ 好的顺序(依赖先复制)
FROM python:3.11-slim

WORKDIR /app

# 1. 先复制依赖文件(不常变化)
COPY requirements.txt .
RUN pip install -r requirements.txt

# 2. 再复制代码(经常变化)
COPY . .

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

# ❌ 差的顺序
FROM python:3.11-slim
WORKDIR /app
COPY . .  # 代码变化导致后续都要重新构建
RUN pip install -r requirements.txt
CMD ["python", "app.py"]

6.6.3 容器启动优化

dockerfile 复制代码
# 1. 使用 ENTRYPOINT + CMD
ENTRYPOINT ["python"]
CMD ["app.py"]

# 2. 使用 exec 形式(不启动 shell,减少进程)
CMD ["nginx", "-g", "daemon off;"]  # ✅
CMD nginx -g "daemon off;"          # ❌

# 3. 预热应用
RUN python -c "import django; django.setup()"

# 4. 编译 Python 字节码
RUN python -m compileall .

6.6.4 网络性能优化

bash 复制代码
# 使用 host 网络(性能最佳,但失去隔离)
docker run --network host myapp

# 调整 MTU
docker network create --opt com.docker.network.driver.mtu=1450 my-network

# 使用 macvlan(接近原生性能)
docker network create -d macvlan \
  --subnet=192.168.1.0/24 \
  --gateway=192.168.1.1 \
  -o parent=eth0 macvlan-network

6.6.5 存储性能优化

bash 复制代码
# 使用更快的存储驱动
docker info | grep "Storage Driver"

# 对于 Linux,推荐 overlay2
# 编辑 /etc/docker/daemon.json
{
  "storage-driver": "overlay2"
}

# Volume 性能优化
# 1. 使用命名卷而不是绑定挂载
docker run -v my-volume:/data myapp  # ✅ 快
docker run -v /host/path:/data myapp # ❌ 慢

# 2. 使用 tmpfs 存储临时数据
docker run --tmpfs /tmp:rw,size=1g myapp

# 3. 使用 :cached 选项(macOS)
docker run -v /host/path:/data:cached myapp

6.6.6 日志优化

json 复制代码
// /etc/docker/daemon.json
{
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "10m",
    "max-file": "3",
    "compress": "true"
  }
}
yaml 复制代码
# docker-compose.yml
services:
  app:
    image: myapp
    logging:
      driver: "json-file"
      options:
        max-size: "10m"
        max-file: "3"

6.7 监控和审计

6.7.1 资源监控

bash 复制代码
# 实时监控容器资源
docker stats

# 监控特定容器
docker stats container-name

# 格式化输出
docker stats --format "table {{.Container}}\t{{.CPUPerc}}\t{{.MemUsage}}"

# 只显示一次
docker stats --no-stream

6.7.2 事件监控

bash 复制代码
# 实时查看 Docker 事件
docker events

# 过滤特定事件
docker events --filter event=start
docker events --filter container=myapp

# 查看历史事件
docker events --since '2024-01-01T00:00:00' --until '2024-01-02T00:00:00'

6.7.3 审计日志

bash 复制代码
# 启用审计
# 编辑 /etc/audit/rules.d/docker.rules
-w /usr/bin/docker -k docker
-w /var/lib/docker -k docker
-w /etc/docker -k docker
-w /usr/lib/systemd/system/docker.service -k docker
-w /etc/default/docker -k docker

# 重启审计服务
sudo service auditd restart

# 查看审计日志
sudo ausearch -k docker | aureport

6.8 Docker Bench Security

自动化安全检查工具:

bash 复制代码
# 运行 Docker Bench Security
docker run -it --net host --pid host --userns host --cap-add audit_control \
  -e DOCKER_CONTENT_TRUST=$DOCKER_CONTENT_TRUST \
  -v /etc:/etc:ro \
  -v /usr/bin/containerd:/usr/bin/containerd:ro \
  -v /usr/bin/runc:/usr/bin/runc:ro \
  -v /usr/lib/systemd:/usr/lib/systemd:ro \
  -v /var/lib:/var/lib:ro \
  -v /var/run/docker.sock:/var/run/docker.sock:ro \
  --label docker_bench_security \
  docker/docker-bench-security

# 检查项包括:
# - 主机配置
# - Docker daemon 配置
# - Docker daemon 文件权限
# - 容器镜像和构建文件
# - 容器运行时
# - Docker 安全操作
# - Docker Swarm 配置
相关推荐
java_logo2 小时前
ComfyUI Docker 镜像部署指南
运维·docker·容器·comfyui部署·docker部署comfyui·comfyui部署文档·comfyui部署教程
眠りたいです2 小时前
docker-compose:使用docker-compose对多容器应用进行管理并进行wordpress简单站点的搭建
运维·nginx·docker·容器·wordpress·busybox
hgz07102 小时前
Docker
docker
qq_317620312 小时前
05:Docker练习项目
docker·微服务架构·大数据平台·监控系统·devops工具链
oMcLin3 小时前
Ubuntu 22.04 Docker 容器启动失败:解决 Overlay2 存储驱动冲突
java·ubuntu·docker
幺零九零零3 小时前
Windows + Docker + k6 + InfluxDB + Grafana
windows·docker·grafana
宋军涛3 小时前
SqlServer性能优化
运维·服务器·性能优化
qq_317620313 小时前
01:Docker 概述
运维·docker·容器·docker安装
拾荒李3 小时前
性能优化-手搓定高虚拟列表实现
javascript·性能优化