上一篇 下一篇 分享链接 返回 返回顶部

生产环境 Docker 漏洞修复实战:从风险排查到灰度升级与回滚验证

发布人:慈云数据-客服中心 发布时间:13小时前 阅读量:1

Docker 最新漏洞修复教程|生产环境实测

适用对象:运维工程师、DevOps 工程师、SRE、后端开发、云原生平台维护人员
适用场景:生产环境 Docker Engine / containerd / Docker Compose / 镜像安全漏洞修复
目标:在尽量不中断业务的前提下,完成 Docker 相关漏洞排查、升级、验证与回滚预案设计


一、前言:为什么 Docker 漏洞修复不能只靠“升级一下”

Docker 作为容器化部署中最常见的基础组件之一,已经广泛应用于测试环境、预发布环境和生产环境。很多企业的 Java、Go、Node.js、Python、PHP、Nginx、MySQL、Redis、Elasticsearch 等服务,都是通过 Docker 或基于 Docker 的容器运行时部署的。

也正因为 Docker 位于基础设施底层,一旦 Docker Engine、containerd、runc 或镜像中存在高危漏洞,就可能影响整个平台的安全边界。例如:

  • 容器逃逸风险;
  • 恶意镜像执行风险;
  • Docker API 未授权访问;
  • 构建过程供应链投毒;
  • 基础镜像存在高危 CVE;
  • 容器以特权模式运行导致宿主机被攻破;
  • 镜像仓库账号泄露导致生产镜像被替换;
  • 旧版本 Docker 组件存在已公开漏洞但未及时升级。

在生产环境中,漏洞修复不是简单执行一条命令:

yum update docker

或者:

apt upgrade docker-ce

因为 Docker 升级过程中可能会影响正在运行的容器、网络、存储驱动、日志驱动、镜像兼容性以及编排系统。如果操作不当,轻则服务短暂中断,重则容器无法启动、数据卷异常、网络规则丢失,甚至导致整台业务节点不可用。

本文将结合生产环境实测经验,给出一套相对稳妥的 Docker 漏洞修复流程,包括漏洞确认、风险评估、升级前检查、备份、灰度升级、验证、回滚和长期加固方案。


二、Docker 漏洞修复的基本思路

在正式操作之前,需要明确一点:Docker 安全修复通常分为三类。

1. Docker Engine / containerd / runc 组件漏洞

这类漏洞属于容器运行时层面的安全问题,通常需要升级以下组件:

  • Docker Engine;
  • Docker CLI;
  • containerd;
  • runc;
  • Docker Compose;
  • BuildKit。

这类漏洞风险最高,因为它们直接影响容器运行时安全边界。

2. 容器镜像漏洞

即使 Docker 本身是最新版本,如果业务镜像中使用了存在漏洞的基础镜像,例如旧版本 Ubuntu、Debian、Alpine、CentOS、OpenJDK、Node.js、Python、Nginx,也可能被安全扫描工具判定为高危。

这类漏洞通常需要:

  • 升级基础镜像;
  • 更新系统依赖包;
  • 重构镜像;
  • 重新构建并发布镜像;
  • 替换生产容器。

3. Docker 配置与使用方式不安全

例如:

  • Docker API 暴露在公网;
  • 容器使用 --privileged
  • 容器挂载宿主机根目录;
  • 容器以 root 用户运行;
  • 未限制容器资源;
  • 未配置日志轮转;
  • 未启用镜像签名和扫描;
  • 敏感信息写入镜像或环境变量。

这类问题不一定是 Docker 软件本身漏洞,但在实际攻防中非常常见。


三、生产环境漏洞修复前的准备工作

生产环境中最重要的原则是:先评估,再变更;先灰度,再全量;先备份,再升级;先验证,再关闭窗口。

1. 确认当前 Docker 版本

首先查看 Docker 版本:

docker version

重点关注:

Client:
 Version:
 API version:

