Add more content

This commit is contained in:
Baohua Yang
2026-01-30 16:48:39 -08:00
parent c58f61dbed
commit fec2e506d9
39 changed files with 8202 additions and 1063 deletions

View File

@@ -1,59 +1,314 @@
# 安全
容器安全是生产环境部署的核心考量评估 Docker 的安全性时主要考虑以下几个方面
容器安全是生产环境部署的核心考量本章介绍 Docker 的安全机制和最佳实践
## 容器安全的本质
> **核心问题**容器共享宿主机内核隔离性弱于虚拟机如何在便利性和安全性之间取得平衡
```
虚拟机安全模型: 容器安全模型:
┌─────────────────┐ ┌─────────────────┐
│ Guest OS │ │ 容器进程 │
├─────────────────┤ │ (共享内核) │
│ Hypervisor │◄── 隔离边界└────────┬────────┘
├─────────────────┤ │
│ Host OS │ ┌────────┴────────┐
└─────────────────┘ │ Namespace │◄── 隔离边界
│ Cgroups │
完全隔离(性能损耗) │ Capabilities │
└─────────────────┘
进程隔离(轻量但需加固)
```
---
## 核心安全机制
* **内核命名空间Namespace**提供进程网络文件系统等资源的隔离
* **控制组Cgroups**限制容器的 CPU内存I/O 等资源使用
* **Docker 守护进程安全**服务端的访问控制和防护
* **内核能力机制Capabilities**细粒度的权限控制
### 1. 命名空间Namespace
## 现代安全实践
提供进程网络文件系统等资源的隔离
### 镜像安全扫描
| Namespace | 隔离内容 | 安全作用 |
|-----------|---------|---------|
| PID | 进程 | 容器看不到其他进程 |
| NET | 网络 | 独立网络栈 |
| MNT | 文件系统 | 独立的根目录 |
| USER | 用户 | 容器 root 宿主机 root |
| IPC | 进程通信 | 隔离共享内存 |
| UTS | 主机名 | 独立主机名 |
使用工具扫描镜像中的已知漏洞
详见 [命名空间](../underly/namespace.md) 章节
* **Docker Scout**Docker 官方集成的安全扫描工具提供 SBOM 分析
* **Trivy**开源的全面漏洞扫描器
* **Snyk**商业级安全平台
### 2. 控制组Cgroups
限制容器的资源使用防止资源耗尽攻击
```bash
# 使用 Docker Scout 扫描镜像
$ docker scout cves myimage:latest
# 限制内存(超出会被 OOM Kill
$ docker run -m 512m myapp
# 使用 Trivy 扫描
$ trivy image myimage:latest
# 限制 CPU
$ docker run --cpus=1.5 myapp
# 限制磁盘 I/O
$ docker run --device-write-bps /dev/sda:10mb myapp
```
### root 用户运行
### 3. 能力机制Capabilities
避免以 root 用户运行容器降低权限逃逸风险
Linux root 权限拆分为多个细粒度的能力Docker 默认禁用危险能力
```dockerfile
FROM node:20-alpine
RUN addgroup -g 1001 appgroup && adduser -u 1001 -G appgroup -D appuser
USER appuser
```
### 只读文件系统
使用只读根文件系统增强安全性
| 能力 | 说明 | 默认状态 |
|------|------|---------|
| `CAP_NET_ADMIN` | 网络管理 | 禁用 |
| `CAP_SYS_ADMIN` | 系统管理 | 禁用 |
| `CAP_SYS_PTRACE` | 进程追踪 | 禁用 |
| `CAP_CHOWN` | 更改文件所有者 | 启用 |
| `CAP_NET_BIND_SERVICE` | 绑定低端口 | 启用 |
```bash
$ docker run --read-only --tmpfs /tmp myimage
# 删除所有能力,只添加需要的
$ docker run --cap-drop=all --cap-add=NET_BIND_SERVICE myapp
# 查看容器的能力
$ docker exec myapp cat /proc/1/status | grep Cap
```
### Docker Content TrustDCT
---
启用镜像签名验证确保镜像来源可信
## 镜像安全
### 使用可信镜像
```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:20-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
# ✅ 好:使用精简镜像
FROM node:20-alpine # ~50MB
FROM gcr.io/distroless/nodejs # ~20MB
# ❌ 差:使用完整镜像
FROM node:20 # ~1GB
FROM ubuntu:24.04 # ~78MB
```
### 2. 多阶段构建
```dockerfile
# 构建阶段
FROM node:20 AS builder
WORKDIR /app
COPY . .
RUN npm install && npm run build
# 生产阶段(不包含开发依赖和源码)
FROM node:20-alpine
COPY --from=builder /app/dist /app
USER node
CMD ["node", "/app/server.js"]
```
### 3. 不存储敏感信息
```dockerfile
# ❌ 错误:敏感信息写入镜像
ENV DB_PASSWORD=secret123
COPY .env /app/
# ✅ 正确:运行时传入
# docker run -e DB_PASSWORD=xxx 或使用 Docker Secrets
```
### 4. 固定依赖版本
```dockerfile
# ✅ 固定版本
FROM node:20.10.0-alpine3.19
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
```
---
## 本章小结
| 安全措施 | 重要程度 | 实现方式 |
|---------|---------|---------|
| root 运行 | | `USER` 指令 |
| 漏洞扫描 | | `docker scout`, `trivy` |
| 资源限制 | | `-m`, `--cpus` |
| 只读文件系统 | | `--read-only` |
| 最小能力 | | `--cap-drop=all` |
| 镜像签名 | | Docker Content Trust |
## 延伸阅读
- [命名空间](../underly/namespace.md)隔离机制详解
- [控制组](../underly/cgroups.md)资源限制详解
- [最佳实践](../appendix/best_practices.md)Dockerfile 安全配置