Appearance
Docker 安全
Docker 安全概述
Docker 安全涉及从镜像构建、容器运行到系统配置的多个层面。由于容器共享宿主机内核,安全问题可能影响整个系统,因此需要在每个环节实施适当的安全措施。
Docker 架构安全
Docker 守护进程安全
Docker 守护进程以 root 权限运行,对系统有完全访问权限,因此需要特别注意其安全配置。
安全配置建议
json
// /etc/docker/daemon.json
{
"icc": false,
"userland-proxy": false,
"live-restore": true,
"userns-remap": "default"
}
TLS 认证
启用 TLS 认证确保 Docker 守护进程和客户端之间的通信安全:
bash
# 生成 TLS 证书
docker daemon --tlsverify --tlscacert=ca.pem --tlscert=server-cert.pem --tlskey=server-key.pem \
-H=0.0.0.0:2376
镜像安全
1. 使用官方镜像
优先使用官方或可信的镜像仓库中的镜像:
docker
# 使用官方镜像
FROM node:16-alpine
# 而不是 FROM unofficial-user/node-image
2. 镜像扫描
使用工具扫描镜像中的漏洞:
bash
# 使用 Trivy 扫描镜像
trivy image my-app:latest
# 使用 Docker Scout
docker scout cves my-app:latest
# 使用 Clair (通过 Dagda)
docker run --rm -v /var/run/docker.sock:/var/run/docker.sock \
-p 8001:8080 --name dagda dagda
3. Dockerfile 安全实践
使用非 root 用户
docker
FROM node:16-alpine
# 创建专用用户
RUN addgroup -g 1001 -S nodejs && \
adduser -S nodejs -u 1001 -G nodejs
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production && npm cache clean --force
# 复制文件并设置权限
COPY --chown=nodejs:nodejs . .
# 切换到非 root 用户
USER nodejs
EXPOSE 3000
CMD ["npm", "start"]
限制权限
docker
FROM node:16-alpine
# 设置安全的环境变量
ENV NODE_ENV=production
RUN addgroup -g 1001 -S appuser && \
adduser -S appuser -u 1001 -G appuser
WORKDIR /app
# 安装必要包,避免安装不必要的工具
RUN apk add --no-cache \
dumb-init \
curl
COPY package*.json ./
RUN npm ci --only=production --no-audit --no-fund && \
npm cache clean --force
COPY --chown=appuser:appuser . .
# 使用 dumb-init 作为 PID 1
ENTRYPOINT ["/usr/bin/dumb-init", "--"]
USER appuser
EXPOSE 3000
CMD ["npm", "start"]
4. 镜像签名与验证
使用 Docker Content Trust 确保镜像的完整性和来源:
bash
# 启用内容信任
export DOCKER_CONTENT_TRUST=1
# 构建签名镜像
docker build -t my-app:signed .
# 推送签名镜像
docker push my-app:signed
容器运行时安全
1. 安全选项配置
只读根文件系统
bash
# 运行容器时使用只读根文件系统
docker run --read-only my-app:latest
# 允许写入特定目录
docker run --read-only -v /app/tmp:/tmp my-app:latest
禁用特权模式
bash
# 避免使用 --privileged
docker run --privileged dangerous-container # 不推荐
# 使用特定的 Linux 功能
docker run --cap-add=NET_ADMIN my-app:latest # 推荐
限制 Linux 功能
bash
# 删除不必要的功能
docker run --cap-drop=ALL --cap-add=NET_BIND_SERVICE my-app:latest
2. 安全配置文件 (Seccomp)
使用 Seccomp 限制容器可以调用的系统调用:
json
// seccomp-profile.json
{
"defaultAction": "SCMP_ACT_ERRNO",
"syscalls": [
{
"name": "accept",
"action": "SCMP_ACT_ALLOW",
"args": []
},
{
"name": "bind",
"action": "SCMP_ACT_ALLOW",
"args": []
}
]
}
bash
# 使用自定义 seccomp 配置文件
docker run --security-opt seccomp=./seccomp-profile.json my-app:latest
3. AppArmor 和 SELinux
bash
# 使用 AppArmor 配置文件
docker run --security-opt apparmor=profile-name my-app:latest
# 使用 SELinux 标签
docker run --security-opt label=user:USER:ROLE:TYPE:LEVEL my-app:latest
网络安全
1. 网络隔离
bash
# 创建自定义网络
docker network create --driver bridge --internal secure-network
# 运行容器在隔离网络中
docker run --network secure-network my-app:latest
2. 端口安全
bash
# 只发布必要的端口
docker run -p 127.0.0.1:8080:80 my-app:latest # 限制访问来源
# 避免使用 --net=host,因为它绕过 Docker 网络隔离
docker run --net=host container # 不推荐
存储安全
1. 卷安全
bash
# 使用命名卷而非绑定挂载(如果不需要直接访问宿主机文件)
docker volume create app-data
docker run -v app-data:/app/data my-app:latest
# 限制卷的访问权限
docker run --read-only -v /host/data:/app/data:ro my-app:latest
2. 敏感数据处理
bash
# 使用 Docker secrets(在 Swarm 模式下)
echo "mypassword" | docker secret create db_password -
# 使用环境变量文件
docker run --env-file .env my-app:latest
Docker Compose 安全
1. 安全配置
yaml
version: '3.8'
services:
app:
image: my-app:latest
read_only: true # 只读根文件系统
user: "1001:1001" # 非 root 用户
cap_drop:
- ALL # 删除所有功能
cap_add:
- NET_BIND_SERVICE # 添加必要功能
security_opt:
- no-new-privileges:true # 防止获取新权限
tmpfs:
- /tmp # 使用 tmpfs 存储临时文件
volumes:
- app-data:/app/data
networks:
- secure-network
networks:
secure-network:
driver: bridge
internal: true
volumes:
app-data:
2. 环境变量安全
bash
# 使用 .env 文件存储敏感信息(确保文件权限设置正确)
# .env
DB_PASSWORD=secret_password
API_KEY=secret_key
yaml
# docker-compose.yml
version: '3.8'
services:
app:
image: my-app:latest
env_file:
- .env
environment:
- NODE_ENV=production
安全扫描和监控
1. 镜像扫描工具
Trivy
bash
# 扫描镜像漏洞
trivy image --security-checks vuln my-app:latest
# 扫描配置文件
trivy config --severity HIGH,CRITICAL .
# 扫描文件系统
trivy fs --security-checks vuln .
Clair
bash
# 启动 Clair 服务
docker run -d --name clair -p 6060-6061:6060-6061 arminc/clair-local-scan:v2.0.6
# 扫描镜像
docker run --rm -i -e CLAIR_OUTPUT=medium -e CLAIR_THRESHOLD=high \
-v /var/run/docker.sock:/var/run/docker.sock \
arminc/clair-local-scan:v2.0.6 my-app:latest
2. 运行时监控
Sysdig
bash
# 安装和运行 Sysdig
docker run -i -t --name=sysdig-agent \
--privileged -v /var/run/docker.sock:/host/var/run/docker.sock \
--pid=host --net=host --env=DOCKER_API_VERSION=1.24 \
sysdig/agent
Docker 安全最佳实践
1. 镜像安全
- 使用官方或可信的基础镜像
- 定期更新基础镜像
- 扫描镜像漏洞
- 最小化镜像内容
- 避免在镜像中存储敏感信息
2. 运行时安全
- 以非 root 用户运行容器
- 限制容器权限
- 使用只读文件系统
- 限制资源使用
- 实施网络隔离
3. 系统安全
- 保持 Docker 引擎更新
- 限制对 Docker 守护进程的访问
- 启用内容信任
- 监控容器活动
- 定期安全审计
安全检查清单
Dockerfile 检查清单
- [ ] 使用官方或可信的基础镜像
- [ ] 避免使用 :latest 标签
- [ ] 以非 root 用户运行应用
- [ ] 不在镜像中存储敏感信息
- [ ] 使用 .dockerignore 排除不必要的文件
- [ ] 安装最小必要包
- [ ] 定期更新基础镜像
运行时检查清单
- [ ] 不使用 --privileged 标志
- [ ] 限制容器资源使用
- [ ] 使用只读根文件系统(如果可能)
- [ ] 删除不必要的 Linux 功能
- [ ] 实施适当的用户和组映射
- [ ] 使用安全配置文件(Seccomp, AppArmor)
- [ ] 限制网络访问
部署检查清单
- [ ] 保护 Docker 守护进程套接字
- [ ] 使用 TLS 认证
- [ ] 实施访问控制
- [ ] 监控容器活动
- [ ] 定期扫描生产镜像
- [ ] 使用容器安全工具
Docker Bench for Security
运行 Docker 安全基准测试:
bash
docker run --rm -it \
--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 /usr/lib/systemd:/usr/lib/systemd \
-v /etc:/etc \
docker/docker-bench-security
安全工具推荐
1. 镜像分析工具
- Docker Scout: Docker 官方镜像分析工具
- Trivy: 开源漏洞扫描器
- Clair: 静态分析工具
- Anchore: 镜像分析平台
2. 运行时安全工具
- Falco: 运行时安全监控
- Sysdig Secure: 容器安全平台
- Aqua Security: 容器安全解决方案
3. 合规性工具
- Open Policy Agent: 策略引擎
- Conftest: 配置验证工具
小结
Docker 安全是一个多层面的课题,需要从镜像构建、容器运行到系统配置全方位考虑。通过实施适当的安全措施,可以有效降低容器化应用的安全风险。在实际应用中,应根据具体需求和安全要求,选择合适的防护措施,并持续监控和更新安全配置。