Skip to content

Docker 安全实践

容器安全是生产环境部署的关键考虑因素。本文将详细介绍 Docker 安全的各个方面,包括镜像安全、运行时安全、网络安全和最佳实践。

目录

  1. 安全概述
  2. 镜像安全扫描
  3. 最小权限原则
  4. Secret 管理
  5. 网络安全策略
  6. 运行时安全
  7. 安全加固清单

安全概述

1.1 容器安全层次

Docker 安全层次:
┌─────────────────────────────────────────┐
│  第 7 层: 应用安全                        │
│  - 代码安全、依赖管理                      │
├─────────────────────────────────────────┤
│  第 6 层: 镜像安全                        │
│  - 基础镜像、漏洞扫描                      │
├─────────────────────────────────────────┤
│  第 5 层: 容器运行时安全                   │
│  - 资源限制、权限控制                      │
├─────────────────────────────────────────┤
│  第 4 层: Docker 守护进程安全              │
│  - TLS、访问控制                          │
├─────────────────────────────────────────┤
│  第 3 层: 主机安全                        │
│  - 内核安全、系统加固                      │
├─────────────────────────────────────────┤
│  第 2 层: 网络安全                        │
│  - 网络隔离、防火墙                        │
├─────────────────────────────────────────┤
│  第 1 层: 物理/基础设施安全                │
│  - 数据中心、硬件安全                      │
└─────────────────────────────────────────┘

1.2 安全威胁模型

威胁类型描述防护措施
镜像漏洞基础镜像或依赖存在 CVE定期扫描、使用最小镜像
权限提升容器逃逸获取主机权限非 root 用户、安全选项
数据泄露敏感信息泄露Secrets 管理、加密
网络攻击未授权访问、中间人攻击网络隔离、TLS
资源耗尽DoS 攻击资源限制、监控

镜像安全扫描

2.1 使用 Docker Scout

Docker Scout 是 Docker 官方提供的镜像安全扫描工具。

bash
# 启用 Docker Scout
docker scout enroll

# 扫描镜像
docker scout cves myimage:latest

# 生成详细报告
docker scout cves --format sarif --output report.sarif myimage:latest

# 比较两个镜像
docker scout compare myimage:old myimage:new

# 查看快速概览
docker scout quickview myimage:latest

2.2 使用 Trivy

Trivy 是一个全面的安全扫描器,支持容器镜像、文件系统等。

bash
# 安装 Trivy
# macOS
brew install trivy

# Linux
curl -sfL https://raw.githubusercontent.com/aquasecurity/trivy/main/contrib/install.sh | sh

# 扫描镜像
trivy image myimage:latest

# 扫描特定严重程度
trivy image --severity HIGH,CRITICAL myimage:latest

# 输出 JSON 格式
trivy image --format json --output report.json myimage:latest

# 扫描镜像文件系统
trivy filesystem /path/to/project

# 扫描 Dockerfile
trivy config Dockerfile

2.3 使用 Snyk

bash
# 安装 Snyk CLI
npm install -g snyk

# 登录 Snyk
snyk auth

# 扫描 Docker 镜像
snyk container test myimage:latest

# 监控镜像
snyk container monitor myimage:latest

# 生成 SBOM
snyk container sbom --format=cyclonedx1.4+json myimage:latest

2.4 集成到 CI/CD

yaml
# GitHub Actions 示例
name: Security Scan
on: [push, pull_request]

jobs:
  scan:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      
      - name: Build image
        run: docker build -t myapp:${{ github.sha }} .
      
      - name: Run Trivy vulnerability scanner
        uses: aquasecurity/trivy-action@master
        with:
          image-ref: 'myapp:${{ github.sha }}'
          format: 'sarif'
          output: 'trivy-results.sarif'
      
      - name: Upload scan results
        uses: github/codeql-action/upload-sarif@v2
        with:
          sarif_file: 'trivy-results.sarif'

