mcpField
C
container-security

container-security

github.com/julianobarbosa安全1462 次安装3 天前更新
代码仓库

关于 container-security

container-security 是面向使用 Azure Container Registry 构建容器镜像的团队的实用技能。它说明从导入基础镜像、构建、用 Trivy 扫描和分析问题,到加固 Dockerfile、重建并验证的流程。

主要功能

  1. 01将基础镜像导入 ACR
  2. 02使用 ACR 构建镜像
  3. 03用 Trivy 扫描镜像和 Dockerfile
  4. 04分类 CVE 并评估修复选项
  5. 05加固 Dockerfile 配置
  6. 06重建并验证镜像安全性

适用场景

  1. 01避免 ACR 云构建遇到 Docker Hub 限流
  2. 02审查并排序容器镜像漏洞
  3. 03加固 SSH 访问和容器运行权限
  4. 04重建镜像后检查安全变更

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/julianobarbosa/claude-code-skills --skill container-security

安装后在 Claude Code 中输入/container-security确认已加载。

附带文件evals/evals.json

详细介绍

容器镜像安全

确保容器镜像安全的完整工作流:扫描、分析、加固、验证。

工作流概览

Import base image to ACR → Build → Scan with Trivy → Analyze CVEs → Harden Dockerfile → Rebuild → Re-scan → Verify

1. 将基础镜像导入 ACR

将基础镜像导入私有 ACR,避免 Docker Hub 速率限制。Azure 的基础设施会代为拉取,无需 Docker Hub 身份验证。

# Import a public image into ACR
az acr import --name <registry> \
  --source docker.io/<image>:<tag> \
  --image <local-path>/<image>:<tag>

# Example: import code-server
az acr import --name example-app \
  --source docker.io/codercom/code-server:4.107.1 \
  --image addons/code-server:4.107.1

# Verify
az acr repository show --name <registry> --repository <local-path>/<image>

然后更新 Dockerfile 中的 FROM,使其指向 ACR 中的副本:

# Before (hits Docker Hub rate limits in ACR cloud builds)
FROM codercom/code-server:latest

# After (pulls from local ACR — no rate limit)
FROM example-app.azurecr.io/addons/code-server:4.107.1

重要:ACR 云构建(az acr build)访问 Docker Hub 时不会进行身份验证。任何引用 Docker Hub 的 FROM 最终都会遇到速率限制。请务必先导入镜像。

2. 使用 ACR 构建

az acr build --registry <registry> --image <repo>:<tag> -f Dockerfile .

ACR 构建器限制——不支持以下 Docker 功能:

  • COPY <<'EOF' heredoc 语法(仅限 BuildKit)——请改用 RUN printf 或 RUN cat
  • 多平台构建需要 --platform 标志
  • BuildKit 专用的 RUN --mount 指令

3. 使用 Trivy 扫描

选项 A:通过 ACR Task 使用 Trivy(推荐用于 CI)

首先,将 Trivy 本身导入 ACR(仅需一次):

az acr import --name <registry> \
  --source docker.io/aquasec/trivy:latest \
  --image tools/trivy:latest

然后扫描:

# Table format for human review
az acr run --registry <registry> \
  --cmd "<registry>.azurecr.io/tools/trivy:latest image \
    --severity HIGH,CRITICAL \
    <registry>.azurecr.io/<image>:<tag>" /dev/null

# JSON format for programmatic analysis
az acr run --registry <registry> \
  --cmd "<registry>.azurecr.io/tools/trivy:latest image \
    --severity HIGH,CRITICAL --format json \
    <registry>.azurecr.io/<image>:<tag>" /dev/null
选项 B:在本地使用 Trivy(需要 Docker 守护进程)
az acr login --name <registry>
trivy image --severity HIGH,CRITICAL <registry>.azurecr.io/<image>:<tag>
选项 C:在本地 Dockerfile 上使用 Trivy(无需构建)
trivy config --severity HIGH,CRITICAL,MEDIUM Dockerfile

4. 分析 CVE 发现项

