🔒 安全最佳实践
1. 不要用 root 运行容器
默认情况下容器以 root 身份运行。如果应用有漏洞,攻击者直接获得 root 权限——相当于给了别人一把管理员钥匙。
dockerfile
# 在 Dockerfile 中创建非 root 用户
FROM node:18-slim
# 创建应用用户
RUN groupadd -r appuser && useradd -r -g appuser appuser
WORKDIR /app
COPY package*.json ./
RUN npm install --production
COPY . .
# 切换到非 root 用户
USER appuser
CMD ["node", "server.js"]bash
# 运行时也可以指定用户
docker run -d --user 1000:1000 myapp
# 查看容器以什么用户运行
docker inspect --format='{{.Config.User}}' myapp
appuser2. 只读文件系统
bash
# 把容器文件系统设为只读(防止被篡改)
docker run -d --read-only --tmpfs /tmp --tmpfs /var/run myapp
# /tmp 和 /var/run 用 tmpfs(内存),应用需要写入的目录挂载为 volume
# docker-compose.yml 中的写法
cat > docker-compose.yml << 'EOF'
services:
web:
image: nginx:alpine
read_only: true
tmpfs:
- /tmp
- /var/cache/nginx
- /var/run
EOF3. 不要挂载 Docker socket
-v /var/run/docker.sock:/var/run/docker.sock 看似方便(可以在容器里管理 Docker),但实际上等于给了容器宿主机的 root 权限——攻击者可以通过 Docker 创建特权容器,直接逃逸到宿主机。
💡 提示: 💡 例外:CI/CD 工具(如 Jenkins)和某些编排工具可能需要访问 Docker API,但不要把
:ro当成安全边界。更稳妥的做法是使用 Docker socket proxy、隔离的构建机、rootless Docker 或 Docker-in-Docker (DinD),并限制可执行的 API 能力。
4. 镜像安全扫描
bash
# 用 Docker Scout 扫描镜像漏洞(Docker Desktop 内置)
docker scout cves myapp:latest
# 用 Trivy 扫描(开源,推荐)
docker run --rm -v /var/run/docker.sock:/var/run/docker.sock \
aquasec/trivy image myapp:latest
# 扫描结果示例:
# myapp:latest (debian 12.4)
# Total: 3 (UNKNOWN: 0, LOW: 1, MEDIUM: 1, HIGH: 1, CRITICAL: 0)
#
# ┌────────────┬──────────────┬──────────┬─────────────────────┐
# │ Library │ Vulnerability │ Severity │ Fixed Version │
# ├────────────┼──────────────┼──────────┼─────────────────────┤
# │ openssl │ CVE-2024-xxx │ HIGH │ 3.0.13-1~deb12u1 │
# └────────────┴──────────────┴──────────┴─────────────────────┘
# 在 CI/CD 中集成扫描(有高危漏洞就阻止构建)
trivy image --exit-code 1 --severity HIGH,CRITICAL myapp:latest