2.5 镜像安全最佳实践

dockerfile
# 1. 使用官方基础镜像
FROM python:3.11-slim-bookworm

# 2. 使用特定版本标签
FROM node:18.17.1-alpine3.18

# 3. 使用最小化基础镜像
FROM python:3.11-alpine
# 或
FROM gcr.io/distroless/python3

# 4. 定期更新基础镜像
# 在 CI/CD 中设置定期重建

# 5. 多阶段构建减少攻击面
FROM node:18-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build

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

最小权限原则

3.1 使用非 Root 用户

dockerfile
# 方法 1: 使用现有用户
FROM node:18-alpine
USER node
WORKDIR /app
COPY --chown=node:node . .
CMD ["node", "server.js"]

# 方法 2: 创建专用用户
FROM python:3.11-slim
RUN groupadd --gid 1000 appgroup && \
    useradd --uid 1000 --gid appgroup --shell /bin/false appuser
WORKDIR /app
COPY --chown=appuser:appgroup . .
USER appuser
CMD ["python", "app.py"]

# 方法 3: Alpine 创建用户
FROM alpine:3.18
RUN addgroup -g 1000 -S appgroup && \
    adduser -u 1000 -S appuser -G appgroup
WORKDIR /app
COPY --chown=appuser:appgroup . .
USER appuser
CMD ["./myapp"]

3.2 文件权限控制

dockerfile
FROM python:3.11-slim

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

WORKDIR /app

# 复制文件并设置权限
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

COPY . .

# 设置安全的文件权限
RUN chmod -R 755 /app && \
    find /app -type f -exec chmod 644 {} \; && \
    chmod 755 /app/entrypoint.sh && \
    chown -R appuser:appgroup /app

# 移除不必要的权限
RUN chmod -R -w /app/static && \
    chmod -R -w /app/templates

USER appuser

# 使用只读根文件系统运行(运行时参数)
# docker run --read-only ...

3.3 能力(Capabilities)管理

bash
# 查看容器能力
docker run --rm alpine sh -c 'apk add libcap && capsh --print'

# 删除所有能力,只添加必要的
docker run --rm \
  --cap-drop ALL \
  --cap-add NET_BIND_SERVICE \
  nginx:alpine

# 常用能力需求:
# - NET_BIND_SERVICE: 绑定特权端口 (<1024)
# - CHOWN: 更改文件所有者
# - SETGID/SETUID: 切换用户组/用户
# - SYS_TIME: 修改系统时间

3.4 Seccomp 配置

bash
# 使用默认 Seccomp 配置(推荐)
docker run --rm alpine

# 使用自定义 Seccomp 配置
docker run --rm \
  --security-opt seccomp=/path/to/seccomp-profile.json \
  myapp:latest

# 禁用 Seccomp(不推荐)
docker run --rm \
  --security-opt seccomp=unconfined \
  myapp:latest

自定义 Seccomp 配置示例:

json
{
  "defaultAction": "SCMP_ACT_ERRNO",
  "architectures": ["SCMP_ARCH_X86_64", "SCMP_ARCH_X86"],
  "syscalls": [
    {
      "names": [
        "accept",
        "accept4",
        "bind",
        "clone",
        "close",
        "connect",
        "execve",
        "exit",
        "exit_group",
        "fcntl",
        "fstat",
        "futex",
        "getpid",
        "getrandom",
        "listen",
        "mmap",
        "mprotect",
        "munmap",
        "openat",
        "read",
        "recvfrom",
        "recvmsg",
        "sendmsg",
        "sendto",
        "socket",
        "write"
      ],
      "action": "SCMP_ACT_ALLOW"
    }
  ]
}

Secret 管理

4.1 Docker Secrets(Swarm 模式)

bash
# 创建 secret
echo "my-secret-password" | docker secret create db_password -

# 从文件创建
docker secret create tls_cert cert.pem