对每项 CRITICAL 和 HIGH 发现项进行分类:

类别操作示例
我们可以修复在 Dockerfile 中固定到较新版本使用旧版 Go 标准库构建的工具二进制文件
上游可以修复跟踪、记录并重新评估基础镜像包含存在漏洞的内部依赖项
操作系统级别,补丁待发布记录并监控 Debian/Ubuntu 跟踪器libsqlite3、openssl
will_not_fix接受风险或寻找替代软件包Debian 中的 zlib1g

对于 JSON 输出,提取 CRITICAL 摘要:

import json
data = json.load(open('trivy-results.json'))
for result in data.get('Results', []):
    for v in result.get('Vulnerabilities', []):
        if v.get('Severity') == 'CRITICAL':
            print(f"{v['VulnerabilityID']} | {v['PkgName']} {v.get('InstalledVersion','')} | fix: {v.get('FixedVersion','')} | {v.get('Status','')}")

5. Dockerfile 加固检查清单

固定版本(消除可复现性 CVE)
# Bad — unpinned, non-reproducible, may pull vulnerable versions
FROM image:latest
RUN curl .../releases/latest/download/tool | bash

# Good — pinned, reproducible, auditable
FROM registry.azurecr.io/addons/image:4.107.1

ARG TOOL_VERSION=v1.2.3
RUN curl -fsSL "https://github.com/org/tool/releases/download/${TOOL_VERSION}/tool_linux_amd64.tar.gz" \
    | tar xz -C /usr/local/bin tool

使用 ARG 定义版本变量——更新时只需修改一行,并且可在 docker history 中查看。

SSH 加固
# Disable password auth, enable key-based only
RUN mkdir -p /run/sshd && \
    sed -i 's/#PasswordAuthentication yes/PasswordAuthentication no/' /etc/ssh/sshd_config && \
    sed -i 's/#PubkeyAuthentication yes/PubkeyAuthentication yes/' /etc/ssh/sshd_config && \
    sed -i 's/#PermitRootLogin prohibit-password/PermitRootLogin no/' /etc/ssh/sshd_config && \
    echo "AllowUsers <user>" >> /etc/ssh/sshd_config && \
    ssh-keygen -A && \
    mkdir -p /home/<user>/.ssh && \
    chmod 700 /home/<user>/.ssh && \
    chown <user>:<user> /home/<user>/.ssh
以非 root 用户运行
# Start privileged services as root, then drop privileges
RUN printf '#!/bin/bash\nset -e\n/usr/sbin/sshd\nexec su - <user> -c "<main-process>"\n' \
    > /usr/local/bin/entrypoint.sh && \
    chmod +x /usr/local/bin/entrypoint.sh

ENTRYPOINT ["/usr/local/bin/entrypoint.sh"]

如果不需要特权服务,只需:

