跳到主要内容

容器安全与镜像扫描

1. 镜像漏洞扫描

1.1 Trivy(推荐,开源)

brew install trivy

# 扫镜像
trivy image myapp:latest
trivy image --severity HIGH,CRITICAL myapp:latest
trivy image --ignore-unfixed myapp:latest # 忽略无修复的

# 扫文件系统
trivy fs .

# 扫配置(K8s yaml / Dockerfile)
trivy config .

# 扫 git repo
trivy repo https://github.com/myorg/myapp

CI 集成:

- uses: aquasecurity/trivy-action@master
with:
image-ref: myapp:$}} github.sha }}
severity: HIGH,CRITICAL
exit-code: 1
ignore-unfixed: true

1.2 Snyk

snyk container test myapp:latest
snyk container monitor myapp:latest

1.3 Docker Scout

docker scout cves myapp:latest
docker scout quickview myapp:latest
docker scout recommendations myapp:latest

1.4 Grype

grype myapp:latest

2. 镜像签名

防中间人篡改 + 来源验证。

2.1 Cosign(Sigstore)

# 安装
brew install cosign

# 生成密钥对
cosign generate-key-pair

# 签名
cosign sign --key cosign.key ghcr.io/myorg/myapp@sha256:xxx

# 验证
cosign verify --key cosign.pub ghcr.io/myorg/myapp@sha256:xxx

无密钥(OIDC)签名:

COSIGN_EXPERIMENTAL=1 cosign sign ghcr.io/myorg/myapp@sha256:xxx

K8s 强制只运行已签名镜像(Kyverno / Sigstore Policy Controller):

apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: verify-images
spec:
validationFailureAction: enforce
rules:
- name: check-image
match:
resources: { kinds: [Pod] }
verifyImages:
- imageReferences: ["ghcr.io/myorg/*"]
attestors:
- entries:
- keys:
publicKeys: |
-----BEGIN PUBLIC KEY-----
...
-----END PUBLIC KEY-----

3. 运行时安全

3.1 容器配置加固

详见模块 04 「生产安全与资源限制」。要点:

  • 非 root(USER node
  • 只读文件系统
  • 删 capabilities
  • seccomp 默认 profile
  • 资源限制
  • no-new-privileges
# K8s
securityContext:
runAsNonRoot: true
runAsUser: 1000
readOnlyRootFilesystem: true
allowPrivilegeEscalation: false
capabilities:
drop: [ALL]
seccompProfile:
type: RuntimeDefault

3.2 运行时威胁检测:Falco

监控容器内异常行为(spawn shell、读敏感文件、外联恶意 IP):

helm install falco falcosecurity/falco -n falco --create-namespace

规则示例:

- rule: Shell in Container
desc: Detect shell spawned in container
condition: >
spawned_process and container.id != host
and proc.name in (sh, bash, zsh, ash)
output: Shell in container (}}container.name}})
priority: WARNING

4. K8s Pod Security Standards

baseline / restricted 级别强制(详见模块 05 RBAC):

metadata:
labels:
pod-security.kubernetes.io/enforce: restricted

5. 网络隔离

NetworkPolicy 默认拒绝(详见模块 05):

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny
spec:
podSelector: {}
policyTypes: [Ingress, Egress]

6. Secret 管理

详见模块 05 ConfigMap / Secret 与 Vault 实践:

  • etcd 加密
  • sealed-secrets / external-secrets
  • 不挂 Docker socket
  • Pod 内不调 K8s API(除非必要)

7. 镜像最小化

# ✗ 完整 Ubuntu,几百 MB,CVE 多
FROM ubuntu:22.04

# ✓ Alpine
FROM node:20-alpine

# ✓✓ Distroless 无 shell
FROM gcr.io/distroless/nodejs20-debian12

# ✓✓✓ scratch(Go 二进制)
FROM scratch

镜像越小 = 攻击面越小 + CVE 越少。

8. CI 安全门

- name: Build image
uses: docker/build-push-action@v6
with: { tags: temp:scan }

- name: Trivy scan
uses: aquasecurity/trivy-action@master
with:
image-ref: temp:scan
severity: CRITICAL,HIGH
exit-code: 1 # 高危阻断

- name: Cosign sign
if: success()
run: cosign sign --key env://COSIGN_KEY ghcr.io/myorg/myapp@$DIGEST

- name: Push
uses: docker/build-push-action@v6
with: { tags: ghcr.io/myorg/myapp:v1.0.0, push: true }

9. 常见反模式

  • 不扫描就上线:CVE 累积
  • 以 root 跑容器:逃逸 = 宿主 root
  • 挂 Docker socket:等于给容器宿主管理员权限
  • --privileged:关掉所有安全机制
  • 不签镜像:可能拉到被替换的镜像
  • secret 写镜像:所有 layer 包含
  • 生产装 SSH / 调试工具:扩大攻击面
  • 不限网络:被入侵后横向移动毫无障碍

10. 延伸阅读