Docker 漏洞排查与修复实战:升级、加固、脚本一次搞定
Docker 最新漏洞修复教程|附源码
适用对象:运维工程师、DevOps 工程师、后端开发人员、安全管理员
适用场景:Linux 服务器 Docker Engine / containerd / runc / Docker Compose 漏洞排查、升级修复、加固与验证
说明:本文以生产环境常见的 Docker 部署方式为例,提供一套通用、可落地的漏洞修复流程,并附带自动化检测与修复脚本源码。
一、为什么 Docker 漏洞需要及时修复?
Docker 已经成为云原生、微服务和 CI/CD 环境中的核心基础设施。大量业务系统、数据库、中间件、定时任务、构建流水线都运行在容器中。由于 Docker 运行时通常具备较高权限,一旦存在漏洞,攻击者可能利用漏洞实现以下风险:
-
容器逃逸
攻击者从容器内部突破隔离限制,访问宿主机文件系统或执行宿主机命令。 -
权限提升
普通容器用户可能获得 root 权限,进一步控制主机或其他容器。 -
镜像供应链投毒
通过恶意镜像、篡改镜像层、污染构建缓存等方式植入后门。 -
敏感信息泄露
包括环境变量、挂载目录、Docker Socket、密钥文件、配置文件等。 -
拒绝服务攻击
恶意容器消耗 CPU、内存、磁盘或文件句柄,导致宿主机或业务不可用。
因此,Docker 漏洞修复不应只理解为“升级一个软件包”,而应包含:版本排查、组件升级、配置加固、镜像治理、权限收敛、验证回滚等完整流程。
二、Docker 漏洞涉及哪些组件?
很多人以为 Docker 漏洞只和 docker 命令有关,其实 Docker 运行依赖多个组件。修复时必须整体关注,否则可能出现 Docker Engine 已升级,但底层运行时仍存在风险的情况。
常见组件如下:
| 组件 | 作用 | 风险点 |
|---|---|---|
| Docker Engine | Docker 核心服务,通常是 dockerd |
API 暴露、权限过大、版本漏洞 |
| containerd | 容器运行时管理组件 | 镜像拉取、容器生命周期管理漏洞 |
| runc | OCI 容器运行时 | 容器逃逸、权限提升风险 |
| Docker Compose | 多容器编排工具 | 依赖漏洞、配置错误 |
| BuildKit | 镜像构建后端 | 构建缓存、Dockerfile 解析风险 |
| Docker CLI | 命令行客户端 | 本地执行、插件风险 |
| 镜像基础系统 | 如 Alpine、Debian、Ubuntu、CentOS | OpenSSL、glibc、curl、bash 等系统漏洞 |
所以,修复 Docker 漏洞时,建议至少同时检查:
docker version
docker info
containerd --version
runc --version
docker compose version
如果只修复其中一项,安全风险可能仍然存在。
三、修复前准备工作
生产环境修复漏洞前,不建议直接升级。正确流程应当包括备份、风险评估和维护窗口安排。
1. 确认当前 Docker 版本
执行:
docker version
示例输出:
Client: Docker Engine - Community
Version: 25.0.3
Server: Docker Engine - Community
Engine:
Version: 25.0.3
containerd:
Version: 1.6.28
runc:
Version: 1.1.12
docker-init:
Version: 0.19.0
你需要重点记录以下版本:
- Docker Engine 版本
- containerd 版本
- runc 版本
- Docker Compose 版本
- 操作系统版本
- 内核版本
查看系统与内核:
cat /etc/os-release
uname -a
2. 备份 Docker 关键数据
Docker 默认数据目录通常在:
/var/lib/docker
如果使用 containerd,也可能涉及:
/var/lib/containerd
生产环境中,建议至少备份以下内容:
/etc/docker/
/var/lib/docker/volumes/
docker-compose.yml
.env
如果容器中挂载了业务数据目录,例如:
/data/mysql
/data/redis
/data/app
也需要纳入备份范围。
备份示例:
sudo mkdir -p /backup/docker-$(date +%F)
sudo cp -a /etc/docker /backup/docker-$(date +%F)/docker-config
sudo docker ps --format "table {{.Names}}\t{{.Image}}\t{{.Status}}\t{{.Ports}}" \
> /backup/docker-$(date +%F)/docker-containers.txt
sudo docker images \
> /backup/docker-$(date +%F)/docker-images.txt
如果业务允许,也可以对卷数据进行打包:
sudo tar -czf /backup/docker-$(date +%F)/docker-volumes.tar.gz /var/lib/docker/volumes
3. 检查是否存在远程 Docker API 暴露
这是非常高危的问题。执行:
ps -ef | grep dockerd
如果看到类似配置:
-H tcp://0.0.0.0:2375
说明 Docker API 可能正在无认证暴露,这属于严重安全隐患。
也可以检查端口:
ss -lntp | grep 2375
如发现 2375 端口对外监听,应立即关闭或改为 TLS 认证方式。
四、Docker 漏洞修复总体流程
推荐修复流程如下:
确认版本
↓
备份配置和数据
↓
停止非核心业务或进入维护窗口
↓
升级 Docker Engine / containerd / runc / Compose
↓
重启 Docker 服务
↓
验证容器运行状态
↓
执行安全加固
↓
扫描镜像漏洞
↓
观察业务日志
下面分别介绍主流 Linux 发行版的修复方法。
五、Ubuntu / Debian 系统修复教程
1. 更新软件源
sudo apt-get update
如果此前没有安装 Docker 官方源,建议先安装依赖:
sudo apt-get install -y ca-certificates curl gnupg lsb-release
添加 Docker 官方 GPG Key:
sudo install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg \
| sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
sudo chmod a+r /etc/apt/keyrings/docker.gpg
Debian 用户需要将 URL 中的
ubuntu替换为debian。
添加 Docker 官方仓库:
echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] \
https://download.docker.com/linux/ubuntu \
$(. /etc/os-release && echo "$VERSION_CODENAME") stable" \
| sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
更新索引:
sudo apt-get update
2. 查看可安装版本
apt-cache madison docker-ce
apt-cache madison containerd.io
如果企业内部要求固定版本,可以选择安全版本安装。若没有特殊要求,建议安装官方稳定版最新版本。
3. 升级 Docker 相关组件
sudo apt-get install -y \
docker-ce \
docker-ce-cli \
containerd.io \
docker-buildx-plugin \
docker-compose-plugin
升级完成后重启服务:
sudo systemctl daemon-reload
sudo systemctl restart docker
检查状态:
sudo systemctl status docker --no-pager
验证版本:
docker version
containerd --version
runc --version
docker compose version
六、CentOS / RHEL / Rocky Linux / AlmaLinux 修复教程
1. 安装 yum-utils
sudo yum install -y yum-utils
对于较新的系统,也可能使用 dnf:
sudo dnf install -y dnf-plugins-core
2. 添加 Docker 官方仓库
CentOS / Rocky / AlmaLinux:
sudo yum-config-manager \
--add-repo \
https://download.docker.com/linux/centos/docker-ce.repo
RHEL 用户应根据企业订阅和系统版本选择合适仓库。
3. 更新缓存
sudo yum makecache
或:
sudo dnf makecache
4. 升级 Docker
sudo yum install -y \
docker-ce \
docker-ce-cli \
containerd.io \
docker-buildx-plugin \
docker-compose-plugin
如果已经安装,则可以执行:
sudo yum update -y \
docker-ce \
docker-ce-cli \
containerd.io \
docker-buildx-plugin \
docker-compose-plugin
启动并设置开机自启:
sudo systemctl enable docker
sudo systemctl restart docker
验证:
docker version
containerd --version
runc --version
docker compose version
七、漏洞修复后的安全加固
升级只是第一步。为了降低后续风险,还需要对 Docker 进行加固。
1. 禁止 Docker API 明文暴露
检查 Docker 服务配置:
sudo systemctl cat docker
以及:
cat /etc/docker/daemon.json
如果存在以下内容,需要谨慎处理:
{
"hosts": ["tcp://0.0.0.0:2375", "unix:///var/run/docker.sock"]
}
建议只保留 Unix Socket:
{
"hosts": ["unix:///var/run/docker.sock"]
}
然后重启:
sudo systemctl daemon-reload
sudo systemctl restart docker
如果必须远程管理 Docker API,应使用 TLS 认证,不要开放无认证的 2375 端口。
2. 限制普通用户访问 Docker
加入 docker 用户组的用户,通常等同于具备宿主机 root 权限。因此,应检查哪些用户属于 docker 组:
getent group docker
如果发现非必要用户,应移除:
sudo gpasswd -d username docker
3. 避免挂载 Docker Socket
以下挂载方式非常危险:
volumes:
- /var/run/docker.sock:/var/run/docker.sock
拥有 Docker Socket 的容器可以直接控制宿主机 Docker 服务,可能创建特权容器、挂载宿主机目录,从而突破隔离。
除非是可信的管理组件,例如受控的 CI Runner、监控 Agent,否则不要挂载该文件。
4. 禁止不必要的特权容器
检查特权容器:
docker ps --quiet | xargs docker inspect \
--format '{{.Name}} Privileged={{.HostConfig.Privileged}}'
如果发现:
Privileged=true
应评估是否确有必要。多数业务容器不需要 --privileged。
Docker Compose 中应避免:
privileged: true
如果只是需要特定能力,应使用更细粒度的 capabilities,例如:
cap_add:
- NET_ADMIN
cap_drop:
- ALL
5. 使用只读文件系统
对于无写入需求的服务,可以启用只读根文件系统:
services:
app:
image: your-app:latest
read_only: true
tmpfs:
- /tmp
这可以降低攻击者在容器内写入恶意文件的风险。
6. 限制容器资源
避免容器消耗宿主机全部资源:
docker run -d \
--name app \
--memory=512m \
--cpus=1 \
nginx:latest
Compose 示例:
services:
web:
image: nginx:latest
deploy:
resources:
limits:
cpus: "1.0"
memory: 512M
对于非 Swarm 模式,也可以使用:
services:
web:
image: nginx:latest
mem_limit: 512m
cpus: 1.0
7. 启用日志轮转
如果不限制日志大小,容器日志可能撑满磁盘。
编辑:
sudo vim /etc/docker/daemon.json
加入:
{
"log-driver": "json-file",
"log-opts": {
"max-size": "100m",
"max-file": "3"
}
}
重启 Docker:
sudo systemctl restart docker
八、镜像漏洞扫描与修复
Docker 本身升级后,还需要关注容器镜像中的漏洞。例如镜像内的 OpenSSL、curl、glibc、libxml2、Java、Python 包也可能存在高危漏洞。
推荐使用 Trivy 扫描镜像。
1. 安装 Trivy
Ubuntu / Debian:
sudo apt-get install -y wget apt-transport-https gnupg
wget -qO - https://aquasecurity.github.io/trivy-repo/deb/public.key \
| sudo gpg --dearmor -o /usr/share/keyrings/trivy.gpg
echo "deb [signed-by=/usr/share/keyrings/trivy.gpg] \
https://aquasecurity.github.io/trivy-repo/deb generic main" \
| sudo tee /etc/apt/sources.list.d/trivy.list
sudo apt-get update
sudo apt-get install -y trivy
CentOS / RHEL:
sudo rpm -ivh https://github.com/aquasecurity/trivy/releases/latest/download/trivy_0.50.0_Linux-64bit.rpm
也可以根据官方最新版本下载对应包。
2. 扫描本地镜像
trivy image nginx:latest
只显示高危和严重漏洞:
trivy image --severity HIGH,CRITICAL nginx:latest
扫描当前所有本地镜像:
docker images --format '{{.Repository}}:{{.Tag}}' \
| grep -v '' \
| xargs -I {} trivy image --severity HIGH,CRITICAL {}
3. 修复镜像漏洞
镜像漏洞修复通常有以下方式:
方式一:升级基础镜像
例如原 Dockerfile:
FROM ubuntu:20.04
可以升级为:
FROM ubuntu:22.04
或:
FROM debian:bookworm-slim
方式二:在构建阶段更新系统包
FROM debian:bookworm-slim
RUN apt-get update \
&& apt-get upgrade -y \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/*
方式三:减少镜像体积
不需要的包越多,漏洞面越大。建议使用 slim、alpine 或 distroless 镜像。
例如 Go 项目可以使用多阶段构建:
FROM golang:1.22 AS builder
WORKDIR /src
COPY . .
RUN go mod download
RUN CGO_ENABLED=0 GOOS=linux go build -o app .
FROM gcr.io/distroless/static-debian12
COPY --from=builder /src/app /app
USER nonroot:nonroot
ENTRYPOINT ["/app"]
九、附源码:Docker 漏洞检查脚本
下面提供一个 Bash 脚本,用于自动收集 Docker 版本、检查高风险配置、列出特权容器、检测 Docker Socket 挂载,并输出基础安全报告。
保存为:
docker_security_check.sh
源码如下:
#!/usr/bin/env bash
set -euo pipefail
REPORT_FILE="docker-security-report-$(date +%F-%H%M%S).txt"
echo "Docker Security Check Report" | tee "$REPORT_FILE"
echo "Generated At: $(date)" | tee -a "$REPORT_FILE"
echo "==================================================" | tee -a "$REPORT_FILE"
echo "" | tee -a "$REPORT_FILE"
echo "[1] System Information" | tee -a "$REPORT_FILE"
echo "--------------------------------------------------" | tee -a "$REPORT_FILE"
if [ -f /etc/os-release ]; then
cat /etc/os-release | tee -a "$REPORT_FILE"
fi
echo "Kernel: $(uname -a)" | tee -a "$REPORT_FILE"
echo "" | tee -a "$REPORT_FILE"
echo "[2] Docker Version" | tee -a "$REPORT_FILE"
echo "--------------------------------------------------" | tee -a "$REPORT_FILE"
if command -v docker >/dev/null 2>&1; then
docker version 2>&1 | tee -a "$REPORT_FILE"
else
echo "Docker command not found." | tee -a "$REPORT_FILE"
exit 1
fi
echo "" | tee -a "$REPORT_FILE"
echo "[3] containerd Version" | tee -a "$REPORT_FILE"
echo "--------------------------------------------------" | tee -a "$REPORT_FILE"
if command -v containerd >/dev/null 2>&1; then
containerd --version 2>&1 | tee -a "$REPORT_FILE"
else
echo "containerd command not found." | tee -a "$REPORT_FILE"
fi
echo "" | tee -a "$REPORT_FILE"
echo "[4] runc Version" | tee -a "$REPORT_FILE"
echo "--------------------------------------------------" | tee -a "$REPORT_FILE"
if command -v runc >/dev/null 2>&1; then
runc --version 2>&1 | tee -a "$REPORT_FILE"
else
echo "runc command not found." | tee -a "$REPORT_FILE"
fi
echo "" | tee -a "$REPORT_FILE"
echo "[5] Docker Compose Version" | tee -a "$REPORT_FILE"
echo "--------------------------------------------------" | tee -a "$REPORT_FILE"
docker compose version 2>&1 | tee -a "$REPORT_FILE" || true
echo "" | tee -a "$REPORT_FILE"
echo "[6] Docker Daemon Listening Ports" | tee -a "$REPORT_FILE"
echo "--------------------------------------------------" | tee -a "$REPORT_FILE"
if command -v ss >/dev/null 2>&1; then
ss -lntp | grep -E '2375|2376' | tee -a "$REPORT_FILE" || echo "No Docker TCP API port found." | tee -a "$REPORT_FILE"
else
netstat -lntp 2>/dev/null | grep -E '2375|2376' | tee -a "$REPORT_FILE" || echo "No Docker TCP API port found." | tee -a "$REPORT_FILE"
fi
echo "" | tee -a "$REPORT_FILE"
echo "[7] Docker Group Users" | tee -a "$REPORT_FILE"
echo "--------------------------------------------------" | tee -a "$REPORT_FILE"
getent group docker | tee -a "$REPORT_FILE" || echo "Docker group not found." | tee -a "$REPORT_FILE"
echo "" | tee -a "$REPORT_FILE"
echo "[8] Privileged Containers" | tee -a "$REPORT_FILE"
echo "--------------------------------------------------" | tee -a "$REPORT_FILE"
CONTAINERS=$(docker ps -q || true)
if [ -z "$CONTAINERS" ]; then
echo "No running containers." | tee -a "$REPORT_FILE"
else
for cid in $CONTAINERS; do
docker inspect "$cid" \
--format 'Name={{.Name}} Image={{.Config.Image}} Privileged={{.HostConfig.Privileged}}' \
| tee -a "$REPORT_FILE"
done
fi
echo "" | tee -a "$REPORT_FILE"
echo "[9] Containers Mounting Docker Socket" | tee -a "$REPORT_FILE"
echo "--------------------------------------------------" | tee -a "$REPORT_FILE"
if [ -n "$CONTAINERS" ]; then
for cid in $CONTAINERS; do
RESULT=$(docker inspect "$cid" \
--format '{{.Name}} {{range .Mounts}}{{.Source}}:{{.Destination}} {{end}}' \
| grep '/var/run/docker.sock' || true)
if [ -n "$RESULT" ]; then
echo "$RESULT" | tee -a "$REPORT_FILE"
fi
done
else
echo "No running containers." | tee -a "$REPORT_FILE"
fi
echo "" | tee -a "$REPORT_FILE"
echo "[10] Docker Daemon Config" | tee -a "$REPORT_FILE"
echo "--------------------------------------------------" | tee -a "$REPORT_FILE"
if [ -f /etc/docker/daemon.json ]; then
cat /etc/docker/daemon.json | tee -a "$REPORT_FILE"
else
echo "/etc/docker/daemon.json not found." | tee -a "$REPORT_FILE"
fi
echo "" | tee -a "$REPORT_FILE"
echo "==================================================" | tee -a "$REPORT_FILE"
echo "Report saved to: $REPORT_FILE" | tee -a "$REPORT_FILE"
赋予执行权限:
chmod +x docker_security_check.sh
执行:
sudo ./docker_security_check.sh
执行后会生成类似文件:
docker-security-report-2026-06-13-103000.txt
你可以将该报告作为漏洞修复前后的对比依据。
十、附源码:Docker 一键升级脚本
下面脚本适用于常见 Linux 系统,会自动识别包管理器,并升级 Docker 相关组件。
注意:生产环境请先在测试环境验证,并安排维护窗口执行。
保存为:
docker_upgrade.sh
源码如下:
#!/usr/bin/env bash
set -euo pipefail
echo "=========================================="
echo " Docker Upgrade Script"
echo "=========================================="
if [ "$(id -u)" -ne 0 ]; then
echo "Please run as root."
exit 1
fi
echo "[1] Current Docker Version"
docker version || true
echo ""
echo "[2] Backup Docker Config"
BACKUP_DIR="/backup/docker-upgrade-$(date +%F-%H%M%S)"
mkdir -p "$BACKUP_DIR"
if [ -d /etc/docker ]; then
cp -a /etc/docker "$BACKUP_DIR/"
fi
docker ps --format "table {{.Names}}\t{{.Image}}\t{{.Status}}\t{{.Ports}}" \
> "$BACKUP_DIR/containers.txt" || true
docker images > "$BACKUP_DIR/images.txt" || true
echo "Backup saved to: $BACKUP_DIR"
echo ""
echo "[3] Detect Package Manager"
if command -v apt-get >/dev/null 2>&1; then
PKG_MANAGER="apt"
elif command -v dnf >/dev/null 2>&1; then
PKG_MANAGER="dnf"
elif command -v yum >/dev/null 2>&1; then
PKG_MANAGER="yum"
else
echo "Unsupported package manager."
exit 1
fi
echo "Package manager: $PKG_MANAGER"
echo ""
echo "[4] Upgrade Docker Packages"
case "$PKG_MANAGER" in
apt)
apt-get update
apt-get install -y \
docker-ce \
docker-ce-cli \
containerd.io \
docker-buildx-plugin \
docker-compose-plugin
;;
dnf)
dnf makecache
dnf update -y \
docker-ce \
docker-ce-cli \
containerd.io \
docker-buildx-plugin \
docker-compose-plugin
;;
yum)
yum makecache
yum update -y \
docker-ce \
docker-ce-cli \
containerd.io \
docker-buildx-plugin \
docker-compose-plugin
;;
esac
echo ""
echo "[5] Restart Docker"
systemctl daemon-reload
systemctl restart docker
systemctl enable docker
echo ""
echo "[6] New Docker Version"
docker version
containerd --version || true
runc --version || true
docker compose version || true
echo ""
echo "Docker upgrade completed successfully."
赋权并执行:
chmod +x docker_upgrade.sh
sudo ./docker_upgrade.sh
十一、修复后验证清单
漏洞修复完成后,不要只看 Docker 服务是否启动,还应检查业务和安全配置。
1. 检查 Docker 服务状态
systemctl status docker --no-pager
2. 检查容器状态
docker ps -a
重点关注是否有容器异常退出:
docker ps -a --filter "status=exited"
3. 检查业务端口
ss -lntp
4. 查看容器日志
docker logs --tail=100 容器名
5. 检查 Docker API 暴露
ss -lntp | grep -E '2375|2376'
如果仍发现 2375 明文端口,需要继续整改。
6. 重新执行安全检查脚本
sudo ./docker_security_check.sh
对比修复前后的报告,确认:
- Docker 版本已更新;
- containerd 和 runc 已更新;
- 无未授权 Docker API 暴露;
- 无不必要的特权容器;
- 无异常 Docker Socket 挂载;
- Docker 日志轮转已配置;
- 镜像漏洞已扫描并修复。
十二、常见问题排查
问题一:升级后 Docker 无法启动
查看日志:
journalctl -u docker -xe --no-pager
常见原因包括:
/etc/docker/daemon.jsonJSON 格式错误;- 配置了冲突的启动参数;
- 存储驱动异常;
- 旧版本配置与新版本不兼容。
可以先校验 JSON:
python3 -m json.tool /etc/docker/daemon.json
如果有错误,修复后重启:
systemctl restart docker
问题二:升级后容器无法访问网络
可以检查 Docker 网络:
docker network ls
docker network inspect bridge
查看 iptables:
iptables -S
或 nftables:
nft list ruleset
必要时重启 Docker:
systemctl restart docker
问题三:旧版 docker-compose 命令不可用
新版 Docker 推荐使用:
docker compose
而不是:
docker-compose
如果脚本中仍使用 docker-compose,可以临时安装兼容版本,或将命令替换为:
docker compose up -d
docker compose down
docker compose logs
十三、生产环境建议
为了长期降低 Docker 漏洞风险,建议建立以下机制:
-
定期升级机制
每月至少检查一次 Docker Engine、containerd、runc 和 Compose 版本。 -
镜像准入机制
所有镜像上线前必须经过漏洞扫描,不允许存在未处理的严重漏洞。 -
最小权限原则
默认不使用--privileged,默认不挂载 Docker Socket。 -
配置基线检查
将 Docker 安全配置纳入主机安全基线,例如日志轮转、API 禁止明文暴露、用户组控制等。 -
镜像签名与可信来源
尽量使用官方镜像、企业内部镜像仓库,并结合镜像签名机制。 -
运行时监控
对异常进程、异常网络连接、异常文件写入进行监控。 -
备份与回滚方案
每次升级前应有备份,每次升级后应有明确回滚路径。
十四、总结
Docker 漏洞修复不能只停留在“升级 Docker 版本”这一层面。完整的修复流程应该包括:
- 识别 Docker Engine、containerd、runc、Compose 等组件版本;
- 备份配置、镜像和关键数据;
- 使用官方源升级到安全稳定版本;
- 检查 Docker API 是否暴露;
- 移除不必要的 docker 组用户;
- 禁止危险的特权容器和 Docker Socket 挂载;
- 配置日志轮转和资源限制;
- 扫描并修复容器镜像漏洞;
- 使用自动化脚本生成安全报告;
- 在生产环境建立长期漏洞治理机制。
通过本文提供的检测脚本和升级脚本,你可以快速完成 Docker 漏洞排查、修复和验证工作。对于生产集群,建议先在测试环境验证脚本和升级流程,再逐步灰度上线,确保业务稳定性与安全性兼顾。