Docker 容器不是天然安全的:默认以 root 运行、镜像可能包含漏洞、构建时 Secret 泄露。本文覆盖 Docker 生产环境的安全加固全系列方案,从镜像扫描、Secret 管理到运行时隔离与监控,构建容器安全的纵深防御体系。
一、镜像安全扫描
容器安全的起点在于镜像本身。一个基础镜像可能携带数千个已知 CVE,这些漏洞在构建阶段即被植入,若未经扫描便投入生产,相当于将攻击面直接开放给了外部威胁。
1.1 为什么镜像扫描是第一步
容器镜像本质上是一个扁平化的文件系统快照,包含了操作系统包、库文件、运行时依赖以及应用程序代码。如果基础镜像中的 glibc、OpenSSL 或 libcurl 存在已知漏洞,那么基于该镜像构建的所有服务都会继承同样的风险。2024 年的统计报告显示,超过 70% 的公开 Docker 镜像至少包含一个可被利用的高危 CVE。
1.2 Trivy — 最受欢迎的开源扫描器
Trivy 由 Aqua Security 开发,支持镜像、文件系统、Git 仓库等多种扫描目标,拥有最快的扫描速度之一。
# 安装 Trivy
curl -sfL https://raw.githubusercontent.com/aquasecurity/trivy/main/contrib/install.sh | sh
# 扫描本地镜像
trivy image my-app:latest
# 扫描特定严重级别并输出为 JSON
trivy image --severity HIGH,CRITICAL \
--format json \
--output trivy-report.json \
my-app:latest
# 扫描公开镜像仓库中的镜像
trivy image alpine:3.18
Trivy 默认扫描以下数据源:Distro 包漏洞(如 Alpine .apk、Debian .deb)、NPM / PIP / Maven 依赖漏洞、不安全的 Dockerfile 配置(如以 root 运行)、以及 secret 泄露(GitHub tokens 等)。
1.3 Snyk — 商业级安全平台
Snyk 在开源社区提供 generous free tier,适合个人项目和中小团队。
# 安装 Snyk
npm install -g snyk
snyk auth
# 容器镜像扫描
snyk container test my-app:latest --severity-threshold=high
# 监控镜像持续跟踪新漏洞
snyk container monitor my-app:latest --project-name=production-api
Snyk 的优势在于其修复建议功能,不仅能告诉你哪个包存在漏洞,还能通过自动化 PR 修复依赖。对于 Node.js 和 Python 项目尤其有用。
1.4 Docker Scout — Docker 官方方案
Docker Scout 随 Docker Desktop 和 Docker Hub 集成,无需额外安装。
# 快速查看镜像安全概要
docker scout quickview my-app:latest
# 查看 CVE 详情(含 CVSS 分数)
docker scout cves --only-packages openssh,openssl my-app:latest
# 比较两个镜像版本之间的漏洞变化
docker scout compare --to my-app:v1.0 my-app:v1.1
1.5 CI/CD 集成扫描
将镜像扫描嵌入 CI/CD 是防止漏洞进入生产环境的关键手段。以下是一个 GitHub Actions 示例:
# .github/workflows/image-scan.yml
name: Image Security Scan
on: [push]
jobs:
scan:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Build image
run: docker build -t my-app:${{ github.sha }} .
- name: Run Trivy scan
uses: aquasecurity/trivy-action@master
with:
image-ref: 'my-app:${{ github.sha }}'
severity: 'CRITICAL,HIGH'
exit-code: '1'
ignore-unfixed: true
上述配置在发现严重或高危漏洞时会中断 CI 流程,确保问题在合并前解决。
二、运行时安全加固
镜像层面的安全只是第一道防线,容器运行时的配置同样关键。Docker 默认运行参数较为宽松,一个错误配置可能导致容器逃逸、资源耗尽乃至宿主机被攻陷。
2.1 非 root 运行
Docker 默认以 root(UID = 0)运行容器内的主进程,这带来极大风险:若应用程序存在命令注入漏洞,攻击者可以直接获得容器内的 root 权限。
# 正确的做法:在 Dockerfile 中创建非 root 用户
FROM node:20-alpine
# 创建用户组和用户
RUN addgroup -S appgroup && adduser -S appuser -G appgroup
# 设置工作目录并赋予非 root 用户所有权
WORKDIR /app
COPY --chown=appuser:appgroup package*.json ./
RUN npm ci
COPY --chown=appuser:appgroup . .
# 切换到非 root 用户
USER appuser
EXPOSE 3000
CMD ["node", "server.js"]
# 验证容器内进程不以 root 运行
docker run --rm -it my-app id
# 输出应为:uid=1000(appuser) gid=1000(appgroup) groups=1000(appgroup)
常见错误包括创建了用户但未切换 USER 指令,或者在 COPY 时忘记赋予非 root 用户文件所有权,导致应用无法读取或写入数据。务必在构建时使用 --chown 一次性解决权限问题。
2.2 只读文件系统
许多攻击向量(如写入 webshell、修改可执行文件)依赖于文件系统的可写性。将容器根文件系统设为只读可以大幅缩小攻击面。
# 启动只读容器,同时挂载临时可写目录用于日志/缓存
docker run \
--read-only \
-v /tmp:/tmp \
-v /app/logs:/app/logs \
-e LOG_PATH=/app/logs \
my-app:latest
应用程序需要区分两类写入需求:运行时临时文件应写入 /tmp,持久化数据通过卷挂载到外部。若应用在只读环境中崩溃,说明存在对容器内路径的非法写入,应及时修复。
2.3 资源限制(防 DoS)
未限制资源的容器可能被恶意流量或 bug 拖垮整个宿主机。
# CPU、内存、swap、PID 限制
docker run \
--memory=512m \
--memory-swap=512m \
--cpus=1.0 \
--pids-limit=100 \
my-app:latest
--pids-limit 经常被忽略,但它能够有效防止 fork 炸弹攻击。建议对每个生产容器同时设置内存、CPU 和 PID 上限。
2.4 禁用特权模式
--privileged 授予容器对宿主设备的完全访问权限,相当于在容器内获得了实质上的宿主机 root 能力,绝大多数场景下毫无必要。
# ❌ 极度危险:容器获得宿主机 root 权限和设备访问
docker run --privileged my-app
# ✅ 正确的做法:仅授予必要的 capabilities
docker run \
--cap-drop=ALL \
--cap-add=NET_BIND_SERVICE \
--cap-add=SETUID \
my-app
--cap-drop=ALL 先剥夺全部 capabilities,再通过 --cap-add 逐条加回真正需要的权限。这是能力最小化原则的实际应用。
三、Secret 管理
将密码、API 密钥或数据库连接字符串硬编码到 Docker 镜像或环境变量中是安全事故的高频原因。BuildKit Secret 和运行时 Secret 机制是规避这些风险的正确方式。
3.1 BuildKit Secret(构建时密钥不落入镜像层)
Docker 镜像的每一层都是可读的,曾经写入 .npmrc 或 id_rsa 的层即使后续被删除,仍然存在镜像历史中被读取的风险。BuildKit 的 Secret mount 机制能将敏感文件在构建时挂载到内存中,构建结束后不留痕迹。
# syntax=docker/dockerfile:1
FROM node:20-alpine
WORKDIR /app
COPY package*.json ./
RUN --mount=type=secret,id=npmrc,target=/root/.npmrc \
npm ci --prefer-offline
COPY . .
RUN npm run build
# 构建时传入 secret,不会写入任何镜像层
DOCKER_BUILDKIT=1 docker build \
--secret id=npmrc,src=$HOME/.npmrc \
--secret id=aws,src=$HOME/.aws/credentials \
-t my-app:v1.0 .
# 构建后验证 secret 不在镜像中
docker run --rm my-app:v1.0 cat /root/.npmrc
# 应输出 cat: can't open '/root/.npmrc': No such file or directory
3.2 运行时 Secret(Docker Swarm / Kubernetes)
构建阶段的安全并不能替代运行时的安全。运行时密码不应以环境变量出现,而应使用 Docker Swarm Secret 或 Kubernetes Secret 机制注入。
# Docker Swarm Secret 示例
echo "my-super-secret-password" | docker secret create db_password -
# 创建服务并绑定 Secret
docker service create \
--name my-api \
--secret db_password \
--secret source=ca_bundle,target=/run/secrets/ca.crt \
my-app:latest
# 在容器内部,secret 以文件形式挂载到 /run/secrets/
docker exec <container_id> cat /run/secrets/db_password
在 Kubernetes 中,更推荐将 Secret 以卷挂载方式注入,同时配合 secrets-csi-driver 实现与外部密钥管理系统(AWS Secrets Manager、Azure Key Vault)的动态同步。
四、私有 Registry(Harbor)
将镜像推送至 Docker Hub 或其他公开仓库时,企业面临知识产权泄露、供应链污染和访问控制缺失等风险。自建私有 Registry 是隔离和安全管理镜像的必由之路。
4.1 Harbor — 企业级 Registry
Harbor 由 VMware 开源,支持漏洞扫描、镜像签名、基于角色的访问控制(RBAC)以及复制策略。
# 下载并配置 Harbor
curl -L https://github.com/goharbor/harbor/releases/download/v2.10.0/harbor-offline-installer-v2.10.0.tgz \
-o harbor-offline-installer.tgz
tar xvf harbor-offline-installer.tgz
cd harbor
cp harbor.yml.tmpl harbor.yml
# 编辑 harbor.yml 配置主机名和 HTTPS 证书
# hostname: harbor.example.com
# https.certificate: /your/cert/path
# 安装并启动
sudo ./install.sh --with-trivy
# 查看服务状态
docker-compose -f docker-compose.yml ps
4.2 推送镜像到 Harbor
# 登录到 Harbor Registry
docker login harbor.example.com
# 标记镜像
docker tag my-app:v1.0 harbor.example.com/project-a/my-app:v1.0
# 推送镜像
docker push harbor.example.com/project-a/my-app:v1.0
# 在 Harbor UI 上查看镜像及其扫描结果
4.3 Harbor 安全策略配置
在 Harbor 的「项目设置」中,启用以下关键安全策略:
- 镜像漏洞扫描:设置为推送后自动扫描,设定阻止存在高危以上漏洞的镜像被拉取
- 不可变标签(Immutable Tag):防止有意义的版本号被覆盖攻击
- 签名策略:要求所有镜像携带 Cosign 或 Notary 签名
- Cosign 公钥白名单:仅允许使用预先注册的公钥签署的镜像
五、Linux 安全机制详解
Docker 容器本质上是利用 Linux 内核特性(cgroups、namespaces、capabilities 等)构建的隔离环境。深入理解并正确配置这些安全原语,才能实现真正的容器加固。
5.1 seccomp — 系统调用过滤
seccomp(secure computing mode)是 Linux 内核的沙箱机制,通过白名单限制进程可使用的系统调用。Docker 默认启用一个包含约 300 个允许调用的 seccomp 配置文件,但某些场景需要自定义。
// my-seccomp.json — 自定义 seccomp 配置文件
{
"defaultAction": "SCMP_ACT_ERRNO",
"syscalls": [
{
"names": ["read", "write", "open", "close", "exit", "exit_group"],
"action": "SCMP_ACT_ALLOW"
},
{
"names": ["bind", "connect", "accept", "listen", "socket"],
"action": "SCMP_ACT_ALLOW",
"comment": "允许网络相关系统调用"
},
{
"names": ["execve", "execveat"],
"action": "SCMP_ACT_ERRNO",
"comment": "禁止执行新程序,防止 shell 逃逸"
}
]
}
# 启动容器时加载自定义 seccomp 配置
docker run \
--security-opt seccomp=/path/to/my-seccomp.json \
my-app:latest
5.2 AppArmor 访问控制
AppArmor 为进程定义安全配置文件,限制其文件访问和特权操作。Docker 自带 docker-default 配置文件,通常足够严密,但对于高安全要求场景可编写自定义策略。
# 查看当前容器的 AppArmor 状态
docker inspect <container_id> | grep -i apparmor
# 加载自定义 AppArmor 策略
sudo apparmor_parser -r -W /etc/apparmor.d/containers/docker-myapp
# 启动容器绑定自定义 AppArmor 策略
docker run \
--security-opt apparmor=docker-myapp \
my-app:latest
# /etc/apparmor.d/containers/docker-myapp 示例
profile docker-myapp flags=(attach_disconnected,mediate_deleted) {
#include <tunables/global>
capability chown,
capability setuid,
deny /proc/sys/** w,
deny /etc/shadow r,
/app/** rw,
/tmp/ rw,
}
deny /proc/sys/** w 阻止写入内核参数,deny /etc/shadow r 阻止读取密码哈希,这些都是防止容器逃逸的典型措施。
5.3 SELinux 强制访问控制
在 RHEL / CentOS / Fedora 环境中,SELinux 提供比 AppArmor 更细粒度的强制访问控制。
# 检查 SELinux 状态
getenforce
# 输出 Expected: Enforcing
# 启动容器时启用 SELinux 标记
docker run \
-v /host/data:/data:Z \
--security-opt label=disable:false \
my-app:latest
:Z 标签让 Docker 自动设置 SELinux 上下文为 container_file_t,确保容器内进程只能访问被明确允许的卷目录。
5.4 Linux Capabilities 精细控制
Linux capabilities 将 root 的传统特权拆分为 40 多项独立权限。通过 --cap-drop=ALL 和 --cap-add 的组合,可实现对容器能力的精确削减。
# 完整示例:Web 服务容器仅需网络绑定能力
docker run \
--cap-drop=ALL \
--cap-add=CHOWN \
--cap-add=SETGID \
--cap-add=SETUID \
--cap-add=NET_BIND_SERVICE \
--security-opt no-new-privileges:true \
-p 8080:8080 \
my-nginx
| Capabilities | 用途 | 风险等级 |
|---|---|---|
NET_ADMIN | 配置网络接口 | 高,可启用伪造流量 |
SYS_ADMIN | 执行挂载等管理操作 | 极高,常被用于容器逃逸 |
SYS_PTRACE | 附加到其他进程 | 高,可读取其他容器内存 |
SYS_MODULE | 加载内核模块 | 极高,直接威胁宿主机 |
NET_BIND_SERVICE | 监听 1024 以下端口 | 低,Web 服务必要 |
DAC_OVERRIDE | 绕过文件权限检查 | 高,可读取任意文件 |
安全原则是:绝不授予 SYS_ADMIN、SYS_MODULE、CAP_BPF 等特权能力,这些与宿主机边界仅一步之遥。
六、Rootless Docker
传统 Docker 守护进程以 root 运行,一旦守护进程本身出现漏洞,整个宿主机都将暴露。Rootless Docker 模式将守护进程迁移到普通用户命名空间下运行,实现了真正的「无 root」容器管理。
6.1 Rootless 模式工作原理
Rootless Docker 利用 Linux 用户命名空间(User Namespace),将容器内的 root(UID 0)映射宿主机上一个普通用户(如 UID 1000)。这意味着即使容器进程认为自己拥有 root 权限,在宿主机内核看来它只是一个非特权进程。
# 安装 rootless Docker 工具包
curl -fsSL https://get.docker.com/rootless | sh
# 验证安装
dockerd-rootless-setuptool.sh check
# 启动 rootless Docker 守护进程
export PATH=$HOME/bin:$PATH
export DOCKER_HOST=unix://$XDG_RUNTIME_DIR/docker.sock
dockerd-rootless.sh &
6.2 uidmap 配置
用户命名空间的映射关系需通过 newuidmap 和 newgidmap 配置,写入 /etc/subuid 和 /etc/subgid。以用户 app 为例:
# /etc/subuid 配置
echo "app:100000:65536" | sudo tee -a /etc/subuid
# /etc/subgid 配置
echo "app:100000:65536" | sudo tee -a /etc/subgid
这表示用户 app 可以在用户命名空间中将容器内 UID 0-65535 映射到宿主机的 100000-165535 范围。容器 root 在宿主机上实际对应 UID 100000,彻底脱离了宿主机 root 的概念。
6.3 Rootless 与 Rootfull 对比
| 维度 | Rootfull Docker | Rootless Docker |
|---|---|---|
| 守护进程运行身份 | root | 普通用户 |
| 容器逃逸影响范围 | 宿主 root 沦陷 | 仅影响普通用户 |
| 能否运行特权容器 | 可以 | 不支持 --privileged |
| 编排工具兼容性 | 完全兼容 | 部分限制 |
| 存储驱动选择 | 全部 | 推荐 overlay2 + fuse-overlayfs |
对于生产环境的安全关键型部署,Rootless Docker 是消除单点特权风险的最佳实践之一。
七、镜像签名与供应链安全
即使有漏洞扫描和安全加固,镜像供应链本身也可能被攻击:攻击者可能替换 Registry 中的镜像为植入后门的版本。镜像签名和供应链安全机制确保你运行的镜像确实来自可信的来源,并且未被篡改。
7.1 Cosign / Sigstore 密钥less签名
Sigstore 是由 Linux 基金会支持的开源项目,提供无需管理私钥的镜像签名方案。Cosign 是其实现工具。
# 安装 Cosign
wget https://github.com/sigstore/cosign/releases/latest/download/cosign-linux-amd64
chmod +x cosign-linux-amd64
sudo mv cosign-linux-amd64 /usr/local/bin/cosign
# 使用 OIDC(如 GitHub Actions)进行密钥less签名
cosign sign --yes harbor.example.com/my-app:v1.0
# 验证签名(无需手动分发公钥)
cosign verify \
--certificate-identity=your-ci@example.com \
--certificate-oidc-issuer=https://token.actions.githubusercontent.com \
harbor.example.com/my-app:v1.0
cosign sign --yes 在 CI/CD 环境中通过 OIDC 身份自动获取临时密钥对进行签名,签名证书和透明日志条目自动发布到 Rekor 公共日志中,行为透明可审计。
7.2 Notary v2
Docker Content Trust v1 的继任者 Notary v2 提供了与 OCI 仓库原生集成的签名规范,支持按 Tag 或按 Digest 签名。
# 使用 Notary v2 (notation) 签名镜像
notation sign harbor.example.com/my-app:v1.0
# 验证镜像签名
notation verify harbor.example.com/my-app:v1.0
Harbor 2.9+ 版本已原生支持 Notary v2 验证,可以在项目级别要求所有镜像必须携带有效签名,否则拒绝部署。
7.3 SBOM 生成与 SLSA 合规
SBOM(Software Bill of Materials)是一份完整的软件成分清单,记录镜像中每个包的来源和版本。欧盟《网络韧性法案》和美国 Wiz 备忘录都要求关键软件提供 SBOM。
# 使用 Syft 生成 SBOM
syft my-app:latest -o spdx-json=sbom.spdx.json
# 使用 Trivy 生成 SBOM
trivy image --format cyclonedx --output sbom.json my-app:latest
# 将 SBOM 作为制品伴随镜像推送
cosign attest \
--predicate sbom.spdx.json \
--type spdxjson \
harbor.example.com/my-app:v1.0
SLSA(Supply-chain Levels for Software Artifacts)是一个分级标准,强调从源码到工件的全程可追溯。要做到 SLSA Level 3,必须满足:构建环境隔离、构建脚本代码化、构建产物签名且支持可验证的追溯链。
八、网络隔离与安全
默认 bridge 网络下所有容器处于同一二层网络,可以直接相互访问。在多租户或微服务架构中,这显然不符合最小权限原则,必须通过自定义网络和 iptables 规则实现隔离。
8.1 自定义隔离网络
# 创建自定义 bridge 网络
docker network create --driver bridge isolated-net
# 启动服务时加入自定义网络
docker run -d --name frontend --network isolated-net frontend:latest
docker run -d --name backend --network isolated-net backend:latest
# 限制边界网络接入,只有前端可暴露端口到外网
docker run -d --name db --network isolated-net \
--network-alias postgres \
postgres:15
数据库服务 db 不映射任何宿主机端口,仅允许在同一 isolated-net 中的其他容器通过内部 DNS 解析进行访问,天然屏蔽了外部直接访问的可能。
8.2 禁用 ICC(容器间通信)
在需要进一步隔离的场景下,可以关闭同一网络内容器之间的直接通信,使其仅允许通过显式端口映射进行交互。
# 创建禁用 ICC 的桥接网络
docker network create \
--driver bridge \
--opt com.docker.network.bridge.enable_icc=false \
high-secure-net
启用此选项后,即使两个容器在同一网络中,也无法直接访问对方的端口,除非通过外部负载均衡或代理转发。
8.3 iptables 规则加固
Docker 默认通过 DOCKER-USER 链将 iptables 规则暴露给用户自定义,所有用户规则均插入到此链中。
# 阻止容器访问特定 IP(例如元数据服务)
iptables -I DOCKER-USER -d 169.254.169.254 -j DROP
# 仅允许容器访问外部 HTTPS 端口
iptables -I DOCKER-USER -p tcp ! --dport 443 -j DROP
# 持久化规则
apt-get install -y iptables-persistent
netfilter-persistent save
169.254.169.254 是云厂商常见的实例元数据服务地址,历史上多次发生容器通过 SSRF 窃取 IAM 凭证的事件,通过 iptables 阻断是最有效的防护措施之一。
九、运行时安全监控
事前加固可以减少攻击面,但无法保证绝对安全。运行时监控和审计日志是发现异常行为和事后取证的关键技术手段。
9.1 Falco — 云原生安全监控
Falco 由 Sysdig 开源,通过内核模块或 eBPF 探针监控系统调用,以规则引擎检测异常行为。它在检测到可疑事件时输出高保真告警日志。
# 使用 Helm 安装 Falco
helm repo add falcosecurity https://falcosecurity.github.io/charts
helm repo update
helm install falco falcosecurity/falco \
--set driver.kind=modern_ebpf \
--set tty=true
# 查看内核触发的 Falco 告警
kubectl logs -l app.kubernetes.io/name=falco | grep Warning
以下是一个自定义 Falco 规则,检测容器内是否出现了反弹 shell 连接行为:
# /etc/falco/rules.d/custom.yaml
- rule: Reverse Shell Detected
desc: Detect spawn of a shell with an established network connection
condition: >
spawned_process and
shell_procs and
(inbound_outbound or
fd.name in ("127.0.0.1", "0.0.0.0"))
output: >
Reverse shell connection detected
user=%user.name command=%proc.cmdline parent=%proc.pname
connection=%fd.name
priority: CRITICAL
9.2 Sysdig 容器取证
Sysdig 是一个轻量级的系统级信息收集工具,能够在不修改应用的情况下捕获容器内的全部系统调用和 I/O 活动,生成 .scap 抓包文件用于事后分析。
# 安装 Sysdig
sudo apt-get install -y sysdig
# 抓取特定容器的全部系统调用(用于事后分析)
sudo sysdig -pc -c echo_fds \
container.name=my-app > /tmp/container-forensics.scap &
# 读取抓包文件
sudo sysdig -r /tmp/container-forensics.scap \
"proc.aname contains curl and evt.type=connect"
Sysdig 特别适用于「某容器曾被入侵但当前不可复现」的场景,通过有限的抓包数据可以还原攻击链全过程。
9.3 审计日志集成(auditd)
Docker 的 dockerd 守护进程支持向 auditd 输出关键事件日志。
# 在 daemon.json 中启用审计日志
sudo tee /etc/docker/daemon.json << 'EOF'
{
"log-driver": "json-file",
"log-opts": {
"max-size": "10m",
"max-file": "3"
},
"labels": ["environment", "service"],
"live-restore": true
}
EOF
sudo systemctl restart docker
# 查看审计日志
cat /var/log/audit/audit.log | grep docker
建议通过 auditd 规则监控对 Docker 守护进程 socket 文件 /var/run/docker.sock 的访问,因为拥有 socket 访问权限等同于拥有 root 权限。
十、CVE 响应与镜像更新策略
安全加固不是一次性的工作,持续跟进漏洞情报和及时更新镜像,是保持安全态的核心运营环节。
10.1 Distroless / Chiseled 最小化攻击面
Google 的 Distroless 镜像和 Canonical 的 Chiseled 镜像通过移除系统包管理器、shell 和冗余库文件,将攻击面压缩到绝对最小。
# Distroless 示例:静态编译 Go 应用
FROM golang:1.22 AS builder
WORKDIR /app
COPY . .
RUN CGO_ENABLED=0 go build -o main .
# 运行时镜像仅包含 scratch + CA certs
gcr.io/distroless/static-debian12:nonroot
COPY --from=builder /app/main /main
USER nonroot:nonroot
ENTRYPOINT ["/main"]
# Chiseled 示例:最小化 Ubuntu 基础镜像
FROM ubuntu:22.04 AS builder
RUN apt-get update && apt-get install -y --no-install-recommends ca-certificates
FROM ubuntu:22.04
COPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/
COPY my-app /usr/local/bin/my-app
ENTRYPOINT ["my-app"]
Distroless 镜像内部没有 sh、bash、apt、curl 等工具,即使攻击者获得执行权,也无法继续横向移动或下载恶意载荷。
10.2 Dependabot / Renovate 自动更新
依赖漏洞通常比操作系统漏洞更多,手动跟踪每个包的更新是不现实的。Dependabot 和 Renovate 是两款流行的自动依赖更新工具。
# .github/dependabot.yml
version: 2
updates:
- package-ecosystem: "docker"
directory: "/"
schedule:
interval: "weekly"
open-pull-requests-limit: 10
ignore:
- dependency-name: "node"
update-types: ["version-update:semver-major"]
- package-ecosystem: "npm"
directory: "/"
schedule:
interval: "daily"
commit-message:
prefix: "security"
Renovate 功能更为强大,支持分支式配置、定时批量合并、以及自动修复 lockfile 冲突。推荐在 CI 中配置 Renovate 且关闭自动合并,要求所有依赖更新 PR 通过回归测试和人工审查后再合并。
10.3 漏洞优先级评估
并非所有 CVE 都需要立即修复,有效的漏洞管理应基于可利用性进行优先级排序。
# 使用 Trivy 的漏洞数据库评估可利用性
trivy image --vuln-type os \
--severity HIGH,CRITICAL \
--ignore-unfixed \
my-app:latest
业界广泛采用 EPSS(Exploit Prediction Scoring System)和 CISA KEV(Known Exploited Vulnerabilities Catalog)作为漏洞优先级判断依据。一个漏洞虽然被评为 Critical,但如果 EPSS 分数低于 0.1 且不在 KEV 目录中,可以延后至下一个维护窗口修复。反之,即使一个漏洞被评为 Medium,如果 KEV 目录中已有野外利用记录,应作为最高优先级立即处理。
常见问题(FAQ)
Docker 容器会被黑客攻击吗?
会。如果容器以 root 运行且应用程序存在漏洞,攻击者可能首先获得容器内 root 权限。虽然从容器突破到宿主机通常需要额外的内核漏洞(容器逃逸),但不应轻视容器安全。历史上,Docker 的 runc 和 Linux 内核的 dirty cow、 privilege escalation 漏洞都曾被利用实现容器逃逸。正确的做法是将容器视为一个可被破坏的边界,通过纵深防御策略降低逃逸后的影响面。
扫描出漏洞怎么办?
- 更新基础镜像:运行
docker pull node:20-alpine拉取最新版本,重新构建后再次扫描 - 更新应用依赖:使用
npm audit fix、pip-audit --fix或cargo audit修复已知依赖漏洞 - 评估风险:如果漏洞无修复版本,结合 CVSS 评分、EPSS 分数和实际利用场景进行风险评估
- 临时缓解:通过 WAF 规则、网络微分段或运行时策略暂时阻止利用路径,等待上游修复
- 记录与跟踪:在漏洞管理系统中归档该 CVE,设定修复时间表并安排复查
相关阅读
继续阅读
探索更多技术文章
浏览归档,发现更多关于系统设计、工具链和工程实践的内容。