# 查看 secrets
docker secret ls

# 在服务中使用 secret
docker service create \
  --name myapp \
  --secret db_password \
  --secret tls_cert \
  myimage:latest

# secret 在容器中的位置:/run/secrets/<secret_name>

4.2 Docker Compose Secrets

yaml
version: '3.8'
services:
  web:
    image: myapp:latest
    secrets:
      - db_password
      - api_key
    environment:
      DB_PASSWORD_FILE: /run/secrets/db_password
      API_KEY_FILE: /run/secrets/api_key

  db:
    image: postgres:15-alpine
    secrets:
      - db_password
    environment:
      POSTGRES_PASSWORD_FILE: /run/secrets/db_password

secrets:
  db_password:
    file: ./secrets/db_password.txt
  api_key:
    file: ./secrets/api_key.txt

4.3 使用环境变量(开发环境)

bash
# ❌ 不安全:直接在命令行传递
docker run -e PASSWORD=secret123 myapp

# ✅ 安全:从文件读取
docker run --env-file .env myapp

# ✅ 安全:使用 --env-file
# .env 文件内容:
# PASSWORD_FILE=/run/secrets/password

4.4 使用外部 Secret 管理工具

bash
# 使用 HashiCorp Vault
docker run --rm \
  -v $(pwd)/vault-config:/vault/config \
  -e VAULT_ADDR=http://vault:8200 \
  vault:latest \
  vault kv get secret/myapp/db_password

# 使用 AWS Secrets Manager
docker run --rm \
  -e AWS_REGION=us-east-1 \
  -v ~/.aws:/root/.aws:ro \
  amazon/aws-cli \
  secretsmanager get-secret-value --secret-id myapp/db_password

网络安全策略

5.1 网络隔离

bash
# 创建内部网络(无外部访问)
docker network create --internal internal-network

# 创建加密网络
docker network create \
  --driver overlay \
  --opt encrypted \
  secure-network

# 禁用容器间通信
docker network create \
  --opt com.docker.network.bridge.enable_icc=false \
  isolated-network

5.2 防火墙规则

bash
# 查看 Docker 创建的 iptables 规则
iptables -L DOCKER -n -v
iptables -L DOCKER-ISOLATION-STAGE-1 -n -v

# 自定义防火墙规则
# 限制容器访问特定 IP
iptables -I DOCKER-USER -i docker0 -d 192.168.1.100 -j DROP

# 限制容器出站连接
iptables -I DOCKER-USER -i docker0 -p tcp --dport 3306 -j DROP

5.3 TLS 加密

bash
# 生成 CA 证书
openssl genrsa -out ca-key.pem 4096
openssl req -new -x509 -days 365 -key ca-key.pem -out ca.pem

# 生成服务器证书
openssl genrsa -out server-key.pem 4096
openssl req -subj "/CN=docker-server" -new -key server-key.pem -out server.csr
openssl x509 -req -days 365 -in server.csr -CA ca.pem -CAkey ca-key.pem \
  -out server-cert.pem

# 配置 Docker 守护进程使用 TLS
# /etc/docker/daemon.json
{
  "tls": true,
  "tlscacert": "/etc/docker/ca.pem",
  "tlscert": "/etc/docker/server-cert.pem",
  "tlskey": "/etc/docker/server-key.pem",
  "tlsverify": true
}

5.4 服务网格安全

yaml
# Docker Compose + Istio 示例
version: '3.8'
services:
  istio-proxy:
    image: istio/proxyv2:1.18.0
    volumes:
      - ./istio-config:/etc/istio/config
    command:
      - proxy
      - sidecar
      - --configPath
      - /etc/istio/config
    network_mode: service:app
  
  app:
    image: myapp:latest
    environment:
      - SERVICE_MESH_ENABLED=true

运行时安全

6.1 资源限制