Server:
 Engine:
  Version:
 containerd:
  Version:
 runc:
  Version:
 docker-init:
  Version:

也可以查看更详细信息:

docker info

如果需要单独查看 containerd 和 runc 版本:

containerd --version
runc --version

在生产环境中,建议将这些信息记录下来,作为升级前基线。

示例记录:

mkdir -p /root/docker-upgrade-backup
docker version > /root/docker-upgrade-backup/docker-version-before.txt
docker info > /root/docker-upgrade-backup/docker-info-before.txt
containerd --version > /root/docker-upgrade-backup/containerd-version-before.txt
runc --version > /root/docker-upgrade-backup/runc-version-before.txt

2. 查看当前运行容器

执行:

docker ps

导出运行中的容器列表:

docker ps --format "table {{.ID}}\t{{.Image}}\t{{.Names}}\t{{.Status}}\t{{.Ports}}" \
> /root/docker-upgrade-backup/docker-ps-before.txt

查看所有容器,包括已停止容器:

docker ps -a > /root/docker-upgrade-backup/docker-ps-a-before.txt

如果生产环境中容器很多,建议重点关注以下信息:

  • 容器名称;
  • 镜像版本;
  • 端口映射;
  • 数据卷挂载;
  • 网络模式;
  • 启动命令;
  • 重启策略;
  • 是否使用特权模式;
  • 是否依赖本地数据目录。

可以通过下面命令导出容器详细配置:

for c in $(docker ps -aq); do
  docker inspect "$c" > "/root/docker-upgrade-backup/container-${c}.json"
done

3. 检查 Docker 数据目录

默认情况下,Docker 数据目录通常位于:

/var/lib/docker

查看 Docker Root Dir:

docker info | grep "Docker Root Dir"

如果数据目录较大,不建议直接整体复制 /var/lib/docker,因为其中包含镜像层、容器层、overlay2 文件、日志和元数据。在生产环境中,备份的重点应该是:

  • 业务数据卷;
  • Compose 文件;
  • Dockerfile;
  • 镜像构建配置;
  • 环境变量文件;
  • 服务启动脚本;
  • 镜像仓库地址和版本号;
  • 关键容器 inspect 信息。

查看所有 volume:

docker volume ls

查看 volume 详情:

docker volume inspect volume_name

如果业务数据存放在宿主机目录,例如:

/data/mysql
/data/redis
/data/nginx
/data/app

需要优先备份这些目录。


4. 检查 Docker Compose 项目

如果生产环境通过 Docker Compose 部署,需要找到对应目录:

find / -name "docker-compose.yml" 2>/dev/null
find / -name "compose.yml" 2>/dev/null

备份 Compose 文件:

cp docker-compose.yml /root/docker-upgrade-backup/
cp .env /root/docker-upgrade-backup/ 2>/dev/null

查看 Compose 版本:

docker compose version

旧环境可能使用的是:

docker-compose version

需要注意,docker-compose v1 与 docker compose v2 在部分行为上存在差异,升级前要确认当前项目是否依赖旧版本命令。


四、漏洞确认与影响范围判断

在实际生产环境中,安全团队通常会给出漏洞编号,例如某个 Docker Engine、containerd 或 runc 的 CVE。收到漏洞通知后,不建议马上升级,而应先确认影响范围。

1. 判断是否存在受影响版本

查看官方公告、发行版安全公告或企业内部安全平台,确认漏洞影响的版本范围。

例如需要确认:

  • 当前 Docker Engine 是否低于安全版本;
  • 当前 containerd 是否低于修复版本;
  • 当前 runc 是否低于修复版本;
  • 当前内核版本是否也存在关联风险;
  • 当前容器是否启用了高危配置;
  • 漏洞是否需要本地权限才能利用;
  • 漏洞是否可远程利用;
  • 是否需要攻击者能够构建镜像或启动容器。

2. 判断业务是否暴露攻击面

