Files
cs-note/hhs/MS/05-部署运维/01-容器化/03-镜像安全.md
T
2026-05-24 11:42:38 +08:00

151 lines
5.2 KiB
Markdown
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.
---
tags: [docker, image-security, trivy, distroless, registry]
create time: 2026-05-18 00:45
---
# 镜像安全 — 扫描、基线 & 仓库管理
## 概述
镜像安全不仅仅是"不要有 CVE"——它是一个完整的供应链安全体系,涵盖基础镜像选型、漏洞扫描、仓库分级管理和推送门禁。更多内容参见 [[../01-容器化/01-Dockerfile最佳实践]]。
## 镜像扫描流程
```mermaid
flowchart LR
Scan["镜像扫描 (Trivy/Snyk)"] --> Clean{"漏洞等级?"}
Clean -- "CRITICAL/HIGH" --> Block["❌ 阻止推送"]
Clean -- "MEDIUM" --> Review["⚠️ 人工审核"]
Clean -- "LOW/INFO" --> Allow["✅ 允许推送"]
style Block fill:#ffebee
style Review fill:#fff3e0
style Allow fill:#e8f5e9
```
### Trivy 常用命令
```bash
# 扫描镜像
trivy image harbor.example.com/app/server:v1.2.3
# 只报告 HIGH 及以上级别
trivy image --severity HIGH,CRITICAL harbor.example.com/app/server:v1.2.3
# 输出 JSON 供 CI 集成
trivy image --format json --output report.json harbor.example.com/app/server:v1.2.3
# 扫描 Dockerfile 中的潜在问题
trivy config Dockerfile
```
## 安全检查清单
- [ ] 不使用 `latest` tag(永远用具体版本号)→ 精确回滚
- [ ] 不安装不必要的软件包(`apk del --purge .build-deps`)→ 最小攻击面
- [ ] 定期更新基础镜像(修复 CVE)→ 跟上安全补丁节奏
- [ ] 使用非 root 用户运行 → `USER appuser`
- [ ] 镜像不包含密钥、密码、私钥 → CI/CD Secret 挂载代替 ENV
- [ ] 使用最小基础镜像(scratch / distroless)→ 减少暴露面
## Distroless 镜像
Google 推出的**无 shell、无包管理器**的极简运行时镜像:
```dockerfile
# 最极致的精简
FROM gcr.io/distroless/static-debian12
COPY --from=builder /app/server .
USER nonroot
CMD ["./server"]
```
> ⚠️ 注意:distroless 镜像没有 shell (`/bin/sh`),调试时需要额外工具(如 debug 镜像或 `kubectl exec` 到 sidecar)。
### 常用 Distroless 变种
| 镜像 | 适用场景 | 大小 |
|------|---------|------|
| `gcr.io/distroless/static-debian12` | 纯静态二进制 | ~2MB |
| `gcr.io/distroless/base-debian12` | 需要 glibc 的动态链接程序 | ~30MB |
| `gcr.io/distroless/java17` | Java 应用(含 JRE) | ~150MB |
| `gcr.io/distroless/nodejs18` | Node.js 应用 | ~100MB |
## 镜像压缩对比参考
| 基础镜像 | 典型 Go 服务大小 | 备注 |
|---------|-----------------|------|
| `ubuntu:22.04` | ~35 MB | 完整发行版 |
| `debian:bookworm-slim` | ~20 MB | 裁剪后较常用 |
| `alpine:3.19` | ~7 MB | musl libc,偶有兼容问题 |
| `distroless/static` | ~5 MB | 无 shell,生产推荐 |
| `scratch` | <取决于二进制 | 仅静态链接二进制可运行 |
> [!warning] Alpine 与 musl libc
>
> Alpine 使用 musl libc 而非 glibc。某些 C 扩展(如 `node-gyp`、部分 Python wheel)可能无法编译或运行时行为不一致。Go 服务通过 `CGO_ENABLED=0` 规避了此问题,但 Node.js/Python 应用需谨慎评估。
## 镜像仓库管理与流转
```mermaid
flowchart LR
Dev["开发者本地"] -->|"docker push"| DEV_REPO["dev 仓库<br/>v1.2.3-dev"]
Staging["Staging 验证"] -->|"通过"| PROD_REPO["prod 仓库<br/>v1.2.3"]
K8s["K8s Cluster"] -->|"pull"| PROD_REPO
PR["PR Merge"] --> Tag["打标签 v1.2.3"]
Tag --> ProdRepoMove["移动到 prod 仓库"]
style DEV_REPO fill:#fff3e0
style PROD_REPO fill:#e8f5e9
```
| 仓库方案 | 特点 | 适用场景 |
|---------|------|---------|
| **Harbor** | 自托管,RBAC + 扫描 | 国内企业首选 |
| **ECR / ACR / GCR** | 云厂商托管 | 全云环境 |
| **Docker Hub** | 公共免费 | 开源项目 |
### Harbor 最佳实践
| 实践 | 说明 |
|------|------|
| **项目隔离** | dev/prod 独立项目,不同团队有不同权限 |
| **自动扫描** | 推送时自动触发 Trivy 扫描,阻断高危漏洞 |
| **复制规则** | dev 仓库 → prod 仓库自动复制已通过测试的镜像 |
| **生命周期策略** | 自动清理过期镜像和垃圾数据 |
## 补充:镜像签名与 Cosign
为了防止中间人攻击或被篡改的镜像被拉到集群,可以使用 Sigstore Cosign 对镜像签名:
```bash
# 签名镜像
cosign sign --key cosign.key harbor.example.com/app/server:v1.2.3
# 在 CI 中验证签名
cosign verify --key cosign.pub harbor.example.com/app/server:v1.2.3
# 不依赖密钥的验证( rekor 透明日志)
cosign verify --certificate-identity=email@company.com \
--certificate-oidc-issuer=https://accounts.google.com \
harbor.example.com/app/server:v1.2.3
```
> [!info] 镜像签名 vs 漏洞扫描
>
> 两者解决不同问题:
> - **漏洞扫描** = 这个镜像有没有已知漏洞?
> - **镜像签名** = 这个镜像确实是我们构建的,没有被篡改?
>
> 生产环境应该两者都有。签名可以作为 Gatekeeper/Admission Webhook 的一部分,在 Pod 启动前强制验证镜像签名。
## 关联笔记
- [[../01-容器化/01-Dockerfile最佳实践]] — Dockerfile 中的安全加固
- [[../01-容器化/02-多架构构建]] — Buildx 构建全平台镜像
- [[../hhs/MS/05-部署运维/03-CICD与GitOps]] — CI 流水线中的安全扫描环节