bash
# 内存限制
docker run -d \
  --memory="512m" \
  --memory-swap="1g" \
  --memory-reservation="256m" \
  myapp:latest

# CPU 限制
docker run -d \
  --cpus="1.5" \
  --cpu-shares=512 \
  --cpuset-cpus="0,1" \
  myapp:latest

# 进程数限制
docker run -d \
  --pids-limit=100 \
  myapp:latest

# 存储限制
docker run -d \
  --storage-opt size=10G \
  myapp:latest

6.2 只读文件系统

bash
# 使用只读根文件系统
docker run -d \
  --read-only \
  --tmpfs /tmp:noexec,nosuid,size=100m \
  --tmpfs /var/cache:size=10m \
  myapp:latest

# Docker Compose 配置
version: '3.8'
services:
  app:
    image: myapp:latest
    read_only: true
    tmpfs:
      - /tmp:noexec,nosuid,size=100m
      - /var/cache:size=10m
      - /app/tmp:size=50m

6.3 安全选项

bash
# 禁用特权模式(默认)
docker run -d --privileged=false myapp:latest

# 不添加新权限
docker run -d \
  --security-opt no-new-privileges:true \
  myapp:latest

# 使用 AppArmor 配置
docker run -d \
  --security-opt apparmor=docker-default \
  myapp:latest

# 使用自定义 AppArmor
docker run -d \
  --security-opt apparmor=myapp-profile \
  myapp:latest

6.4 日志和审计

bash
# 配置日志驱动
{
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "10m",
    "max-file": "3",
    "labels": "production_status",
    "env": "OS_VERSION"
  }
}

# 启用审计日志
auditctl -w /etc/docker/ -k docker
auditctl -w /var/lib/docker/ -k docker
auditctl -w /var/run/docker.sock -k docker

安全加固清单

7.1 主机安全

  • [ ] 使用最新的稳定内核
  • [ ] 启用 SELinux/AppArmor
  • [ ] 配置防火墙规则
  • [ ] 禁用不必要的服务
  • [ ] 定期更新系统补丁
  • [ ] 配置日志监控和告警
  • [ ] 使用专用 Docker 主机

7.2 Docker 守护进程安全

  • [ ] 启用 TLS 加密通信
  • [ ] 配置用户命名空间
  • [ ] 限制默认 ulimit
  • [ ] 启用日志轮转
  • [ ] 配置资源配额
  • [ ] 禁用实验性功能(生产环境)

7.3 镜像安全

  • [ ] 使用官方基础镜像
  • [ ] 定期扫描镜像漏洞
  • [ ] 使用最小化基础镜像
  • [ ] 多阶段构建减少攻击面
  • [ ] 固定镜像版本标签
  • [ ] 签名和验证镜像
  • [ ] 定期更新依赖

7.4 容器运行时安全

  • [ ] 使用非 root 用户
  • [ ] 启用只读根文件系统
  • [ ] 删除不必要的 capabilities
  • [ ] 配置资源限制
  • [ ] 使用 Seccomp 配置
  • [ ] 配置健康检查
  • [ ] 限制进程数

7.5 网络安全

  • [ ] 使用自定义网络
  • [ ] 限制端口暴露
  • [ ] 配置网络策略
  • [ ] 启用网络加密
  • [ ] 禁用 ICC(如不需要)
  • [ ] 配置 TLS 证书

7.6 数据安全

  • [ ] 使用 Docker Secrets
  • [ ] 加密敏感数据
  • [ ] 定期备份数据
  • [ ] 配置数据保留策略
  • [ ] 使用只读挂载配置文件

安全工具推荐

工具用途推荐场景
Docker Scout镜像扫描开发/CI
Trivy综合扫描CI/CD
Snyk漏洞管理企业环境
Falco运行时安全生产监控
Sysdig容器安全企业监控
Twistlock完整安全平台企业级
Aqua Security容器安全企业级

下一步

基于 MIT 许可发布