Docker 安全实践
构建安全的容器化应用
安全最佳实践
1. 使用非 root 用户
dockerfile
# ❌ 以 root 用户运行(危险)
FROM node:18-alpine
WORKDIR /app
COPY . .
RUN npm ci
CMD ["node", "server.js"]
# ✅ 创建专用用户
FROM node:18-alpine
WORKDIR /app
# 创建用户和组
RUN addgroup -g 1001 -S nodejs && \
adduser -S nextjs -u 1001 -G nodejs
# 复制文件并设置权限
COPY --chown=nextjs:nodejs package*.json ./
COPY --chown=nextjs:nodejs . .
# 切换用户
USER nextjs
CMD ["node", "server.js"]2. 避免敏感信息泄露
dockerfile
# ❌ 敏感信息在镜像中
ENV DATABASE_PASSWORD=secret123
COPY . .
# ✅ 使用构建时 ARG(不进入最终镜像)
ARG BUILD_SECRET
RUN echo $BUILD_SECRET > /tmp/secret && rm /tmp/secret
# ✅ 生产环境通过环境变量注入
# docker run -e DB_PASSWORD=xxx myapp3. 使用特定版本而非 latest
dockerfile
# ❌ latest 标签可能导致不可预测的构建
FROM node:latest
# ✅ 固定版本,确保可复现
FROM node:18.19.1-alpine4. 最小化镜像层数
dockerfile
# ✅ 合并指令
RUN apt-get update && \
apt-get install -y --no-install-recommends \
curl \
vim \
&& rm -rf /var/lib/apt/lists/*5. 使用健康检查
dockerfile
HEALTHCHECK --interval=30s --timeout=3s \
CMD node -e "require('http').get('http://localhost:3000/health', (r) => process.exit(r.statusCode === 200 ? 0 : 1))"安全扫描工具
Trivy 扫描
bash
# 安装
brew install trivy
# 扫描镜像
trivy image myapp:latest
# 扫描文件系统
trivy fs .
# 扫描漏洞报告
trivy image --format json --output result.json myapp:latestDocker Scout
bash
# 登录
docker scout login
# 分析镜像
docker scout cves myapp:latest
# 推荐修复
docker scout recommendations myapp:latestDocker Bench Security
bash
# 运行安全检查
docker run -it --rm \
--net host \
--pid host \
--userns host \
-v /var/lib/docker:/var/lib/docker \
aquasec/docker-bench-security:latest安全加固检查清单
| 检查项 | 说明 |
|---|---|
| 非 root 用户 | 容器不以 root 运行 |
| 最小权限 | 只授予必要权限 |
| 镜像签名 | 使用 Docker Content Trust |
| 漏洞扫描 | 定期扫描镜像漏洞 |
| 只读根文件系统 | 使用 --read-only |
| 资源限制 | 设置 CPU/内存限制 |
| 敏感信息 | 不在镜像中存储密钥 |
| 及时更新 | 定期更新基础镜像 |
运行时安全
bash
# 资源限制
docker run \
--memory=512m \
--cpus=0.5 \
--read-only \
--tmpfs /tmp:size=10m,mode=1777 \
myapp
# 安全选项
docker run \
--security-opt=no-new-privileges \
--cap-drop ALL \
--cap-add NET_BIND_SERVICE \
myapp面试高频题
Q1: 如何确保容器以非 root 用户运行?
答案:
- 在 Dockerfile 中创建专用用户
- 使用
USER指令切换用户 - 设置文件所有权
dockerfile
RUN adduser -S appuser
COPY --chown=appuser:appuser . .
USER appuserQ2: 如何防止敏感信息泄露?
答案:
- 不在 Dockerfile 中硬编码密钥
- 使用
.dockerignore排除敏感文件 - 通过环境变量或密钥管理服务注入
- 构建时不使用
--build-arg传递敏感信息
Q3: Docker 容器有哪些安全风险?
答案:
- 容器逃逸风险
- 权限过大(privileged 模式)
- 敏感信息泄露
- 镜像漏洞
- 网络隔离不足
- 资源未限制