重点检查:

ps -ef | grep dockerd

查看 dockerd 是否监听 TCP:

ss -lntp | grep docker

如果看到类似:

0.0.0.0:2375

这是非常危险的配置,因为 Docker Remote API 如果未启用 TLS 认证,相当于把宿主机控制权暴露给网络访问者。

检查 Docker daemon 配置:

cat /etc/docker/daemon.json

检查 systemd 启动参数:

systemctl cat docker

如果存在:

-H tcp://0.0.0.0:2375

或:

-H tcp://公网IP:2375

应立即整改,至少限制为内网访问,并启用 TLS 认证,更推荐直接关闭 TCP 暴露。


五、生产环境升级前的核心检查

1. 确认系统发行版

不同系统升级方式不同:

cat /etc/os-release

常见系统包括:

  • Ubuntu;
  • Debian;
  • CentOS;
  • Rocky Linux;
  • AlmaLinux;
  • RHEL;
  • Amazon Linux;
  • openEuler;
  • Anolis OS。

不要混用不同发行版的软件源,也不要随意使用第三方未知源。


2. 检查当前软件包

Ubuntu / Debian

dpkg -l | grep -E "docker|containerd|runc"

CentOS / Rocky / RHEL

rpm -qa | grep -E "docker|containerd|runc"

同时查看可升级版本。

Ubuntu / Debian:

apt-cache policy docker-ce docker-ce-cli containerd.io

CentOS / Rocky / RHEL:

yum list docker-ce docker-ce-cli containerd.io --showduplicates

或者:

dnf list docker-ce docker-ce-cli containerd.io --showduplicates

3. 检查容器重启策略

如果 Docker 服务升级过程中需要重启,容器是否会自动恢复,取决于 restart policy。

查看容器重启策略:

docker inspect -f '{{.Name}} {{.HostConfig.RestartPolicy.Name}}' $(docker ps -aq)

常见策略:

  • no:不会自动重启;
  • always:Docker 重启后自动拉起;
  • unless-stopped:除非人为停止,否则自动拉起;
  • on-failure:异常退出时重启。

生产环境建议关键服务配置:

restart: unless-stopped

或:

restart: always

但数据库类服务仍需结合实际情况评估,避免异常恢复导致数据损坏。


4. 检查单机容器是否可中断

如果是单机部署,例如单台机器上运行 MySQL、Redis、业务 API,则 Docker 重启可能造成短暂中断。

如果是集群部署,例如:

  • 多节点 Nginx;
  • 多副本业务服务;
  • Redis 哨兵或集群;
  • MySQL 主从;
  • Kafka 集群;
  • Elasticsearch 集群;

则可以按节点滚动升级。

生产建议:

  1. 从非核心节点开始;
  2. 一次只升级一台;
  3. 从负载均衡摘除节点;
  4. 升级完成后验证;
  5. 加回负载均衡;
  6. 继续下一台。

六、Ubuntu / Debian 环境 Docker 漏洞修复流程

以下命令适用于使用 Docker 官方源安装的环境。

1. 更新软件源

apt update

查看可升级组件:

apt list --upgradable | grep -E "docker|containerd|runc"

2. 升级 Docker 相关组件

apt install --only-upgrade docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

如果系统提示需要重启 Docker 服务,需要确认维护窗口。

升级后查看版本:

docker version
containerd --version
runc --version
docker compose version

3. 重启 Docker 服务

如果升级过程中 Docker 未自动重启,建议在维护窗口内手动重启:

systemctl daemon-reload
systemctl restart docker

查看状态:

systemctl status docker --no-pager

查看 containerd:

systemctl status containerd --no-pager

七、CentOS / Rocky Linux / RHEL 环境 Docker 漏洞修复流程

1. 刷新缓存

yum makecache

或:

dnf makecache

2. 查看可升级版本

yum list docker-ce docker-ce-cli containerd.io --showduplicates