USER <non-root-user>
ENTRYPOINT ["<main-process>"]
其他加固措施
  • 尽量减少层数:合并相关的 RUN 命令
  • 清理 apt 缓存:始终以 && rm -rf /var/lib/apt/lists/* 结尾
  • 不要在镜像中存放密钥:使用运行时注入(环境变量、挂载的密钥)
  • 验证下载内容:尽可能使用校验和或 GPG 验证二进制文件
  • 只读文件系统:尽可能在运行时添加 --read-only

6. 重新构建并重新扫描

加固后,务必重新构建并重新扫描,以验证修复效果:

# Rebuild with new tag
az acr build --registry <registry> --image <repo>:<new-tag> -f Dockerfile .

# Re-scan
az acr run --registry <registry> \
  --cmd "<registry>.azurecr.io/tools/trivy:latest image \
    --severity HIGH,CRITICAL \
    <registry>.azurecr.io/<repo>:<new-tag>" /dev/null

# Compare CRITICAL counts: before vs after

7. 验证检查清单

完成安全流程后,验证以下各项:

  • az acr repository show — ACR 中存在基础镜像
  • az acr build — 构建完成,且未出现速率限制错误
  • Trivy 扫描 — CRITICAL 数量减少(记录剩余的上游 CVE)
  • az acr repository show — ACR 中存在最终镜像
  • Dockerfile 使用固定版本(工具未使用 :latest)
  • SSH 配置为仅允许密钥身份验证(如适用)
  • 容器以非 root 用户身份运行
  • 镜像层中未嵌入密钥

常见模式

速率限制恢复

当 az acr import 也遇到速率限制时(突发导入时可能发生),请等待 15 分钟,或使用经过身份验证的 Docker Hub 帐户:

az acr import --name <registry> \
  --source docker.io/<image>:<tag> \
  --image <local-path>/<image>:<tag> \
  --username <dockerhub-user> --password <dockerhub-token>
固定版本的多工具 Dockerfile
ARG K9S_VERSION=v0.50.18
ARG ARGOCD_VERSION=v3.3.3
ARG YQ_VERSION=v4.52.4
ARG KUSTOMIZE_VERSION=v5.8.0

RUN curl -fsSL "https://github.com/derailed/k9s/releases/download/${K9S_VERSION}/k9s_Linux_amd64.tar.gz" | tar xz -C /usr/local/bin k9s
RUN curl -sSL -o /usr/local/bin/argocd "https://github.com/argoproj/argo-cd/releases/download/${ARGOCD_VERSION}/argocd-linux-amd64" && chmod +x /usr/local/bin/argocd
RUN curl -fsSL "https://github.com/mikefarah/yq/releases/download/${YQ_VERSION}/yq_linux_amd64" -o /usr/local/bin/yq && chmod +x /usr/local/bin/yq
RUN curl -fsSL "https://github.com/kubernetes-sigs/kustomize/releases/download/kustomize%2F${KUSTOMIZE_VERSION}/kustomize_${KUSTOMIZE_VERSION}_linux_amd64.tar.gz" | tar xz -C /usr/local/bin kustomize

易踩坑

  • RUN apt-get upgrade 不会更新 Trivy 的 CVE 数据库,只会更新已安装的软件包: 重建后镜像仍显示为红色,因为 Trivy 会根据自身数据库比对软件包版本。使用 --db-repository 固定扫描器数据库版本,并从新导入的基础镜像重新构建。
  • ACR 云端构建不会向 Docker Hub 进行身份验证: 任何 FROM docker.io/... 都能成功构建几次,随后就会触发匿名拉取限流(每个 IP 每 6 小时 100 次,与 Azure 的出站 NAT 共享额度)。务必先执行 az acr import——症状是间歇性出现 toomanyrequests 错误,而且“重试后就能成功”。
  • COPY <<'EOF' heredoc 在 ACR 构建器中会失败,但在本地可以正常工作: ACR 使用经典 Docker 构建,而不是 BuildKit。在笔记本电脑上可以正常构建的 heredoc 语法,在 CI 中会因 unexpected EOF 而失败。请使用 RUN printf,或通过 COPY 从上下文暂存文件。
  • Trivy 的 --severity HIGH,CRITICAL 会隐藏可修复的 MEDIUM 级发现: 过滤会丢失软件包级补丁的线索,而这些补丁比显眼的 CRITICAL 问题更容易解决。每次发布时先运行一次不过滤的扫描,以掌握完整情况,然后再筛选以便分诊。
  • 非 root 的 USER 指令不适用于多阶段构建中的 COPY --from: 在不同阶段之间复制的文件会保留源阶段的 UID/GID。最终阶段使用非 root 用户时,如果复制了归 root 用户所有的二进制文件,运行时会导致 exec 失败。请显式使用 COPY --chown=<user>。
  • Debian 标记为 will_not_fix 的 CVE 也不会通过升级镜像得到修复: 标记为 will_not_fix 的 zlib1g、libssl 等软件包会随每个 Debian 版本一同发布。更换基础镜像标签没有帮助——只有更换发行版(distroless、alpine、ubi)才行。记录并接受风险,不要继续追查。

评论

支持 Markdown