Skip to content

Docker 安全实践

本章将介绍 Docker 容器安全的最佳实践,帮助你构建和运行安全的容器化应用。

镜像安全

使用官方镜像

dockerfile
# ✅ 使用官方镜像
FROM node:20-alpine

# ❌ 避免使用来源不明的镜像
FROM random-user/node-custom

固定镜像版本

dockerfile
# ✅ 使用具体版本标签
FROM node:20.11.1-alpine3.19

# ⚠️ 避免使用 latest(可能引入未知变更)
FROM node:latest

镜像漏洞扫描

bash
# 使用 Docker Scout 扫描
docker scout cves myimage:latest

# 使用 Trivy 扫描
docker run --rm -v /var/run/docker.sock:/var/run/docker.sock \
  aquasec/trivy image myimage:latest

最小化镜像

dockerfile
# 使用多阶段构建,最终镜像只包含运行时必需的文件
FROM golang:1.22 AS builder
WORKDIR /app
COPY . .
RUN CGO_ENABLED=0 go build -o main .

FROM scratch
COPY --from=builder /app/main /main
CMD ["/main"]

容器运行安全

使用非 root 用户

dockerfile
FROM node:20-alpine
WORKDIR /app
COPY . .
RUN npm ci

# 创建并切换到非 root 用户
RUN addgroup -S appgroup && adduser -S appuser -G appgroup
USER appuser

CMD ["node", "server.js"]

只读文件系统

bash
# 以只读模式运行容器
docker run --read-only \
  --tmpfs /tmp \
  --tmpfs /var/run \
  myapp:latest

限制容器权限

bash
# 删除所有 Linux capabilities
docker run --cap-drop ALL myapp:latest

# 只添加必要的 capabilities
docker run --cap-drop ALL --cap-add NET_BIND_SERVICE myapp:latest

# 禁止容器获取新权限
docker run --security-opt no-new-privileges myapp:latest

资源限制

bash
# 限制内存和 CPU
docker run -m 256m --cpus 0.5 myapp:latest

# 限制进程数
docker run --pids-limit 100 myapp:latest

# 限制重启次数
docker run --restart on-failure:5 myapp:latest

网络安全

网络隔离

bash
# 创建隔离网络
docker network create --internal backend-net

# 前端网络(可访问外部)
docker network create frontend-net

# 数据库只在内部网络
docker run -d --name db --network backend-net postgres:16

# 应用连接两个网络
docker run -d --name app --network frontend-net myapp
docker network connect backend-net app

限制容器间通信

bash
# 禁用默认 bridge 网络的容器间通信
# 编辑 /etc/docker/daemon.json
{
  "icc": false
}

敏感信息管理

使用 Docker Secrets(Swarm 模式)

bash
# 创建 secret
echo "my-password" | docker secret create db_password -

# 在服务中使用
docker service create \
  --name myapp \
  --secret db_password \
  myapp:latest

环境变量安全

bash
# ❌ 不要在 Dockerfile 中硬编码敏感信息
ENV DB_PASSWORD=secret123

# ✅ 运行时通过环境变量传入
docker run -e DB_PASSWORD=secret123 myapp

# ✅ 使用 .env 文件
docker run --env-file .env myapp

# ✅ 使用 Docker Compose secrets
# docker-compose.yml
services:
  app:
    image: myapp
    secrets:
      - db_password
secrets:
  db_password:
    file: ./secrets/db_password.txt

.dockerignore 排除敏感文件

# .dockerignore
.env
.env.*
*.key
*.pem
secrets/
.git

Dockerfile 安全检查清单

检查项说明
✅ 使用官方基础镜像确保镜像来源可信
✅ 固定版本标签避免意外引入变更
✅ 使用非 root 用户降低容器逃逸风险
✅ 多阶段构建减少攻击面
✅ 不包含敏感信息密码、密钥等不写入镜像
✅ 最小化安装包只安装必要的依赖
✅ 使用 COPY 而非 ADDADD 有自动解压等隐含行为
✅ 设置 HEALTHCHECK监控容器健康状态

Docker Daemon 安全

启用 TLS

bash
# 生成 CA 和证书后配置 daemon.json
{
  "tls": true,
  "tlscacert": "/etc/docker/ca.pem",
  "tlscert": "/etc/docker/server-cert.pem",
  "tlskey": "/etc/docker/server-key.pem",
  "hosts": ["unix:///var/run/docker.sock", "tcp://0.0.0.0:2376"]
}

日志审计

bash
# 配置日志驱动
{
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "10m",
    "max-file": "5"
  }
}

本章小结

Docker 安全需要从镜像构建、容器运行、网络配置和敏感信息管理等多个层面综合考虑。遵循最小权限原则,定期扫描漏洞,是保障容器安全的关键。

关键要点:

  • 使用官方镜像并固定版本
  • 容器以非 root 用户运行
  • 限制容器权限和资源
  • 网络隔离和通信控制
  • 敏感信息不写入镜像

延伸阅读