如果使用 dnf:

dnf list docker-ce docker-ce-cli containerd.io --showduplicates

3. 执行升级

yum update docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

或:

dnf update docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

4. 重启服务

systemctl daemon-reload
systemctl restart docker

确认服务状态:

systemctl status docker --no-pager

检查版本:

docker version
containerd --version
runc --version

八、生产环境滚动升级实测流程

以下是我们在生产环境中采用的滚动升级方式,适合多节点容器部署环境。

第一步:选择灰度节点

优先选择:

  • 流量较低的节点;
  • 非核心节点;
  • 有冗余副本的节点;
  • 可以快速从负载均衡摘除的节点。

在负载均衡或网关中下线该节点,例如:

  • Nginx upstream 注释;
  • SLB / ELB 后端摘除;
  • Kubernetes 节点 cordon/drain;
  • 服务注册中心临时下线;
  • 网关路由权重调为 0。

第二步:确认节点无业务流量

通过访问日志确认:

tail -f /var/log/nginx/access.log

或者通过监控平台确认:

  • QPS 降为 0;
  • CPU 降低;
  • 业务接口无请求;
  • 连接数下降;
  • 错误率未上升。

第三步:备份关键配置

mkdir -p /root/docker-upgrade-backup-$(date +%F)

docker version > /root/docker-upgrade-backup-$(date +%F)/docker-version-before.txt
docker info > /root/docker-upgrade-backup-$(date +%F)/docker-info-before.txt
docker ps -a > /root/docker-upgrade-backup-$(date +%F)/docker-ps-a-before.txt
cp -a /etc/docker /root/docker-upgrade-backup-$(date +%F)/etc-docker

如果使用 Compose:

cp -a /opt/compose-project /root/docker-upgrade-backup-$(date +%F)/

第四步:执行升级

根据系统类型选择前文命令升级 Docker 组件。

第五步:重启 Docker

systemctl restart docker

第六步:检查容器状态

docker ps
docker ps -a

确认容器是否全部正常运行。

如果部分容器未启动,可以查看日志:

docker logs container_name --tail=200

查看容器退出原因:

docker inspect container_name

重点看:

State.ExitCode
State.Error
State.OOMKilled

第七步:业务验证

执行以下验证:

curl -I http://127.0.0.1:端口/health
curl http://127.0.0.1:端口/actuator/health

根据业务类型验证:

  • Web 服务返回 200;
  • API 健康检查正常;
  • 数据库连接正常;
  • 消息队列消费正常;
  • 日志正常输出;
  • 容器网络互通;
  • 数据卷挂载正常;
  • 监控指标恢复;
  • 错误率无异常。

第八步:重新加入流量

将节点重新加入负载均衡,观察 10 到 30 分钟:

  • CPU;
  • 内存;
  • 磁盘 IO;
  • 网络连接;
  • 业务错误率;
  • 5xx 数量;
  • 容器重启次数;
  • 日志异常。

如果灰度节点稳定,再继续下一台节点。


九、升级后安全验证

1. 查看版本是否已更新

docker version
containerd --version
runc --version
docker compose version

保存升级后版本:

docker version > /root/docker-upgrade-backup/docker-version-after.txt
docker info > /root/docker-upgrade-backup/docker-info-after.txt

2. 检查 Docker 服务状态

systemctl is-active docker
systemctl is-enabled docker

查看最近日志:

journalctl -u docker -n 200 --no-pager

如果日志中出现如下信息,需要进一步排查:

  • storage driver error;
  • overlay2 mount error;
  • iptables error;
  • failed to start daemon;
  • failed to initialize network controller;
  • containerd connection error。

3. 检查容器是否异常重启

docker ps --format "table {{.Names}}\t{{.Status}}\t{{.Image}}"

如果看到:

Restarting
Exited
Dead

说明容器存在异常,需要立即处理。

查看容器重启次数:

