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 核心安全原则
- 最小权限: 只授予必需的权限
- 纵深防御: 多层安全措施
- 持续监控: 实时检测威胁
- 定期更新: 及时修复漏洞
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容器安全指南