第25章 Docker安全

25.1 Docker安全概述

25.1.1 容器安全威胁

主要安全风险:

  • 不安全的镜像(恶意代码、漏洞)
  • 容器逃逸(突破隔离访问宿主机)
  • 权限过高(root权限运行)
  • 敏感数据泄露(配置、密码)
  • 网络攻击(未授权访问)

25.1.2 Docker安全架构

Docker安全依赖多层防护:

  • 命名空间隔离: PID、NET、MNT、UTS、IPC
  • Cgroups资源限制: 防止资源耗尽攻击
  • Capabilities: 细粒度权限控制
  • AppArmor/SELinux: 强制访问控制
  • Seccomp: 系统调用过滤

25.2 镜像安全

25.2.1 使用官方和验证镜像

bash 复制代码
# 使用官方镜像
docker pull nginx:alpine

# 使用Docker官方认证镜像
docker pull postgres:15  # OFFICIAL IMAGE标识

# 启用内容信任(Content Trust)
export DOCKER_CONTENT_TRUST=1
docker pull nginx:alpine  # 自动验证签名

# 验证镜像摘要
docker pull nginx@sha256:abc123...

25.2.2 镜像漏洞扫描

使用Trivy扫描:

bash 复制代码
# 安装Trivy
sudo apt install trivy

# 扫描本地镜像
trivy image nginx:alpine

# 扫描并显示高危漏洞
trivy image --severity HIGH,CRITICAL nginx:alpine

# 输出JSON格式报告
trivy image -f json -o report.json myapp:latest

# 在CI/CD中使用
trivy image --exit-code 1 --severity CRITICAL myapp:latest

使用Docker Scout(新工具):

bash 复制代码
# 启用Docker Scout
docker scout quickview nginx:alpine

# 详细CVE报告
docker scout cves nginx:alpine

# 比较镜像漏洞
docker scout compare --to nginx:alpine nginx:latest

25.2.3 最小化镜像

dockerfile 复制代码
# 不安全: 使用完整OS镜像
FROM ubuntu:22.04
RUN apt-get update && apt-get install -y python3
COPY app.py /app/
CMD ["python3", "/app/app.py"]

# 安全: 使用精简镜像
FROM python:3.11-alpine
COPY app.py /app/
CMD ["python3", "/app/app.py"]

# 最佳: Distroless镜像(无shell、包管理器)
FROM gcr.io/distroless/python3
COPY app.py /app/
CMD ["/app/app.py"]

# 多阶段构建去除构建工具
FROM golang:1.21 AS builder
WORKDIR /app
COPY . .
RUN go build -o myapp

FROM gcr.io/distroless/base
COPY --from=builder /app/myapp /
CMD ["/myapp"]

25.3 运行时安全

25.3.1 非root用户运行

dockerfile 复制代码
# Dockerfile中创建非root用户
FROM nginx:alpine

# 创建用户和组
RUN addgroup -g 1001 appgroup && \
    adduser -D -u 1001 -G appgroup appuser

# 修改文件权限
RUN chown -R appuser:appgroup /var/cache/nginx /var/run /var/log/nginx

# 切换到非root用户
USER appuser

EXPOSE 8080
CMD ["nginx", "-g", "daemon off;"]

运行时指定用户:

bash 复制代码
# 使用--user指定UID:GID
docker run -d --user 1001:1001 nginx:alpine

# 使用用户名(容器内必须存在)
docker run -d --user appuser nginx:alpine

# 禁止root用户(Docker 20.10+)
docker run -d --user 1001 --security-opt=no-new-privileges nginx

25.3.2 Capabilities管理

bash 复制代码
# 查看默认capabilities
docker run --rm alpine sh -c 'apk add libcap && capsh --print'

# 移除所有capabilities,仅添加必需的
docker run -d \
  --cap-drop=ALL \
  --cap-add=NET_BIND_SERVICE \
  --cap-add=CHOWN \
  nginx:alpine

# 危险: 添加特权capabilities
# 避免使用--cap-add=SYS_ADMIN, SYS_PTRACE等

常用Capabilities说明:

Capability 作用 风险级别
NET_BIND_SERVICE 绑定<1024端口
CHOWN 修改文件所有者
DAC_OVERRIDE 绕过文件权限检查
SYS_ADMIN 系统管理(挂载等)
SYS_PTRACE 调试其他进程

25.3.3 只读文件系统

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

# 只读+临时目录可写
docker run -d \
  --read-only \
  --tmpfs /tmp \
  --tmpfs /var/cache/nginx \
  nginx:alpine

