跳到主要内容

Docker 安全

安全威胁概览

镜像安全

使用可信基础镜像

# ✅ 使用官方镜像 + 固定版本
FROM node:20.11-alpine3.19

# ❌ 使用 latest(不可控)
FROM node:latest

# ❌ 使用来路不明的镜像
FROM someone/random-image

镜像漏洞扫描

# Docker Scout(官方工具)
docker scout cves myimage:latest
docker scout quickview myimage:latest

# Trivy(推荐,开源免费)
trivy image myimage:latest
trivy image --severity HIGH,CRITICAL myimage:latest

# Grype
grype myimage:latest
CI/CD 集成扫描

在流水线中加入镜像扫描步骤,阻止包含高危漏洞的镜像发布:

.github/workflows/scan.yml
- name: Scan image
uses: aquasecurity/trivy-action@master
with:
image-ref: myimage:latest
severity: HIGH,CRITICAL
exit-code: 1 # 发现高危漏洞时构建失败

避免泄露敏感信息

# ❌ 密钥写入镜像层(即使后续删除也能恢复)
COPY .env /app/.env
RUN rm /app/.env # 仍然存在于历史层中!

# ✅ 使用 BuildKit secret mount(构建时使用,不写入镜像层)
RUN --mount=type=secret,id=mysecret \
cat /run/secrets/mysecret > /dev/null

# 构建时传入 secret
docker build --secret id=mysecret,src=./secret.txt .

容器运行时安全

非 root 用户运行

# 创建非 root 用户
RUN addgroup -g 1000 appgroup && \
adduser -D -u 1000 -G appgroup appuser

# 切换到非 root 用户
USER appuser
# 运行时指定用户
docker run -u 1000:1000 myimage

只读文件系统

# 容器文件系统只读 + tmpfs 可写
docker run -d \
--read-only \
--tmpfs /tmp:size=100m \
--tmpfs /var/run \
-v app-data:/app/data \
myimage

限制 Linux Capabilities

# 删除所有 capabilities,只添加需要的
docker run -d \
--cap-drop ALL \
--cap-add NET_BIND_SERVICE \ # 绑定低端口
myimage

# 禁止获取新权限
docker run -d \
--security-opt no-new-privileges \
myimage

常用 Capabilities:

Capability说明
NET_BIND_SERVICE绑定 1024 以下端口
CHOWN修改文件所有者
SYS_TIME修改系统时间
NET_RAW原始套接字(ping)

资源限制

docker run -d \
--memory 512m \
--memory-swap 512m \ # 禁用 swap
--cpus 1.0 \
--pids-limit 100 \ # 限制进程数(防 fork 炸弹)
--ulimit nofile=1024:1024 \
myimage

Seccomp 和 AppArmor

# 自定义 Seccomp 配置
docker run -d \
--security-opt seccomp=./seccomp-profile.json \
myimage

# 使用默认 AppArmor
docker run -d \
--security-opt apparmor=docker-default \
myimage

Docker Daemon 安全

保护 Docker Socket

# docker.sock 只允许 docker 组访问
ls -la /var/run/docker.sock
# srw-rw---- 1 root docker 0 Jan 1 00:00 /var/run/docker.sock

# ❌ 绝对不要把 docker.sock 挂载到不可信容器
docker run -v /var/run/docker.sock:/var/run/docker.sock untrusted
Docker Socket = root 权限

能访问 Docker Socket 就等于拥有宿主机 root 权限。可以通过创建特权容器逃逸到宿主机。

TLS 远程访问

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

# 配置 Docker Daemon 使用 TLS
cat /etc/docker/daemon.json
{
"hosts": ["unix:///var/run/docker.sock", "tcp://0.0.0.0:2376"],
"tls": true,
"tlscacert": "/etc/docker/certs/ca.pem",
"tlscert": "/etc/docker/certs/server-cert.pem",
"tlskey": "/etc/docker/certs/server-key.pem",
"tlsverify": true
}

网络安全

# 创建内部网络(不能访问外网)
docker network create --internal secure-net

# 绑定端口到 localhost
docker run -p 127.0.0.1:8080:80 myapp

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

Docker Bench Security

Docker Bench for Security 根据 CIS Docker Benchmark 自动检查安全配置:

# 运行安全基线检查
docker run --rm --net host --pid host --userns host \
--cap-add audit_control \
-v /etc:/etc:ro \
-v /var/lib:/var/lib:ro \
-v /var/run/docker.sock:/var/run/docker.sock:ro \
docker/docker-bench-security

安全最佳实践清单

# 镜像层面
- [ ] 使用官方/可信基础镜像
- [ ] 固定镜像版本标签(不用 latest)
- [ ] 多阶段构建,最小化最终镜像
- [ ] CI/CD 镜像漏洞扫描
- [ ] 不在镜像中存储密钥/密码

# 容器层面
- [ ] 非 root 用户运行
- [ ] 只读文件系统 + tmpfs
- [ ] 删除不需要的 Capabilities
- [ ] 设置资源限制(内存、CPU、进程数)
- [ ] 启用 no-new-privileges

# 主机层面
- [ ] 保护 Docker Socket
- [ ] 启用 TLS 远程访问
- [ ] 定期更新 Docker Engine
- [ ] 启用审计日志

# 网络层面
- [ ] 使用自定义网络隔离
- [ ] 端口只绑定 localhost
- [ ] 内部服务用 internal 网络

常见面试问题

Q1: Docker 容器逃逸有哪些途径?如何防御?

答案

常见逃逸途径:

  1. 特权容器--privileged):可访问所有设备
  2. 挂载 docker.sock:可创建特权容器
  3. 内核漏洞(如 Dirty Pipe):利用内核漏洞逃逸
  4. 挂载宿主机敏感目录//etc

防御措施:

  • 不使用 --privileged
  • 不挂载 docker.sock 到不可信容器
  • 使用非 root 用户 + --cap-drop ALL
  • 启用 Seccomp/AppArmor
  • 及时更新内核和 Docker 版本

Q2: 如何安全管理容器中的敏感信息?

答案

  1. 环境变量:通过运行时注入,不硬编码在镜像中
  2. Docker Secrets(Swarm): docker secret create
  3. BuildKit secret mount:构建时使用,不存入镜像层
  4. 外部密钥管理:HashiCorp Vault、AWS Secrets Manager
  5. Kubernetes Secrets + 加密存储

Q3: 如何在 CI/CD 中保障镜像安全?

答案

  1. 构建后用 Trivy/Grype 扫描漏洞
  2. 设置策略:HIGH/CRITICAL 漏洞阻止发布
  3. 使用私有镜像仓库(Harbor)+ 镜像签名
  4. 定期重建基础镜像获取安全补丁
  5. 使用 Cosign 进行镜像签名和验证

相关链接