Files
docker_practice/11_ops/security/README.md
2026-02-12 16:51:50 -08:00

398 lines
8.5 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 安全
容器安全是生产环境部署的核心考量本章介绍 Docker 的安全机制和最佳实践
## 容器安全的本质
> **核心问题**容器共享宿主机内核隔离性弱于虚拟机如何在便利性和安全性之间取得平衡
```
虚拟机安全模型: 容器安全模型:
┌─────────────────┐ ┌─────────────────┐
│ Guest OS │ │ 容器进程 │
├─────────────────┤ │ (共享内核) │
│ Hypervisor │◄── 隔离边界└────────┬────────┘
├─────────────────┤ │
│ Host OS │ ┌────────┴────────┐
└─────────────────┘ │ Namespace │◄── 隔离边界
│ Cgroups │
完全隔离(性能损耗) │ Capabilities │
└─────────────────┘
进程隔离(轻量但需加固)
```
---
## 核心安全机制
### 1. 命名空间Namespace
提供进程网络文件系统等资源的隔离
| Namespace | 隔离内容 | 安全作用 |
|-----------|---------|---------|
| PID | 进程 | 容器看不到其他进程 |
| NET | 网络 | 独立网络栈 |
| MNT | 文件系统 | 独立的根目录 |
| USER | 用户 | 容器 root 宿主机 root |
| IPC | 进程通信 | 隔离共享内存 |
| UTS | 主机名 | 独立主机名 |
详见 [命名空间](../../14_implementation/14.2_namespace.md) 章节
### 2. 控制组Cgroups
限制容器的资源使用防止资源耗尽攻击
```bash
## 限制内存(超出会被 OOM Kill
$ docker run -m 512m myapp
## 限制 CPU
$ docker run --cpus=1.5 myapp
## 限制磁盘 I/O
$ docker run --device-write-bps /dev/sda:10mb myapp
```
### 3. 能力机制Capabilities
Linux root 权限拆分为多个细粒度的能力Docker 默认禁用危险能力
| 能力 | 说明 | 默认状态 |
|------|------|---------|
| `CAP_NET_ADMIN` | 网络管理 | 禁用 |
| `CAP_SYS_ADMIN` | 系统管理 | 禁用 |
| `CAP_SYS_PTRACE` | 进程追踪 | 禁用 |
| `CAP_CHOWN` | 更改文件所有者 | 启用 |
| `CAP_NET_BIND_SERVICE` | 绑定低端口 | 启用 |
```bash
## 删除所有能力,只添加需要的
$ docker run --cap-drop=all --cap-add=NET_BIND_SERVICE myapp
## 查看容器的能力
$ docker exec myapp cat /proc/1/status | grep Cap
```
---
## 镜像安全
### 使用可信镜像
运行以下命令
```bash
## ✅ 使用官方镜像
$ docker pull nginx
## ✅ 使用经过验证的镜像
$ docker pull bitnami/nginx
## ⚠️ 谨慎使用未知来源镜像
$ docker pull randomuser/suspicious-image
```
### 漏洞扫描
扫描镜像中的已知安全漏洞
```bash
## Docker Scout官方工具
$ docker scout cves nginx:latest
$ docker scout recommendations nginx:latest
## Trivy开源工具
$ trivy image nginx:latest
## Snyk商业工具
$ snyk container test nginx:latest
```
### 镜像签名验证
使用 Docker Content Trust (DCT) 验证镜像来源
```bash
## 启用镜像签名验证
$ export DOCKER_CONTENT_TRUST=1
## 此后的 pull/push 会验证签名
$ docker pull myregistry/myimage:latest
```
---
## 运行时安全
### 1. root 用户运行
> 笔者强调这是最重要的安全实践之一
```dockerfile
FROM node:22-alpine
## 创建非 root 用户
RUN addgroup -g 1001 appgroup && \
adduser -u 1001 -G appgroup -D appuser
## 设置工作目录权限
WORKDIR /app
COPY --chown=appuser:appgroup . .
## 切换用户
USER appuser
CMD ["node", "server.js"]
```
或在运行时指定
```bash
$ docker run -u 1001:1001 myapp
```
### 2. 只读文件系统
运行以下命令
```bash
## 根文件系统只读
$ docker run --read-only myapp
## 需要写入的目录使用 tmpfs
$ docker run --read-only --tmpfs /tmp --tmpfs /var/run myapp
```
### 3. 禁用特权模式
运行以下命令
```bash
## ❌ 绝对不要在生产环境使用
$ docker run --privileged myapp
## ✅ 只添加必要的能力
$ docker run --cap-add=SYS_TIME myapp
```
### 4. 限制资源
运行以下命令
```bash
$ docker run \
-m 512m \ # 内存限制
--cpus=1 \ # CPU 限制
--pids-limit=100 \ # 进程数限制
--ulimit nofile=1024:1024 \ # 文件描述符限制
myapp
```
### 5. 网络隔离
运行以下命令
```bash
## 禁用网络(适用于不需要网络的任务)
$ docker run --network=none myapp
## 使用自定义网络隔离
$ docker network create --internal isolated_net
$ docker run --network=isolated_net myapp
```
---
## Dockerfile 安全实践
### 1. 使用精简基础镜像
Dockerfile 内容如下
```dockerfile
## ✅ 好:使用精简镜像
FROM node:22-alpine # ~50MB
FROM gcr.io/distroless/nodejs # ~20MB
## ❌ 差:使用完整镜像
FROM node:22 # ~1GB
FROM ubuntu:24.04 # ~78MB
```
### 2. 多阶段构建
Dockerfile 内容如下
```dockerfile
## 构建阶段
FROM node:22 AS builder
WORKDIR /app
COPY . .
RUN npm install && npm run build
## 生产阶段(不包含开发依赖和源码)
FROM node:22-alpine
COPY --from=builder /app/dist /app
USER node
CMD ["node", "/app/server.js"]
```
### 3. 不存储敏感信息
Dockerfile 内容如下
```dockerfile
## ❌ 错误:敏感信息写入镜像
ENV DB_PASSWORD=secret123
COPY .env /app/
## ✅ 正确:运行时传入
## docker run -e DB_PASSWORD=xxx 或使用 Docker Secrets
...
```
### 4. 固定依赖版本
Dockerfile 内容如下
```dockerfile
## ✅ 固定版本
FROM node:22.12.0-alpine3.21
RUN apk add --no-cache curl=8.5.0-r0
## ❌ 使用 latest
FROM node:latest
RUN apk add curl
```
---
## 安全扫描清单
部署前检查
| 检查项 | 命令/方法 |
|--------|----------|
| 漏洞扫描 | `docker scout cves` `trivy` |
| root 运行 | 检查 Dockerfile 中的 `USER` |
| 资源限制 | 检查 `-m`, `--cpus` 参数 |
| 只读文件系统 | 检查 `--read-only` |
| 无特权模式 | 确认没有 `--privileged` |
| 最小能力 | 检查 `--cap-drop=all` |
| 网络隔离 | 检查网络配置 |
| 敏感信息 | 确认无硬编码密码 |
---
## 高级安全方案
### Seccomp 系统调用过滤
限制容器可以使用的系统调用
```bash
$ docker run --security-opt seccomp=/path/to/profile.json myapp
```
### AppArmor / SELinux
使用强制访问控制
```bash
$ docker run --security-opt apparmor=docker-default myapp
```
### 安全容器gVisor / Kata
需要更强隔离时
```bash
## 使用 gVisor 运行时
$ docker run --runtime=runsc myapp
```
---
## 软件供应链安全
随着软件供应链攻击日益频繁仅保障运行时安全已不足够
### 1. SBOM软件物料清单
SBOM 类似于食品的配料表列出了容器镜像中包含的所有软件包及其版本
- **生成 SBOM**: 使用 `docker buildx build --sbom` `docker scout sbom`
- **管理 SBOM**: 确保持续监控 SBOM 中的组件是否存在新披露的漏洞
### 2. 镜像签名Sigstore / Notary v2
确保镜像在构建后未被篡改且确实来自可信的发布者
- **Cosign**: Sigstore 项目的一部分用于签署和验证容器镜像
```bash
## 签署镜像
$ cosign sign --key cosign.key myimage:tag
## 验证镜像
$ cosign verify --key cosign.pub myimage:tag
```
### 3. SLSASupply-chain Levels for Software Artifacts
遵循 SLSA 框架确保构建过程的完整性例如使用 GitHub Actions 等受控环境进行构建而非在开发者本地机器上构建发布
---
## 本章小结
| 安全措施 | 重要程度 | 实现方式 |
|---------|---------|---------|
| root 运行 | | `USER` 指令 |
| 漏洞扫描 | | `docker scout`, `trivy` |
| 资源限制 | | `-m`, `--cpus` |
| 只读文件系统 | | `--read-only` |
| 最小能力 | | `--cap-drop=all` |
| 镜像签名 | | Docker Content Trust |
## 延伸阅读
- [命名空间](../../14_implementation/14.2_namespace.md)隔离机制详解
- [控制组](../../14_implementation/14.3_cgroups.md)资源限制详解
- [最佳实践](../../16_appendix/16.1_best_practices.md)Dockerfile 安全配置