# Compose配置
services:
  app:
    image: myapp:latest
    read_only: true
    tmpfs:
      - /tmp
      - /var/run

25.3.4 Seccomp配置

bash 复制代码
# 使用默认seccomp配置(推荐)
docker run -d nginx:alpine

# 禁用seccomp(不安全,仅调试)
docker run -d --security-opt seccomp=unconfined nginx

# 自定义seccomp配置
docker run -d --security-opt seccomp=/path/to/profile.json nginx

自定义Seccomp配置示例:

json 复制代码
{
  "defaultAction": "SCMP_ACT_ERRNO",
  "architectures": ["SCMP_ARCH_X86_64"],
  "syscalls": [
    {
      "names": ["read", "write", "open", "close", "stat"],
      "action": "SCMP_ACT_ALLOW"
    },
    {
      "names": ["chmod", "chown"],
      "action": "SCMP_ACT_ALLOW"
    }
  ]
}

25.4 敏感数据管理

25.4.1 Docker Secrets

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

# 从文件创建
docker secret create db_cert ./database.crt

# 查看secrets
docker secret ls

# 在Swarm服务中使用
docker service create \
  --name postgres \
  --secret db_password \
  -e POSTGRES_PASSWORD_FILE=/run/secrets/db_password \
  postgres:15

# Compose配置(仅Swarm模式)
version: '3.8'
services:
  db:
    image: postgres:15
    secrets:
      - db_password
    environment:
      POSTGRES_PASSWORD_FILE: /run/secrets/db_password

secrets:
  db_password:
    external: true

25.4.2 环境变量最佳实践

bash 复制代码
# 不安全: 命令行传递(可通过ps看到)
docker run -e DB_PASSWORD=secret123 myapp

# 较好: 使用.env文件
docker run --env-file .env myapp

# .env文件内容
# DB_PASSWORD=secret123
# API_KEY=xyz789

# 最佳: 使用secrets或外部密钥管理
docker run -e DB_PASSWORD_FILE=/run/secrets/db_pass myapp

# 避免在镜像中硬编码
# 错误做法:
# ENV DB_PASSWORD=hardcoded_secret

25.4.3 使用HashiCorp Vault

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

services:
  vault:
    image: vault:latest
    ports:
      - "8200:8200"
    environment:
      VAULT_DEV_ROOT_TOKEN_ID: myroot
      VAULT_DEV_LISTEN_ADDRESS: 0.0.0.0:8200
    cap_add:
      - IPC_LOCK

  app:
    image: myapp:latest
    environment:
      VAULT_ADDR: http://vault:8200
      VAULT_TOKEN: myroot
    depends_on:
      - vault

25.5 网络安全

25.5.1 网络隔离

bash 复制代码
# 创建隔离网络
docker network create --internal backend

# 前端网络(可访问外网)
docker network create frontend

# 数据库只连接内部网络
docker run -d --name db --network backend postgres:15

# 应用连接两个网络
docker run -d --name app \
  --network frontend \
  myapp:latest

docker network connect backend app

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

25.5.2 限制端口暴露

bash 复制代码
# 仅绑定localhost(不对外暴露)
docker run -d -p 127.0.0.1:5432:5432 postgres:15

# 使用防火墙规则
sudo iptables -I DOCKER-USER -i eth0 -p tcp --dport 5432 -j DROP
sudo iptables -I DOCKER-USER -s 10.0.1.0/24 -j ACCEPT

25.6 AppArmor与SELinux

25.6.1 AppArmor配置

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

# 使用默认Docker配置
docker run -d nginx:alpine

# 自定义AppArmor配置
docker run -d \
  --security-opt apparmor=docker-nginx \
  nginx:alpine

# 禁用AppArmor(不推荐)
docker run -d --security-opt apparmor=unconfined nginx

自定义AppArmor配置文件:

bash 复制代码
# /etc/apparmor.d/docker-nginx
#include <tunables/global>

