用于安全服务的‘Chainguard’镜像

发布: (2026年1月17日 GMT+8 13:28)
9 min read
原文: Dev.to

Source: Dev.to

如果你从事 DevOpssystem‑backend 开发,最大的压力来源之一就是 security。即使它始终位列优先事项之首,其实际内容常常让人捉摸不透。

假设你正在维护一个 Kubernetes 集群或构建 Docker 镜像(大多数 DevOps 工程师至少会涉及其中一种)。即使你的代码本身是安全的,基础镜像 — Debian、Ubuntu、Alpine 等 — 往往带有技术债务,而这些债务可能包含会危及服务的安全风险。这正是 Chainguard 镜像发挥作用的地方。

什么是 Chainguard?

简而言之,Chainguard Images 是“默认安全”的容器镜像,构建于 Wolfi 之上,Wolfi 是专为容器设计的 Linux “undistro”。

与标准 Docker Hub 镜像不同,Chainguard 镜像具有以下几个显著特性:

  • Distroless – 只包含运行应用所需的最小内容。没有 shell、运行时没有包管理器,也没有不必要的臃肿。
  • Daily Rebuilds – 每个镜像每天都会从上游源代码重新构建,以便立即修补漏洞。
  • SBOMs & Signing – 镜像默认附带软件材料清单(Software Bill of Materials)和 Sigstore 签名。

对决:官方 vs. Chainguard

最直接的好处是降低噪声。下面是我使用 Trivy 在标准 Python 镜像和 Chainguard 等价镜像上进行的比较。

镜像漏洞
官方 (python:3.11)> 300 个漏洞,包括 “Critical”(严重)和 “High”(高)等级
Chainguard (cgr.dev/chainguard/python:latest)0 个 CVE

这不是魔法;而是积极的极简主义。通过移除应用不使用的操作系统组件,你可以显著缩小攻击面。

实践:迁移指南

迁移并不总是一次简单的替换,尤其是使用 Chainguard 的无发行版(distroless)镜像时。由于它们在运行时缺少 shell 和包管理器,你必须使用 多阶段构建

工具限制

一个典型(且略有漏洞)的 Dockerfile 可能如下所示:

# Standard Python Image
FROM python:3.9-slim

WORKDIR /app

# Installing dependencies
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

COPY . .

# Running as root (default)
CMD ["python", "app.py"]

使用 Chainguard 的迁移后版本

# 1️⃣ Builder stage
# Use the `-dev` tag because we need a shell and build tools (gcc, headers, etc.)
FROM cgr.dev/chainguard/python:latest-dev AS builder

WORKDIR /app

# Create a virtual environment
RUN python -m venv /app/venv
ENV PATH="/app/venv/bin:$PATH"

COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

# 2️⃣ Runtime stage
# This image has no shell or package manager; it is pure runtime.
FROM cgr.dev/chainguard/python:latest

WORKDIR /app

# Copy the virtual environment from the builder
COPY --from=builder /app/venv /app/venv
COPY . .

# Use the virtualenv
ENV PATH="/app/venv/bin:$PATH"

# Chainguard runs as a non‑root user (`nonroot`) by default.
# No need to create a user manually.
CMD ["python", "app.py"]

常见问题与排查

问题说明解决方案
“我无法 exec 进入 pod!”运行时镜像没有 shell(/bin/shbash)。使用临时调试容器,或暂时切换到 -dev 标签进行调试。
权限Chainguard 强制非 root 执行。写入 / 或在运行时安装软件包会失败。确保应用仅写入可写位置(如 /tmp 或挂载的卷)。
缺少 sudo镜像中不包含 sudo,运行时也没有包管理器。builder 阶段执行任何特权操作(如有需要使用 USER root),并设计应用在运行时无需 root。

按照设计,Chainguard 镜像省略了 sudo(以及大多数包管理器),以遵循最小特权原则。它们默认以预配置的非 root 用户(UID 65532)运行,从而消除整类特权提升攻击。

解决方案: 将特权任务转移到 构建 阶段。尽可能重构你的应用,使其在运行时不需要 root。如果必须执行 root 级别的任务(例如安装系统依赖),请在多阶段构建中使用 USER root 指令完成,然后在最终镜像中切换回非 root 用户。

“仅最新”软件包哲学

Chainguard 底层的软件包生态系统 Wolfi 采用 滚动发布(Rolling Release) 模型,这对软件包版本化提出了特定限制。

  • 固定仓库约束 – Chainguard 镜像仅从受信任的 Wolfi 或 Chainguard 仓库拉取。强烈不建议添加第三方或未经验证的仓库,以保持 “Zero CVE” 保证。
  • 仅最新规则 – 公共 Wolfi 仓库通常只保留软件包的最新稳定版本。尝试固定旧版本(例如 apk add openssl=1.1.1)会导致 “Unsatisfiable constraints” 错误,因为该版本已被移除,以防止使用存在漏洞的软件。

哲学: Chainguard 强制你使用最新、经过审查的软件包,降低了遗留漏洞的风险。

结论

Chainguard 镜像为容器化工作负载提供了 安全、精简且可复现 的基础。其权衡在于工作流的转变:您必须采用多阶段构建,拥抱非 root 执行,并依赖最新的经过审查的包。调整后,收益是显著降低的漏洞面以及安全扫描工具中大幅减少的噪声。

“仅最新”方法确保您不会在不知情的情况下将已知漏洞嵌入镜像中。如果您的系统绝对需要使用遗留的、已到生命周期结束(EOL)的版本,您可能需要考虑其企业版,它提供了用于旧版已修补镜像的私有仓库。

“遗留版本”维护的陷阱

团队坚持使用旧的 Docker 镜像(例如 node:14python:3.6)用于生产级服务的最大原因之一是 稳定性

“它能工作,请不要动它。”

在标准的 Docker 环境中,将版本固定为 python:3.6‑slim 意味着底层操作系统(通常是旧的 Debian 发行版)不再接收安全更新。你实际上坐在一个随时可能爆炸的 OS 级别漏洞定时炸弹上。

大家都知道需要采取行动,但迁移往往并非简单的代码修改。它需要大量测试并考虑无数使用场景。Chainguard 改变了这一范式:即使你使用特定的语言版本,Chainguard 也会 每天 重新构建底层的 Wolfi OS 层。

  • 好处: 你可以获得语言版本的稳定性,同时拥有前沿 OS 的安全性。
  • 坏处: 镜像哈希每天都会变化。依赖长期保持不变的 SHA 摘要的流水线将会中断;你需要接受 滚动标签
  • 成本: 对于已到生命周期终点的语言版本(例如 Python 3.7 或 Java 8),Chainguard 通常会将这些镜像迁移到付费层。免费层专注于当前受支持的版本。
Back to Blog

相关文章

阅读更多 »

后端转向 AI 开发

在使用 LLMs 之后,我认为后端工程师转型中最难的部分不是数学——而是要摆脱 determinism。在传统的 distributed ...

你知道吗?

云不仅仅是技术;它正在改变企业的运营方式。公司现在可以更快地推出产品,瞬间扩展服务,并且触及全球……