关于 container-security
container-security 是面向使用 Azure Container Registry 构建容器镜像的团队的实用技能。它说明从导入基础镜像、构建、用 Trivy 扫描和分析问题,到加固 Dockerfile、重建并验证的流程。
主要功能
- 01将基础镜像导入 ACR
- 02使用 ACR 构建镜像
- 03用 Trivy 扫描镜像和 Dockerfile
- 04分类 CVE 并评估修复选项
- 05加固 Dockerfile 配置
- 06重建并验证镜像安全性
适用场景
- 01避免 ACR 云构建遇到 Docker Hub 限流
- 02审查并排序容器镜像漏洞
- 03加固 SSH 访问和容器运行权限
- 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