生产环境 Docker 漏洞修复实战:从风险排查到灰度升级与回滚验证
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 集群;
则可以按节点滚动升级。
生产建议:
- 从非核心节点开始;
- 一次只升级一台;
- 从负载均衡摘除节点;
- 升级完成后验证;
- 加回负载均衡;
- 继续下一台。
六、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. 节点级回滚
如果是云主机,升级前可以创建快照。
推荐流程:
- 升级前创建系统盘快照;
- 升级后验证;
- 如失败,停止节点业务流量;
- 回滚快照或重新拉起旧节点;
- 恢复负载均衡。
3. 容器镜像回滚
保留旧镜像版本:
docker images
Compose 中快速回滚:
image: your-registry.com/project/app:old-version
执行:
docker compose up -d
不要在生产中只使用 latest,否则回滚时无法确认上一个稳定版本。
十三、生产环境实测结论
经过生产环境多节点滚动升级验证,Docker 漏洞修复相对安全的方式是:
- 先确认漏洞影响范围,不要盲目升级;
- 先升级灰度节点,观察稳定后再扩大范围;
- 升级前必须备份 Docker 配置和容器元数据;
- 确保关键容器具备正确的 restart policy;
- 数据库、中间件节点不要和无状态业务节点混用升级策略;
- Docker Engine、containerd、runc 要整体考虑;
- 镜像漏洞需要通过重构镜像解决,不能只升级宿主机 Docker;
- 升级后要验证业务,而不仅仅是验证 Docker 服务状态;
- 禁止 Docker API 未授权暴露,这是生产环境最常见高危问题;
- 建立定期扫描、定期升级、定期演练机制。
十四、推荐的最终修复检查清单
升级完成后,可以按照以下清单逐项确认:
- [ ] Docker Engine 已升级到安全版本;
- [ ] containerd 已升级到安全版本;
- [ ] runc 已升级到安全版本;
- [ ] Docker Compose 插件版本正常;
- [ ] Docker 服务状态正常;
- [ ] containerd 服务状态正常;
- [ ] 所有关键容器运行正常;
- [ ] 容器无异常重启;
- [ ] 业务健康检查通过;
- [ ] 日志无明显异常;
- [ ] 监控指标恢复正常;
- [ ] 负载均衡节点已恢复;
- [ ] Docker API 未暴露公网;
- [ ] 无不必要的特权容器;
- [ ] 无高危宿主机目录挂载;
- [ ] 镜像漏洞已重新扫描;
- [ ] 回滚镜像和旧版本包已保留;
- [ ] 变更记录已归档。
十五、总结
Docker 漏洞修复的难点不在于命令本身,而在于生产环境的不确定性。不同业务对容器的依赖程度不同,不同节点上的数据卷、网络、镜像版本和启动方式也不完全一样。因此,生产环境修复 Docker 漏洞,必须采用工程化流程,而不是临时手工操作。
一套可靠的 Docker 漏洞修复流程应该包括:
- 漏洞确认;
- 资产盘点;
- 影响分析;
- 备份配置;
- 灰度升级;
- 服务验证;
- 安全加固;
- 回滚预案;
- 长期治理。
如果只是简单升级 Docker 软件包,可能短期内解决 CVE 扫描告警,但无法真正提升容器平台安全性。真正可靠的做法,是把 Docker 运行时安全、镜像安全、配置安全、权限安全和供应链安全统一纳入日常运维体系。
对于生产环境来说,最推荐的策略是:小步快跑、滚动升级、持续扫描、版本可控、配置最小化、权限最小化。这样既能及时修复漏洞,又能最大限度降低业务中断风险。