容器安全最佳实践

全面讲解容器安全生命周期:镜像安全(Distroless/多阶段构建)、运行时防护(seccomp/AppArmor/Capabilities)、容器扫描(Trivy/Snyk)与 Pod Security Standards 实践。

容器已成为现代应用部署的标准载体,但容器的轻量和共享内核特性也带来了新的安全挑战。本文从镜像构建到运行时防护,系统讲解容器安全的最佳实践。


1. 容器安全生命周期

┌─────────────────────────────────────────────────────────────┐
│                容器安全生命周期                               │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  开发        构建        分发        运行        销毁       │
│   │          │          │          │          │            │
│   ▼          ▼          ▼          ▼          ▼            │
│ 依赖扫描   镜像扫描   签名验证   运行时防护   审计清理       │
│ SAST/SCA   Trivy     Cosign    Falco       日志归档        │
│                                                            │
└─────────────────────────────────────────────────────────────┘

2. 镜像安全

2.1 最小镜像原则

# ❌ 不安全:包含 shell、包管理器、调试工具
FROM ubuntu:22.04
RUN apt-get update && apt-get install -y python3 curl
COPY app.py /app/
CMD ["python3", "/app/app.py"]

# ✅ 安全:Distroless,无 shell、无包管理器
FROM python:3.11-slim AS builder
WORKDIR /app
COPY requirements.txt .
RUN pip install --user --no-cache-dir -r requirements.txt

FROM gcr.io/distroless/python3-debian12
WORKDIR /app
COPY --from=builder /root/.local /home/nonroot/.local
COPY app.py .
USER nonroot:nonroot
ENV PATH=/home/nonroot/.local/bin:$PATH
CMD ["app.py"]
基础镜像大小Shell包管理器适用
Ubuntu/Debian~80MB开发调试
Alpine~5MBapk权衡选择
Distroless~20MB生产推荐
Scratch~0MBGo 静态编译

2.2 多阶段构建

# 编译阶段(包含编译工具)
FROM golang:1.21-alpine AS build
WORKDIR /src
COPY . .
RUN CGO_ENABLED=0 go build -o /bin/app ./cmd/app

# 最终阶段(仅二进制)
FROM scratch
COPY --from=build /bin/app /app
COPY --from=build /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/
ENTRYPOINT ["/app"]

2.3 镜像扫描

# Trivy 扫描
trivy image myapp:latest

# 只关注严重/高危
trivy image --severity CRITICAL,HIGH myapp:latest

# 镜像签名(Cosign)
cosign generate-key-pair

cosign sign --key cosign.key myregistry/myapp:latest

cosign verify --key cosign.pub myregistry/myapp:latest

3. Dockerfile 安全基线

# ✅ 使用官方镜像,指定具体版本
FROM python:3.11.6-slim-bookworm

# ✅ 创建非 root 用户
RUN groupadd -r appgroup && useradd -r -g appgroup appuser

# ✅ 设置工作目录
WORKDIR /app

# ✅ 先复制依赖,利用缓存层
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

# ✅ 再复制应用代码
COPY --chown=appuser:appgroup . .

# ✅ 只暴露需要的端口
EXPOSE 8080

# ✅ 切换到非 root 用户
USER appuser:appgroup

# ✅ 使用 HEALTHCHECK
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s \
  CMD curl -f http://localhost:8080/health || exit 1

# ✅ 明确 ENTRYPOINT/CMD
ENTRYPOINT ["python"]
CMD ["app.py"]

3.1 Dockerfile 安全检查清单

检查项说明
使用特定版本标签不用 latest
最小基础镜像Distroless/Alpine/Scratch
非 root 运行USER 指令
不暴露不必要端口最小化攻击面
敏感数据不入镜像用 Secret/环境变量
使用 COPY 而非 ADDADD 会自动解压 URL
多阶段构建分离编译时依赖
扫描依赖漏洞SCA 工具

4. Linux 安全机制

4.1 Capabilities(能力)

# 默认 Docker 容器会 drop 大部分 capabilities
# 只保留必要的:

# 查看容器 capabilities
docker run --rm alpine:latest capsh --print

# 运行容器时移除所有 capabilities,只添加需要的
docker run --cap-drop=ALL --cap-add=NET_BIND_SERVICE nginx

# Kubernetes
capabilities:
  drop:
    - ALL
  add:
    - NET_BIND_SERVICE

常见 Capabilities:

能力说明需要场景
NET_BIND_SERVICE绑定 < 1024 端口非 root 运行 nginx
NET_ADMIN网络管理VPN/路由
SYS_TIME修改系统时间NTP
SYS_PTRACE进程跟踪调试工具

4.2 seccomp(安全计算模式)