docker inspect -f '{{.Name}} {{.RestartCount}}' $(docker ps -aq)

十、容器镜像漏洞修复

Docker 运行时升级完成后,还需要处理镜像漏洞。很多安全扫描报告中出现的漏洞,并不是 Docker Engine 的问题,而是镜像内部软件包的问题。

1. 扫描镜像

可以使用 Trivy 扫描:

trivy image nginx:latest
trivy image your-registry.com/project/app:version

也可以扫描本地镜像:

trivy image app:latest

2. 更新基础镜像

如果 Dockerfile 中使用旧基础镜像:

FROM ubuntu:18.04

建议升级到受支持版本,例如:

FROM ubuntu:22.04

或者使用更小的运行时镜像:

FROM alpine:3.20

对于 Java 应用,可以考虑:

FROM eclipse-temurin:17-jre

对于 Node.js 应用:

FROM node:20-alpine

但不要盲目追求 latest,生产环境更推荐明确版本号,例如:

FROM nginx:1.26-alpine

这样可以保证构建可复现。

3. 更新系统包

Debian / Ubuntu 镜像:

RUN apt-get update \
    && apt-get upgrade -y \
    && rm -rf /var/lib/apt/lists/*

Alpine 镜像:

RUN apk update \
    && apk upgrade \
    && rm -rf /var/cache/apk/*

4. 重新构建镜像

docker build -t your-registry.com/project/app:2026-secfix .

推送镜像:

docker push your-registry.com/project/app:2026-secfix

更新 Compose:

services:
  app:
    image: your-registry.com/project/app:2026-secfix

重新发布:

docker compose pull
docker compose up -d

十一、Docker 安全加固建议

漏洞修复不是一次性工作,生产环境应长期执行安全加固。

1. 禁止 Docker API 裸奔

检查是否监听 2375:

ss -lntp | grep 2375

如果不需要远程访问,关闭 TCP 监听。只保留 Unix Socket:

unix:///var/run/docker.sock

如果必须远程访问,必须启用 TLS 认证,并限制来源 IP。


2. 避免使用特权容器

检查特权容器:

docker inspect -f '{{.Name}} {{.HostConfig.Privileged}}' $(docker ps -aq)

如果结果为:

true

需要评估是否真的必须使用。

避免:

docker run --privileged

尽量改为最小权限:

--cap-drop=ALL
--cap-add=NET_BIND_SERVICE

3. 禁止挂载宿主机敏感目录

高风险挂载包括:

/
 /etc
 /root
 /var/run/docker.sock
 /proc
 /sys

尤其是:

-v /var/run/docker.sock:/var/run/docker.sock

这相当于让容器拥有控制宿主机 Docker 的能力,应谨慎使用。


4. 使用非 root 用户运行容器

Dockerfile 中增加:

RUN useradd -r -u 10001 appuser
USER appuser

或者在 Compose 中配置:

user: "10001:10001"

这样即使容器内部进程被攻破,也能降低攻击者权限。


5. 配置日志轮转

防止容器日志撑满磁盘。

编辑:

vim /etc/docker/daemon.json

加入:

{
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "100m",
    "max-file": "5"
  }
}

重启 Docker:

systemctl restart docker

注意:该配置通常只对新创建的容器生效,旧容器需要重建。


6. 限制容器资源

Compose 示例:

services:
  app:
    image: app:secure
    mem_limit: 1g
    cpus: "1.0"
    restart: unless-stopped

避免单个容器异常占满宿主机资源。


7. 定期清理无用镜像

查看磁盘占用:

docker system df

清理无用资源:

docker system prune

谨慎清理所有未使用镜像:

docker system prune -a

生产环境执行前必须确认不会删除待回滚镜像。


十二、回滚方案设计

任何生产升级都必须有回滚方案。

1. 软件包回滚

升级前记录旧版本:

docker version
rpm -qa | grep docker
dpkg -l | grep docker

如果升级后出现严重问题,可尝试安装旧版本。

Ubuntu / Debian:

apt-cache madison docker-ce
apt install docker-ce=指定版本 docker-ce-cli=指定版本 containerd.io=指定版本

CentOS / Rocky:

yum downgrade docker-ce docker-ce-cli containerd.io

不过需要注意:Docker 降级可能存在数据目录兼容性风险,不建议频繁降级。更稳妥的方式是通过节点级别回滚或替换节点。

2. 节点级回滚

如果是云主机,升级前可以创建快照。

推荐流程:

  1. 升级前创建系统盘快照;
  2. 升级后验证;
  3. 如失败,停止节点业务流量;
  4. 回滚快照或重新拉起旧节点;
  5. 恢复负载均衡。

3. 容器镜像回滚

保留旧镜像版本:

docker images

Compose 中快速回滚:

image: your-registry.com/project/app:old-version

执行:

docker compose up -d

不要在生产中只使用 latest,否则回滚时无法确认上一个稳定版本。


十三、生产环境实测结论

经过生产环境多节点滚动升级验证,Docker 漏洞修复相对安全的方式是:

  1. 先确认漏洞影响范围,不要盲目升级;
  2. 先升级灰度节点,观察稳定后再扩大范围;
  3. 升级前必须备份 Docker 配置和容器元数据
  4. 确保关键容器具备正确的 restart policy
  5. 数据库、中间件节点不要和无状态业务节点混用升级策略
  6. Docker Engine、containerd、runc 要整体考虑
  7. 镜像漏洞需要通过重构镜像解决,不能只升级宿主机 Docker
  8. 升级后要验证业务,而不仅仅是验证 Docker 服务状态
  9. 禁止 Docker API 未授权暴露,这是生产环境最常见高危问题;
  10. 建立定期扫描、定期升级、定期演练机制

十四、推荐的最终修复检查清单

升级完成后,可以按照以下清单逐项确认:

  • [ ] Docker Engine 已升级到安全版本;
  • [ ] containerd 已升级到安全版本;
  • [ ] runc 已升级到安全版本;
  • [ ] Docker Compose 插件版本正常;
  • [ ] Docker 服务状态正常;
  • [ ] containerd 服务状态正常;
  • [ ] 所有关键容器运行正常;
  • [ ] 容器无异常重启;
  • [ ] 业务健康检查通过;
  • [ ] 日志无明显异常;
  • [ ] 监控指标恢复正常;
  • [ ] 负载均衡节点已恢复;
  • [ ] Docker API 未暴露公网;
  • [ ] 无不必要的特权容器;
  • [ ] 无高危宿主机目录挂载;
  • [ ] 镜像漏洞已重新扫描;
  • [ ] 回滚镜像和旧版本包已保留;
  • [ ] 变更记录已归档。

十五、总结

Docker 漏洞修复的难点不在于命令本身,而在于生产环境的不确定性。不同业务对容器的依赖程度不同,不同节点上的数据卷、网络、镜像版本和启动方式也不完全一样。因此,生产环境修复 Docker 漏洞,必须采用工程化流程,而不是临时手工操作。

一套可靠的 Docker 漏洞修复流程应该包括:

  • 漏洞确认;
  • 资产盘点;
  • 影响分析;
  • 备份配置;
  • 灰度升级;
  • 服务验证;
  • 安全加固;
  • 回滚预案;
  • 长期治理。

如果只是简单升级 Docker 软件包,可能短期内解决 CVE 扫描告警,但无法真正提升容器平台安全性。真正可靠的做法,是把 Docker 运行时安全、镜像安全、配置安全、权限安全和供应链安全统一纳入日常运维体系。

对于生产环境来说,最推荐的策略是:小步快跑、滚动升级、持续扫描、版本可控、配置最小化、权限最小化。这样既能及时修复漏洞,又能最大限度降低业务中断风险。

目录结构
全文