profile docker-nginx flags=(attach_disconnected,mediate_deleted) {
  #include <abstractions/base>
  
  network inet tcp,
  network inet udp,
  
  /usr/sbin/nginx mr,
  /etc/nginx/** r,
  /var/log/nginx/* w,
  
  deny /proc/sys/** w,
  deny /sys/** w,
}

25.6.2 SELinux配置

bash 复制代码
# 检查SELinux状态
getenforce

# 启用SELinux标签
docker run -d --security-opt label=type:svirt_apache_t nginx

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

# 设置Volume的SELinux标签
docker run -d -v /data:/data:z nginx  # 私有标签
docker run -d -v /data:/data:Z nginx  # 共享标签

25.7 Rootless Docker

25.7.1 安装Rootless模式

bash 复制代码
# 安装依赖
sudo apt install -y uidmap dbus-user-session

# 以非root用户安装
curl -fsSL https://get.docker.com/rootless | sh

# 设置环境变量
export PATH=$HOME/bin:$PATH
export DOCKER_HOST=unix://$XDG_RUNTIME_DIR/docker.sock

# 添加到.bashrc
echo 'export PATH=$HOME/bin:$PATH' >> ~/.bashrc
echo 'export DOCKER_HOST=unix://$XDG_RUNTIME_DIR/docker.sock' >> ~/.bashrc

# 启动Docker守护进程
systemctl --user start docker

# 设置开机自启
systemctl --user enable docker
sudo loginctl enable-linger $(whoami)

25.7.2 Rootless限制

功能限制:

  • 不支持cgroups v1
  • 不支持AppArmor、SELinux
  • 端口<1024需要特殊配置
  • 性能略低于root模式

端口映射配置:

bash 复制代码
# 允许非root用户绑定低端口
sudo sh -c "echo 'net.ipv4.ip_unprivileged_port_start=80' > /etc/sysctl.d/99-rootless.conf"
sudo sysctl --system

# 现在可以绑定80端口
docker run -d -p 80:80 nginx:alpine

25.8 安全扫描与审计

25.8.1 持续安全扫描

bash 复制代码
#!/bin/bash
# security-scan.sh - 定期扫描镜像

IMAGES=$(docker images --format "{{.Repository}}:{{.Tag}}" | grep -v '<none>')

for image in $IMAGES; do
  echo "=== 扫描: $image ==="
  trivy image --severity HIGH,CRITICAL $image
  
  if [ $? -ne 0 ]; then
    echo "警告: $image 存在高危漏洞"
    # 发送告警通知
  fi
done

25.8.2 Docker Bench Security

bash 复制代码
# 运行Docker安全基准测试
docker run -it --rm \
  --net host \
  --pid host \
  --userns host \
  --cap-add audit_control \
  -v /var/lib:/var/lib \
  -v /var/run/docker.sock:/var/run/docker.sock \
  -v /etc:/etc \
  docker/docker-bench-security

# 输出包括:
# - 主机配置检查
# - Docker守护进程配置
# - 容器镜像和构建文件
# - 容器运行时检查
# - Docker安全操作

25.8.3 审计日志

bash 复制代码
# 启用Docker审计日志
sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<EOF
{
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "10m",
    "max-file": "3"
  }
}
EOF

sudo systemctl restart docker

# 使用auditd监控Docker事件
sudo auditctl -w /usr/bin/docker -k docker
sudo auditctl -w /var/lib/docker -k docker
sudo auditctl -w /etc/docker -k docker

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

25.9 安全配置实战

25.9.1 安全的Web应用部署

yaml 复制代码
# secure-webapp.yml
version: '3.8'

services:
  nginx:
    image: nginx:alpine
    read_only: true
    cap_drop:
      - ALL
    cap_add:
      - NET_BIND_SERVICE
      - CHOWN
    security_opt:
      - no-new-privileges:true
    tmpfs:
      - /var/cache/nginx
      - /var/run
    ports:
      - "127.0.0.1:80:8080"
    user: "1001:1001"
    networks:
      - frontend

  app:
    image: myapp:latest
    read_only: true
    cap_drop:
      - ALL
    security_opt:
      - no-new-privileges:true
    tmpfs:
      - /tmp
    user: "1001:1001"
    networks:
      - frontend
      - backend
    environment:
      DB_HOST: postgres
      DB_PASSWORD_FILE: /run/secrets/db_password
    secrets:
      - db_password

  postgres:
    image: postgres:15-alpine
    cap_drop:
      - ALL
    cap_add:
      - CHOWN
      - DAC_OVERRIDE
      - SETGID
      - SETUID
    security_opt:
      - no-new-privileges:true
    user: "999:999"
    networks:
      - backend
    volumes:
      - postgres-data:/var/lib/postgresql/data
    environment:
      POSTGRES_PASSWORD_FILE: /run/secrets/db_password
    secrets:
      - db_password

networks:
  frontend:
  backend:
    internal: true

volumes:
  postgres-data:

secrets:
  db_password:
    external: true

25.9.2 ROCm GPU安全配置

yaml 复制代码
# rocm-secure.yml
version: '3.8'

services:
  rocm-training:
    image: rocm/pytorch:latest
    
    # 用户权限
    user: "1001:1001"
    group_add:
      - video  # GPU访问组
    
    # 资源限制
    deploy:
      resources:
        limits:
          cpus: '8.0'
          memory: 16G
    
    # 安全选项
    cap_drop:
      - ALL
    cap_add:
      - DAC_OVERRIDE  # GPU设备访问
    security_opt:
      - no-new-privileges:true
      - seccomp=unconfined  # ROCm需要
    
    # GPU设备(只读)
    devices:
      - /dev/kfd
      - /dev/dri/renderD128
    
    # 只读根文件系统
    read_only: true
    tmpfs:
      - /tmp
      - /root/.cache
    
    # 工作目录挂载
    volumes:
      - ./workspace:/workspace
      - ./models:/models:ro  # 模型只读
    
    # 网络隔离
    networks:
      - isolated
    
    environment:
      ROCR_VISIBLE_DEVICES: "0"

networks:
  isolated:
    internal: true

25.10 安全最佳实践清单

25.10.1 镜像安全

  • 使用官方或验证过的基础镜像
  • 定期扫描镜像漏洞(Trivy/Clair)
  • 使用多阶段构建减少镜像体积
  • 不在镜像中包含敏感信息
  • 使用.dockerignore排除敏感文件
  • 启用Docker Content Trust

25.10.2 运行时安全

  • 使用非root用户运行容器
  • 移除不必要的capabilities
  • 启用只读根文件系统
  • 使用--security-opt no-new-privileges
  • 限制容器资源使用
  • 启用AppArmor/SELinux

25.10.3 数据安全

  • 使用Docker Secrets管理敏感数据
  • 避免在环境变量中存储密码
  • 加密敏感数据卷
  • 定期备份并测试恢复
  • 使用外部密钥管理系统(Vault)

25.10.4 网络安全

  • 使用自定义网络隔离容器
  • 限制端口暴露范围
  • 配置防火墙规则
  • 禁用不必要的容器间通信
  • 使用TLS加密通信

25.10.5 监控与审计

  • 启用Docker审计日志
  • 定期运行Docker Bench Security
  • 监控容器异常行为
  • 配置安全告警
  • 定期审查安全配置

25.11 总结

25.11.1 核心安全原则

  1. 最小权限: 只授予必需的权限
  2. 纵深防御: 多层安全措施
  3. 持续监控: 实时检测威胁
  4. 定期更新: 及时修复漏洞

25.11.2 安全配置模板

bash 复制代码
# 安全容器运行模板
docker run -d \
  --name secure-app \
  --user 1001:1001 \
  --read-only \
  --tmpfs /tmp \
  --cap-drop=ALL \
  --cap-add=NET_BIND_SERVICE \
  --security-opt=no-new-privileges:true \
  --security-opt=apparmor=docker-default \
  -m 512m \
  --cpus=1.0 \
  --network isolated \
  -p 127.0.0.1:8080:8080 \
  myapp:latest

扩展资源:

  • CIS Docker Benchmark
  • OWASP Docker Security Cheat Sheet
  • Docker官方安全最佳实践
  • NIST容器安全指南
相关推荐
智算菩萨2 小时前
AI 安全前沿:从对抗攻击到大模型越狱与防御
人工智能·安全
小润nature2 小时前
openclaw的安全和tokens消耗探讨,我们是否真的需要它?
安全
大模型发展与战略研究中心2 小时前
安全顶刊 | InstPro: 基于指令执行追踪和溯源的CPU漏洞利用攻击检测和调查
网络·安全
yaoxin5211232 小时前
329. Java Stream API - 打开 Optional 的正确方式:如何安全提取值?
java·安全·rpc
努力搬砖的咸鱼2 小时前
用 Ingress 统一管理多个微服务的入口
微服务·云原生·容器·架构·kubernetes
IT研究所11 小时前
IT 资产管理 (ITAM) 与 ITSM 协同实践:构建从资产到服务的闭环管理体系
大数据·运维·人工智能·科技·安全·低代码·自动化
莫比乌斯之梦12 小时前
使用 Docker 运行 Jenkins:快速搭建高效 CI/CD 环境指南
ci/cd·docker·jenkins
程序设计实验室13 小时前
从挖矿木马入侵到 Docker Rootless 加固,我的服务器安全复盘
linux·docker
only_Klein14 小时前
Kubernetes发布策略之蓝绿发布与金丝雀发布
云原生·容器·kubernetes