// 自定义 seccomp 配置(限制系统调用)
{
  "defaultAction": "SCMP_ACT_ERRNO",
  "syscalls": [
    {
      "names": ["accept", "bind", "connect", "listen", "socket"],
      "action": "SCMP_ACT_ALLOW"
    }
  ]
}
# Docker 使用自定义 seccomp
docker run --security-opt seccomp=custom-seccomp.json myapp

# Kubernetes
securityContext:
  seccompProfile:
    type: Localhost
    localhostProfile: profiles/custom.json

4.3 AppArmor

# 查看当前 AppArmor 状态
sudo aa-status

# Docker 使用 AppArmor 策略
docker run --security-opt apparmor=docker-default nginx

# Kubernetes
metadata:
  annotations:
    container.apparmor.security.beta.kubernetes.io/nginx: runtime/default

4.4 SELinux

# Docker 使用 SELinux
docker run --security-opt label=type:container_t nginx

5. Kubernetes Pod 安全

5.1 Pod Security Standard(PSS)

Kubernetes 1.23+ 提供三种安全级别:

级别策略适用
Privileged无限制系统/管理 Pod
Baseline最小限制一般应用
Restricted最严格安全敏感应用
apiVersion: v1
kind: Namespace
metadata:
  name: production
  labels:
    pod-security.kubernetes.io/enforce: restricted
    pod-security.kubernetes.io/enforce-version: latest
    pod-security.kubernetes.io/audit: restricted
    pod-security.kubernetes.io/warn: restricted
---
apiVersion: v1
kind: Pod
metadata:
  name: secure-app
  namespace: production
spec:
  securityContext:
    runAsNonRoot: true
    seccompProfile:
      type: RuntimeDefault
    fsGroup: 1000
  containers:
    - name: app
      image: myapp:1.0
      securityContext:
        allowPrivilegeEscalation: false
        readOnlyRootFilesystem: true
        capabilities:
          drop:
            - ALL
        runAsUser: 1000
        runAsGroup: 1000
      resources:
        limits:
          memory: "256Mi"
          cpu: "500m"
      volumeMounts:
        - name: tmp
          mountPath: /tmp
  volumes:
    - name: tmp
      emptyDir: {}

5.2 Kyverno 策略引擎

apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  name: require-non-root
spec:
  validationFailureAction: enforce
  rules:
    - name: check-runasnonroot
      match:
        resources:
          kinds:
            - Pod
      validate:
        message: "Pod 必须设置 runAsNonRoot: true"
        pattern:
          spec:
            securityContext:
              runAsNonRoot: true

6. 运行时安全监控

6.1 Falco

# falco-rule.yaml
- rule: Terminal Shell in Container
  desc: Detect shell spawned in container
  condition: spawned_process and container and shell_procs
  output: >
    Shell spawned in container
    (user=%user.name container=%container.name shell=%proc.name)
  priority: WARNING

- rule: Unauthorized K8s API Access
  desc: Detect access to K8s API from unexpected sources
  condition: >
    k8s_audit and k8s_audit_object_resource=pods
    and not (ka.auth.decision=allow and authorized_user)
  output: Unauthorized K8s API access
  priority: CRITICAL
# 运行 Falco
docker run -d --name falco \
  --privileged \
  -v /var/run/docker.sock:/host/var/run/docker.sock \
  -v /dev:/host/dev \
  -v /proc:/host/proc:ro \
  -v /boot:/host/boot:ro \
  -v /lib/modules:/host/lib/modules:ro \
  -v /usr:/host/usr:ro \
  falcosecurity/falco:latest

6.2 运行时安全检查清单

检查项工具/方法
异常进程创建Falco
文件完整性监控AIDE/Tripwire
网络连接异常Falco/Network Policy
权限提升尝试Falco audit
敏感文件访问Falco
容器逃逸检测Falco + 内核审计

7. 总结

容器安全的 Defense in Depth:

应用层 ──► 安全编码、依赖扫描
    │
镜像层 ──► 最小镜像、多阶段构建、镜像扫描、签名验证
    │
编排层 ──► Pod Security Standard、Network Policy、RBAC
    │
运行时 ──► seccomp、AppArmor/SELinux、Capabilities、Falco
    │
主机层 ──► 主机加固、容器运行时安全、内核安全

核心原则:

  1. 最小权限:容器只能做必须的事
  2. 最小镜像:减少攻击面
  3. 不可变基础设施:镜像只读,配置外部化
  4. 持续扫描:从开发到运行全程监控
  5. 快速响应:漏洞发现后立即修复重建

继续阅读

探索更多技术文章

浏览归档,发现更多关于系统设计、工具链和工程实践的内容。

全部文章 返回首页

「安全」更多文章

  1. Kubernetes安全体系:RBAC、PodSecurity与NetworkPolicy实战
  2. 安全合规与数据保护
  3. 渗透测试与红蓝对抗