<返回目录 Powered by claude/xia兄
第13课: 安全实践
Docker安全威胁
- 容器逃逸:攻击者从容器突破到主机
- 镜像漏洞:使用含有漏洞的基础镜像
- 权限提升:容器以root用户运行
- 敏感信息泄露:密码、密钥硬编码
- 网络攻击:容器间未隔离
使用非root用户
# Dockerfile中创建并使用非root用户
FROM python:3.9-slim
# 创建应用用户
RUN useradd -m -u 1000 appuser && \
mkdir -p /app && \
chown -R appuser:appuser /app
WORKDIR /app
# 以root安装依赖
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
# 切换到非root用户
USER appuser
# 复制应用代码
COPY --chown=appuser:appuser . .
EXPOSE 8000
CMD ["python", "app.py"]
为什么使用非root用户?
- 限制容器内的权限,减少攻击面
- 防止容器逃逸后获得主机root权限
- 符合最小权限原则
镜像扫描
# 使用Docker Scout扫描镜像
docker scout cves myapp:latest
# 使用Trivy扫描镜像
docker run --rm \
-v /var/run/docker.sock:/var/run/docker.sock \
aquasec/trivy image myapp:latest
# 扫描并输出报告
trivy image --severity HIGH,CRITICAL myapp:latest
# 扫描Dockerfile
trivy config Dockerfile
# 使用Clair扫描
docker run -d --name clair-db postgres
docker run -d --name clair --link clair-db:postgres arminc/clair-local-scan
签名和验证镜像
# 启用Docker Content Trust
export DOCKER_CONTENT_TRUST=1
# 推送签名镜像
docker push myregistry.com/myapp:latest
# 拉取时自动验证签名
docker pull myregistry.com/myapp:latest
# 使用Notary签名
notary init myregistry.com/myapp
notary publish myregistry.com/myapp
限制容器能力
# 删除所有能力
docker run --cap-drop=ALL nginx
# 只添加需要的能力
docker run --cap-drop=ALL --cap-add=NET_BIND_SERVICE nginx
# 常用能力
# NET_BIND_SERVICE: 绑定1024以下端口
# CHOWN: 修改文件所有者
# DAC_OVERRIDE: 绕过文件权限检查
# SETUID/SETGID: 设置用户/组ID
# 以只读方式运行容器
docker run --read-only nginx
# 只读根文件系统,挂载临时目录
docker run --read-only --tmpfs /tmp nginx
使用安全计算模式(Seccomp)
# 使用默认seccomp配置
docker run --security-opt seccomp=default.json nginx
# 禁用seccomp(不推荐)
docker run --security-opt seccomp=unconfined nginx
# 自定义seccomp配置
{
"defaultAction": "SCMP_ACT_ERRNO",
"architectures": ["SCMP_ARCH_X86_64"],
"syscalls": [
{
"names": ["read", "write", "open", "close"],
"action": "SCMP_ACT_ALLOW"
}
]
}
docker run --security-opt seccomp=custom-seccomp.json nginx
AppArmor和SELinux
# 使用AppArmor配置
docker run --security-opt apparmor=docker-default nginx
# 使用SELinux标签
docker run --security-opt label=level:s0:c100,c200 nginx
# 禁用SELinux(不推荐)
docker run --security-opt label=disable nginx
敏感信息管理
# 使用Docker Secrets(Swarm模式)
echo "mysecretpassword" | docker secret create db_password -
# 在服务中使用secret
docker service create \
--name mysql \
--secret db_password \
-e MYSQL_ROOT_PASSWORD_FILE=/run/secrets/db_password \
mysql
# 使用环境变量文件
# .env文件
DB_PASSWORD=secret123
API_KEY=abc123
# docker-compose.yml
version: '3.8'
services:
app:
image: myapp
env_file:
- .env
# 使用外部密钥管理
# HashiCorp Vault, AWS Secrets Manager等
网络安全
# 创建隔离网络
docker network create --internal backend
# 容器只能访问内部网络
docker run -d --network backend mysql
# 使用防火墙规则
iptables -A DOCKER-USER -i ext_if ! -s 192.168.1.0/24 -j DROP
# 禁用容器间通信
docker network create --driver bridge --opt com.docker.network.bridge.enable_icc=false isolated
# 限制容器访问主机
docker run --add-host=host.docker.internal:127.0.0.1 myapp
资源隔离
# 使用cgroup限制资源
docker run -d \
--memory="512m" \
--cpus="1" \
--pids-limit=100 \
nginx
# 禁用OOM杀死(需谨慎)
docker run -d --memory="512m" --oom-kill-disable nginx
# 使用namespace隔离
docker run -d --userns-remap=default nginx
审计和日志
# 启用Docker审计
# /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/docker/daemon.json -k docker
# 重启auditd
systemctl restart auditd
# 查看审计日志
ausearch -k docker
# 配置日志驱动
docker run -d \
--log-driver syslog \
--log-opt syslog-address=tcp://192.168.1.100:514 \
nginx
镜像安全最佳实践
# 安全的Dockerfile示例
FROM python:3.9-slim AS builder
# 使用特定版本而不是latest
FROM python:3.9.18-slim
# 更新系统包
RUN apt-get update && \
apt-get upgrade -y && \
apt-get install -y --no-install-recommends \
gcc \
libc-dev && \
apt-get clean && \
rm -rf /var/lib/apt/lists/*
# 创建非root用户
RUN useradd -m -u 1000 appuser
WORKDIR /app
# 安装依赖
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
# 切换用户
USER appuser
# 复制应用
COPY --chown=appuser:appuser . .
# 健康检查
HEALTHCHECK --interval=30s --timeout=3s \
CMD curl -f http://localhost:8000/health || exit 1
EXPOSE 8000
CMD ["python", "app.py"]
Docker Bench Security
# 运行Docker安全基准测试
docker run -it --rm \
--net host \
--pid host \
--userns host \
--cap-add audit_control \
-e DOCKER_CONTENT_TRUST=$DOCKER_CONTENT_TRUST \
-v /var/lib:/var/lib \
-v /var/run/docker.sock:/var/run/docker.sock \
-v /etc:/etc \
--label docker_bench_security \
docker/docker-bench-security
# 查看报告并修复问题
运行时安全
# 使用Falco监控运行时行为
docker run -d \
--name falco \
--privileged \
-v /var/run/docker.sock:/host/var/run/docker.sock \
-v /dev:/host/dev \
-v /proc:/host/proc:ro \
falcosecurity/falco
# Falco会检测异常行为:
# - 容器中执行shell
# - 修改系统文件
# - 异常网络连接
# - 权限提升
Docker Compose安全配置
version: '3.8'
services:
app:
image: myapp:latest
user: "1000:1000"
read_only: true
tmpfs:
- /tmp
cap_drop:
- ALL
cap_add:
- NET_BIND_SERVICE
security_opt:
- no-new-privileges:true
- seccomp:default.json
networks:
- frontend
deploy:
resources:
limits:
cpus: '1'
memory: 512M
db:
image: postgres:14
user: postgres
read_only: true
tmpfs:
- /tmp
- /var/run/postgresql
volumes:
- db-data:/var/lib/postgresql/data
networks:
- backend
environment:
POSTGRES_PASSWORD_FILE: /run/secrets/db_password
secrets:
- db_password
networks:
frontend:
backend:
internal: true
volumes:
db-data:
secrets:
db_password:
external: true
安全检查清单
- 使用官方或可信的基础镜像
- 定期扫描镜像漏洞
- 使用非root用户运行容器
- 限制容器能力(capabilities)
- 使用只读文件系统
- 不在镜像中硬编码敏感信息
- 启用Docker Content Trust
- 配置资源限制
- 使用网络隔离
- 启用审计日志
- 定期更新Docker和镜像
- 使用安全扫描工具
实践练习
- 修改Dockerfile使用非root用户运行应用
- 使用Trivy扫描镜像并修复高危漏洞
- 配置容器使用只读文件系统
- 运行Docker Bench Security检查安全配置
- 使用Docker Secrets管理敏感信息
- 配置网络隔离,限制容器间通信