Docker:渗透前置容器化核心基础
- Docker:渗透前置容器化核心基础
- 前言:容器环境与渗透学习链路
-
- [1 Docker 容器核心认知](#1 Docker 容器核心认知)
-
- [1.1 容器核心定义](#1.1 容器核心定义)
- [1.2 容器VS虚拟机客观认知纠正](#1.2 容器VS虚拟机客观认知纠正)
- [1.3 渗透场景下Docker核心价值](#1.3 渗透场景下Docker核心价值)
- [1.4 Docker核心三要素:镜像/容器/仓库](#1.4 Docker核心三要素:镜像/容器/仓库)
- [1.5 底层依托:Linux Namespace/Cgroups极简原理](#1.5 底层依托:Linux Namespace/Cgroups极简原理)
- [2 Docker Kali系统标准化安装](#2 Docker Kali系统标准化安装)
-
- [2.1 系统残留冲突组件清理](#2.1 系统残留冲突组件清理)
- [2.2 Docker Engine官方正规安装](#2.2 Docker Engine官方正规安装)
- [2.3 国内镜像源加速器配置](#2.3 国内镜像源加速器配置)
- [2.4 docker用户组权限规范(免sudo安全说明)](#2.4 docker用户组权限规范(免sudo安全说明))
- [2.5 服务启停与开机自启管理](#2.5 服务启停与开机自启管理)
- [2.6 安装报错与环境自检排错](#2.6 安装报错与环境自检排错)
- [3 Docker 镜像核心管理](#3 Docker 镜像核心管理)
-
- [3.1 镜像分层存储原理](#3.1 镜像分层存储原理)
- [3.2 pull 拉取镜像与标签规范](#3.2 pull 拉取镜像与标签规范)
- [3.3 images 本地镜像列表完整解析](#3.3 images 本地镜像列表完整解析)
- [3.4 tag 镜像重命名与私有打标](#3.4 tag 镜像重命名与私有打标)
- [3.5 rmi 删除镜像](#3.5 rmi 删除镜像)
- [3.6 虚悬/废弃镜像批量清理](#3.6 虚悬/废弃镜像批量清理)
- [4 Docker 容器核心操作命令](#4 Docker 容器核心操作命令)
-
- [4.1 run 容器创建启动(渗透核心指令)](#4.1 run 容器创建启动(渗透核心指令))
-
- [4.1.1 -p 端口映射原理与实操](#4.1.1 -p 端口映射原理与实操)
- [4.1.2 -v 数据挂载核心作用](#4.1.2 -v 数据挂载核心作用)
- [4.1.3 --name / -d 后台运行参数](#4.1.3 --name / -d 后台运行参数)
- [4.2 ps 容器状态查看字段解析](#4.2 ps 容器状态查看字段解析)
- [4.3 start/stop/restart 容器生命周期控制](#4.3 start/stop/restart 容器生命周期控制)
- [4.4 exec 进入容器终端(主流交互方式)](#4.4 exec 进入容器终端(主流交互方式))
- [4.5 attach 交互模式坑点规避](#4.5 attach 交互模式坑点规避)
- [4.6 rm 容器删除与批量清理](#4.6 rm 容器删除与批量清理)
- [5 容器数据持久化与挂载实战](#5 容器数据持久化与挂载实战)
-
- [5.1 容器临时数据丢失机制](#5.1 容器临时数据丢失机制)
- [5.2 绑定挂载Bind Mount实操](#5.2 绑定挂载Bind Mount实操)
- [5.3 数据卷Volume管理](#5.3 数据卷Volume管理)
- [5.4 渗透场景挂载风险警示](#5.4 渗透场景挂载风险警示)
- [6 Docker 信息排查与取证命令](#6 Docker 信息排查与取证命令)
-
- [6.1 inspect 容器/镜像底层信息解析](#6.1 inspect 容器/镜像底层信息解析)
- [6.2 logs 容器运行日志查看](#6.2 logs 容器运行日志查看)
- [6.3 top 查看容器内部进程](#6.3 top 查看容器内部进程)
- [6.4 diff 检测容器文件篡改痕迹](#6.4 diff 检测容器文件篡改痕迹)
- [7 Dockerfile 自定义渗透镜像](#7 Dockerfile 自定义渗透镜像)
-
- [7.1 镜像分层构建原理](#7.1 镜像分层构建原理)
- [7.2 高频指令:FROM/RUN/COPY/CMD 详解](#7.2 高频指令:FROM/RUN/COPY/CMD 详解)
- [7.3 build 构建自定义镜像](#7.3 build 构建自定义镜像)
- [8 Docker Compose 靶场编排核心](#8 Docker Compose 靶场编排核心)
-
- [8.1 Compose 适用场景(多服务靶场)](#8.1 Compose 适用场景(多服务靶场))
- [8.2 yaml 配置文件核心字段解析](#8.2 yaml 配置文件核心字段解析)
- [8.3 up/down/logs 核心编排命令](#8.3 up/down/logs 核心编排命令)
-
- [8.3.1. 启动靶场:docker compose up](#8.3.1. 启动靶场:docker compose up)
- [8.3.2. 销毁靶场:docker compose down](#8.3.2. 销毁靶场:docker compose down)
- [8.3.3. 查看日志:docker compose logs](#8.3.3. 查看日志:docker compose logs)
- [8.3.4. 其他常用编排命令](#8.3.4. 其他常用编排命令)
- [8.4 一键部署开源漏洞靶场实操(Vulhub)](#8.4 一键部署开源漏洞靶场实操(Vulhub))
-
- [步骤 1:安装 git 工具](#步骤 1:安装 git 工具)
- [步骤 2:克隆 Vulhub 仓库](#步骤 2:克隆 Vulhub 仓库)
- [步骤 3:选择漏洞环境并进入目录](#步骤 3:选择漏洞环境并进入目录)
- [步骤 4:查看编排配置文件](#步骤 4:查看编排配置文件)
- [步骤 5:一键启动漏洞环境](#步骤 5:一键启动漏洞环境)
- [步骤 6:查看服务运行状态](#步骤 6:查看服务运行状态)
- [步骤 7:访问漏洞页面验证](#步骤 7:访问漏洞页面验证)
- [步骤 8:销毁漏洞环境](#步骤 8:销毁漏洞环境)
- [9 Docker 安全风险与渗透攻防要点](#9 Docker 安全风险与渗透攻防要点)
-
- [9.1 docker组权限逃逸原理与防御](#9.1 docker组权限逃逸原理与防御)
- [9.2 挂载宿主机目录高危漏洞](#9.2 挂载宿主机目录高危漏洞)
- [9.3 容器内信息搜集与环境探测](#9.3 容器内信息搜集与环境探测)
- [9.4 容器逃逸基础前置认知](#9.4 容器逃逸基础前置认知)
- 总结
Docker:渗透前置容器化核心基础
前言:容器环境与渗透学习链路
在学习完《Kali Linux:渗透前置终端核心基础 》后,你已经掌握了 Linux 系统底层逻辑、终端命令、权限体系、进程日志与网络基础 。这些内容是渗透测试的硬件级地基 ,而本章要讲解的 Docker ,是渗透测试的软件级工程地基。
很多入门学习者会有一个误区:掌握 Kali 命令后,直接上手漏洞复现、靶场渗透、工具开发 ,最终频繁遇到环境报错、依赖冲突、系统污染、版本不兼容 等问题。究其根本,不是你的命令基础不扎实,而是缺少标准化的隔离运行环境。
在当下的红队攻防、渗透测试、漏洞研究 领域,Docker 已经成为刚需基础设施,而非可选工具。我们可以直白定义它的核心价值:Docker 是一套基于 Linux 内核的轻量级容器引擎,用于打包、分发、隔离运行程序与完整环境。
1 Docker 容器核心认知
1.1 容器核心定义
从Linux内核视角来看,容器是一种基于内核隔离技术的轻量级虚拟运行环境 。它并非完整复刻一套操作系统,而是依托宿主机原生Linux内核,通过资源隔离与文件封装,为程序提供独立的运行目录、网络空间、进程视图与权限边界。
简单通俗定义:容器就是把程序、依赖库、运行环境打包在一起,在隔离空间内运行的"便携沙箱" 。它复用宿主机内核,仅隔离用户态资源,因此具备体积小、启动快、性能无损耗三大核心特征,这也是它区别于虚拟机的本质根源。
1.2 容器VS虚拟机客观认知纠正
绝大多数初学者会混淆容器与虚拟机,甚至认为二者只是"大小区别",这是典型认知误区,必须从底层架构纠正。
虚拟机(VM) :属于硬件级虚拟化,基于Hypervisor虚拟化CPU、内存、磁盘、网卡整套硬件资源,内部需要完整加载独立操作系统内核(Windows/Linux)。虚拟机拥有完整硬件栈隔离,但占用资源大、启动慢、内核层级冗余。
容器(Docker) :属于系统级虚拟化,不虚拟化硬件,不自带内核,直接复用Kali宿主机Linux内核,仅通过内核API隔离进程、文件、网络、用户组。容器秒级启动、磁盘占用极小、性能与原生主机无差异。
渗透场景一句话区分:虚拟机用来隔离整套系统,容器用来隔离单个/一组攻防服务与工具环境。
1.3 渗透场景下Docker核心价值
脱离渗透谈Docker开发用法没有意义,本节聚焦红队/渗透测试专属价值,也是你必须掌握Docker的核心原因:
-
环境零污染 :所有靶场、老旧工具、特殊依赖全部运行在容器内,删除容器即可清空环境,永不污染宿主Kali系统;
-
依赖强制统一 :老旧漏洞、Python2、特定版本组件可封装进镜像,规避本机依赖冲突;
-
快速搭建靶场 :当代绝大多数CVE漏洞靶场、AWD攻防环境、WEB漏洞平台均基于Docker Compose编排;
-
工具便携分发 :自定义封装带后门、扫描器、代理环境的专属镜像,任意主机拉取即可直接作战;
-
隔离边界防护:容器默认资源受限,可规避恶意工具、恶意样本直接读取宿主机敏感文件,提升测试安全性。
1.4 Docker核心三要素:镜像/容器/仓库
Docker的全部操作,本质围绕镜像、容器、仓库三个核心对象流转,三者关系必须牢记:
镜像(Image) :只读的静态模板,相当于系统/工具的"安装包",包含程序、依赖、配置、基础文件系统,不可写入修改 ;
容器(Container) :由镜像运行生成的可运行实例,是读写的动态沙箱,一个镜像可以同时启动无数个独立容器;
仓库(Registry):存放、分发镜像的远程服务器,官方公共仓库为Docker Hub,企业/团队可搭建私有仓库存放专属攻防镜像。
极简流转逻辑:仓库拉取镜像 → 镜像运行生成容器 → 容器修改后可重新打包为新镜像 → 推送至仓库分发。
1.5 底层依托:Linux Namespace/Cgroups极简原理
Docker本身不是虚拟化技术,也没有独立开发隔离逻辑,它全部的隔离、限制能力都调用Linux内核自带底层模块实现,这也是Windows、Mac系统必须依靠虚拟机搭载Linux内核才能运行Docker的根本原因。前面章节我们学习过Linux进程、用户、权限、网络等基础内容,Namespace与Cgroups就是内核专门用来切割资源边界的两套核心组件,是理解容器逃逸、容器权限漏洞的前置理论,不能浅尝辄止。
简单概括两者分工:Namespace负责「隔离看得到什么」,Cgroups负责「限制能用多少」。两套机制叠加,才构成容器完整的隔离边界。
Namespace(命名空间):视图隔离,分割"可见范围"
Namespace的作用是给进程分配独立视图。同一个宿主机上,宿主机进程能看到全部系统资源,容器内进程只能看见分配给自己的那一部分,看不见宿主机及其他容器的资源。Linux内核提供7种标准命名空间,Docker全部启用,分别隔离不同维度资源:
| Namespace类型 | 隔离对象 | 渗透核心意义 |
|---|---|---|
| PID Namespace | 进程编号 | 容器内PID从1重新计数,看不到宿主机进程;但宿主机能看到容器全部进程,是权限不对等关键点 |
| Mount Namespace | 文件挂载点 | 容器拥有独立文件系统视图,默认无法读取宿主机根目录;-v手动挂载会直接打通,是容器逃逸最常用突破口 |
| Network Namespace | 网络栈 | 每个容器有独立网卡、IP、端口、路由表;默认容器间无法互通,需端口映射或网桥打通 |
| User Namespace | 用户/用户组ID | 容器内root映射到宿主机为普通低权限用户;多数靶场为方便操作关闭该隔离,逃逸风险大幅提升 |
| UTS Namespace | 主机名/域名 | 容器可自定义独立hostname,与宿主机互不干扰 |
| IPC Namespace | 进程间通信 | 容器内进程只能与同容器进程交互,阻断跨容器IPC通信 |
| Cgroup Namespace | 控制组视图 | 容器内无法读取宿主机Cgroup限制配置 |
只要任意一种Namespace存在隔离缺陷,攻击者就可以突破视图限制,读取宿主机进程、文件、网络信息,完成信息搜集与权限探测。
Cgroups(控制组):资源限流,约束"可用资源上限"
Namespace解决"看得见哪些资源",Cgroups解决"最多能用多少资源"。专门对一组进程做硬件资源配额限制,防止单个容器恶意占用整机资源,造成宿主机卡顿、崩溃,渗透场景下可抵御恶意靶场、恶意样本发起资源耗尽攻击。
| Cgroup子系统 | 限制内容 | 渗透场景作用 |
|---|---|---|
| CPU Cgroup | CPU核心数、最大使用率 | 防止容器满负载跑满全部处理器,避免宿主机死机 |
| Memory Cgroup | 最大可用内存 | 超出阈值进程被内核强制终止,防止恶意程序疯狂占内存 |
| BlkIO Cgroup | 磁盘读写速度 | 限制容器磁盘IO速率,避免大量读写拖慢宿主机整体性能 |
| Net_cls Cgroup | 网络带宽 | 标记容器网络数据包,配合tc工具限制上下行带宽,防止流量占满 |
核心结论必须牢记:Docker隔离 = Namespace视图隔离 + Cgroups资源限制。所有容器逃逸、权限绕过漏洞,本质都是突破这两层内核机制中的某一层或多层。理解这个底层逻辑,后面学习容器逃逸、Docker提权时才能真正看懂原理,而不是死记命令。
2 Docker Kali系统标准化安装
2.1 系统残留冲突组件清理
Kali系统自带旧版docker相关组件,版本老旧且容易与官方新版Docker Engine产生端口、服务冲突,安装前必须彻底卸载清理。执行清理命令移除docker.io、docker-doc等系统预装包,同时删除残留配置目录,避免后续启动失败。
bash
apt remove docker.io docker-doc docker-compose podman-docker containerd runc -y
rm -rf /var/lib/docker /etc/docker
清理完成后通过apt list --installed | grep docker校验,无任何docker相关输出即代表清理干净。
bash
apt list --installed | grep docker
2.2 Docker Engine官方正规安装
不推荐直接使用apt默认仓库的简化版docker,性能与功能存在阉割,渗透靶场编排、自定义镜像构建会出现兼容问题。本节采用Docker官方Deb源完整安装Docker Engine,包含客户端、服务端、容器运行时全套组件。
操作流程分为三步:导入官方GPG密钥校验软件合法性、写入Docker专属软件源、更新索引后批量安装docker-ce、docker-ce-cli、containerd。
bash
apt update && apt install ca-certificates curl gnupg lsb-release -y
curl -fsSL https://download.docker.com/linux/debian/gpg | gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/debian $(lsb_release -cs) stable" | tee /etc/apt/sources.list.d/docker.list > /dev/null
apt update && apt install docker-ce docker-ce-cli containerd.io -y
安装结束执行docker -v查看版本,输出版本号说明安装成功。
bash
docker -v
显示如下版本号即为安装成功

2.3 国内镜像源加速器配置
默认从Docker Hub拉取镜像网络延迟极高,大体积漏洞靶场镜像极易出现超时失败,需要配置国内镜像加速器加速拉取。通过修改docker守护进程配置文件/etc/docker/daemon.json写入镜像地址,配置完成重载docker服务生效。
bash
cat > /etc/docker/daemon.json <<EOF
{
"registry-mirrors": ["国内镜像地址"]
}
EOF
systemctl daemon-reload
systemctl restart docker
使用docker info命令查看加速器配置是否加载成功,镜像加速器仅作用于镜像下载,不影响容器网络访问。
bash
docker info
能看到这部分说明已经配置好了

2.4 docker用户组权限规范(免sudo安全说明)
docker服务后台进程以root最高权限运行,默认只有root用户能直接调用docker相关命令。普通用户直接执行docker ps、docker pull会报权限不足,每次操作都要额外加上sudo,使用十分繁琐。我们可以将当前登录的普通用户加入docker系统用户组,实现免sudo执行所有docker操作。
bash
usermod -aG docker $USER
- usermod:系统修改用户信息工具
- -aG:将用户追加至指定附属用户组,不覆盖用户原有分组权限
- docker:系统内置docker专属权限组
- $USER:环境变量,自动指代当前登录用户名
未执行这条命令前的现象(直接运行docker命令会报错) :
直接在终端输入docker ps,终端输出权限拒绝报错,效果如下:

执行这条命令后发生的变化:
- 系统把你当前登录的普通用户,添加进名为
docker的系统权限组; - 当前终端会话权限不立刻更新,此时敲docker命令依然会权限报错;
- 注销Kali账户、重新登录系统后,权限完全生效,无需输入sudo就能直接使用所有docker指令(docker pull、docker run、docker ps等)。

可以看到这里的倒数第二个已经有docker了说明执行成功了
这个时候再次运行docker ps就不会显示权限问题了

安全重点提醒:docker用户组权限等同于半root管理员权限,这是渗透测试必须重视的高危风险点。宿主机的
/var/run/docker.sock套接字文件归属于docker组,拥有该组权限即可完全操控容器引擎。一旦运行容器时使用高危挂载参数,攻击者就能突破容器隔离实现容器逃逸,读取、篡改宿主机全部文件,造成内网密钥、渗透报告、账号密码等敏感数据泄露。日常搭建靶场、运行工具时,尽量不要挂载宿主机根目录、docker套接字等高风险路径。
2.5 服务启停与开机自启管理
Docker依托systemd进行服务管理,命令格式与前文学习的systemctl统一。常用操作包含启动、停止、重启docker服务,设置开机自启、取消开机自启。
bash
systemctl start docker
systemctl stop docker
systemctl restart docker
systemctl enable docker
systemctl disable docker
实操配置建议:
-
必执行开机自启命令
systemctl enable docker每次开机自动启动Docker后台服务,无需手动启动,重启机器后靶场、镜像配置全部保留,适合长期做漏洞复现、搭建攻防环境;此时需要输入管理员密码

-
start/stop/restart属于临时操作,无需提前配置,出现镜像拉取失败、服务异常时再执行重启;
-
仅长期不使用容器、离线节省系统资源时,执行systemctl disable docker取消开机自启。
-
使用
systemctl status docker检测docker是否已经启动了
渗透实操场景:离线环境可临时关闭docker节省内存;长期搭建靶场环境设置开机自启,重启主机后容器自动恢复运行。
2.6 安装报错与环境自检排错
整理Kali安装Docker高频故障:源密钥校验失败、端口被旧组件占用、镜像加速器配置格式错误、用户组权限未生效、服务启动崩溃。
自检流程:查看docker服务状态、读取服务日志journalctl、校验daemon.json语法、核对系统内核版本是否满足最低要求,按流程排查可快速定位绝大多数安装异常。
bash
systemctl status docker
journalctl -u docker
-
systemctl status docker直观展示服务启停状态,绿色
active (running)代表正常运行;出现红色报错、inactive (dead)说明服务启动失败,可初步判断故障。
-
journalctl -u docker读取
systemd记录的Docker完整运行日志,配置文件写错、端口冲突、镜像源解析失败、内核不兼容等底层报错都会完整输出,用于深度排错。
3 Docker 镜像核心管理
3.1 镜像分层存储原理
Docker 镜像采用分层只读存储架构,是镜像的核心底层设计,所有镜像均由多层文件堆叠构成:
- 基础底层:操作系统基础文件层(如debian、alpine),本地多个镜像可共享同一基础层,避免重复占用磁盘;
- 增量只读层:执行安装软件、修改配置等操作时,仅新增一层只读文件,上层同名文件会覆盖下层,底层原始分层永久不变;
- 容器临时读写层:容器启动时,会在镜像最顶层自动生成一层可读写临时层,容器销毁后该读写层同步删除,原始镜像文件完全不受修改影响。
分层存储两大优势:多镜像共享分层节省磁盘;更新镜像仅下载变更分层,大幅提升拉取速度。
通俗大白话解释:
镜像像搭积木,底层系统积木所有镜像共用,只存一份,不重复占硬盘;
镜像每一步操作单独做成一层积木,所有积木只能看不能改,新文件直接盖住旧文件,底层原始内容永远不会损坏;
镜像本身固定不变,只有启动容器时才会多一层临时可修改空间,你在容器里改的所有内容都只存在这一层,删掉容器,修改内容直接消失,镜像完好如初;
优势总结:共享底层减少磁盘占用,更新镜像只下载改动的分层,不用完整重下,下载速度更快。
补充:镜像 vs 容器核心区别镜像:静态、只读的安装包模板,相当于系统/软件安装光盘,不能运行、无法写入修改;
容器:基于镜像运行出来的动态实例,相当于装好系统正在运行的电脑,拥有独立可读写临时层,可以修改文件、运行程序;
关系:一个镜像可以同时启动无数个独立容器;删除容器不会损伤镜像,删除镜像会导致无法再新建容器。
3.2 pull 拉取镜像与标签规范
docker pull 作用:从远程镜像仓库(Docker Hub/私有仓库)下载镜像至本地。
bash
docker pull [仓库地址]/镜像名:标签
标签规范说明:
- 标签代表镜像版本,不写标签默认拉取
latest(最新版),生产/靶场环境不推荐latest,版本不稳定; - 常用标签:系统版本(ubuntu:22.04)、软件版本(mysql:5.7)、轻量化alpine版(nginx:alpine);
例如:
bash
docker pull maven:3.9
docker pull nginx:stable-alpine
这里我们拉去一个docker的hello-world镜像

3.3 images 本地镜像列表完整解析
查看本地全部已下载镜像基础命令:
bash
docker images
输出字段解析:
- REPOSITORY:镜像仓库/镜像名称;
- TAG:镜像版本标签;
- IMAGE ID:镜像唯一ID,全局唯一标识镜像;
- CREATED:镜像制作时间;
- SIZE:镜像占用本地磁盘大小。

现象说明:如果执行docker images后表格空白,代表本地无任何镜像,多为pull拉取镜像失败导致。
拓展查询命令:
显示所有镜像(包含虚悬废弃镜像)
bash
docker images -a

仅打印镜像ID,用于批量删除操作
bash
docker images -q

过滤查询指定名称镜像
bash
docker images nginx

3.4 tag 镜像重命名与私有打标
docker tag 不会复制镜像文件,仅给原有镜像新增别名标签,共享同一分层,不额外占用磁盘。
语法:
bash
docker tag 原镜像名:原标签 新镜像名:新标签
实操场景:
-
本地镜像重命名:
docker tag nginx:stable-alpine mynginx:v1
-
私有仓库打标上传:docker tag nginx:stable-alpine 192.168.1.100:5000/nginx:stable-alpine

3.5 rmi 删除镜像
docker rmi 用于删除本地无用镜像,支持「镜像名+标签」「镜像ID」两种删除语法。
- 根据镜像名称+标签删除
bash
docker rmi 镜像名:标签
例如:docker rmi nginx:stable-alpine
执行 docker rmi nginx:stable-alpine 只输出 Untagged(取消标签绑定),没有删除镜像实体因为还有另外两个标签指向该镜像,底层分层文件依然保留,所以列表里还能看到这条镜像 ID

- 根据镜像ID删除(支持短ID)
bash
docker rmi 镜像ID
实操示例(本机nginx完整ID)
bash
docker rmi 0d3b80406a13

镜像 ID 0d3b80406a13 绑定了2 个不同仓库标签:
192.168.1.100:5000/nginx:stable-alpine、mynginx:v1
普通 docker rmi 镜像ID 无法直接删除多标签镜像,必须加 -f 强制删除。
短ID简写示例(只输入前4位即可识别)
bash
docker rmi d561

特性:通过镜像ID删除会一次性解绑该镜像全部标签,无容器占用时直接彻底删除镜像文件,无需逐个删除标签。
- 强制删除(镜像被容器占用无法正常删除时加
-f参数)
bash
docker rmi -f 镜像名:标签 / 镜像ID
标签强制删除示例
bash
docker rmi -f mynginx:v1

镜像ID强制删除示例
bash
docker rmi -f 0d3b80406a13

说明:镜像正在被容器使用时,直接执行
docker rmi会报错,必须添加-f强制清理镜像;不推荐频繁强制删除,优先删除关联容器后再删镜像。
3.6 虚悬/废弃镜像批量清理
虚悬镜像(dangling):镜像名、标签均为,构建镜像残留无用分层,长期堆积占用大量磁盘。
单独清理虚悬镜像:
bash
docker image prune

一键清理全部未使用镜像(虚悬+无容器关联的废弃镜像):
bash
docker image prune -a

无交互自动清理(脚本批量执行适用,无需手动确认y):
bash
docker image prune -a -f
4 Docker 容器核心操作命令
此处为了实验方便我们再次运行docker pull nginx:stable-alpine
4.1 run 容器创建启动(渗透核心指令)
4.1.1 -p 端口映射原理与实操
通用语法
bash
-p 宿主机端口:容器端口
示例
bash
docker run -p 8080:80 nginx:stable-alpine
容器内部是独立隔离网络,默认外部主机无法直接访问容器内的服务端口;-p 的作用是建立端口转发通道,把宿主机端口流量转发到容器内部端口。

- 冒号前面 8080 = Kali 宿主机端口,外部浏览器访问 127.0.0.1:8080
- 冒号后面 80 = Nginx 容器内部服务端口
- 访问宿主机 8080,流量会自动转发到容器 80 端口,从而打开 Nginx 网页。

此时终端会显示

4.1.2 -v 数据挂载核心作用
通用语法
bash
-v 宿主机目录:容器内目录
示例
bash
docker run -v /www:/usr/share/nginx/html nginx:stable-alpine
容器默认数据存在临时读写层,容器销毁则数据全部清空;-v 实现宿主机目录与容器目录双向绑定,文件永久保存在宿主机磁盘,容器删除数据也不会丢失。

-v /www:/usr/share/nginx/html:
- 冒号前面 /www = Kali 宿主机本地文件夹,可直接在系统里修改 html 源码
- 冒号后面 /usr/share/nginx/html = Nginx 容器存放网页的根目录
- 宿主机 /www 内的文件会实时同步到容器网页目录,修改文件页面立刻更新。
4.1.3 --name / -d 后台运行参数
-d 后台运行语法
bash
docker run -d 镜像名:标签
--name 指定容器名语法
bash
docker run --name 自定义容器名 镜像名:标签
组合示例
bash
docker run -d --name web-nginx -p 8080:80 nginx:stable-alpine
注意这里直接运行会报错,因为前面已经启动过一次了,用4.2及以后的知识来关掉

4.2 ps 容器状态查看字段解析
基础查看运行中容器
bash
docker ps

查看全部容器(含已停止)
bash
docker ps -a

仅输出容器ID
bash
docker ps -q

4.3 start/stop/restart 容器生命周期控制
启动停止重启通用语法
bash
docker start 容器名/容器ID
docker stop 容器名/容器ID
docker restart 容器名/容器ID
停止刚刚运行的两个容器
bash
docker stop awesome_meitner
docker stop pedantic_herschel

此时再次运行docker run -d --name web-nginx -p 8081:80 -v /www:/usr/share/nginx/html nginx:stable-alpine

此时删除旧容器
bash
docker rm web-nginx
输出 web-nginx,代表名称为 web-nginx 的旧容器已成功删除,名字占用冲突解除。
此时再次运行就好了

使用docker ps检查一遍

4.4 exec 进入容器终端(主流交互方式)
通用语法
bash
docker exec -it 容器名/ID 终端解释器
示例
bash
docker exec -it web-nginx /bin/sh

bash
退出容器回到宿主机
bash
exit
可在容器内执行的验证命令
- 查看网页挂载目录,验证 - v 挂载是否生效
bash
ls /usr/share/nginx/html
在宿主机 /www 创建测试页面
bash
echo "<h1>测试挂载页面</h1>" > /www/index.html
再次进入容器查看目录
bash
docker exec -it web-nginx /bin/sh
ls /usr/share/nginx/html
此时就能看到 index.html 文件

- 查看 nginx 配置文件
bash
cat /etc/nginx/conf.d/default.conf
- 退出容器回到 kali 宿主机终端
bash
exit
alpine 系列镜像无bash,只能使用
/bin/sh进入交互终端;完整发行版镜像(如普通nginx、centos)才支持/bin/bash。
4.5 attach 交互模式坑点规避
bash
docker attach 容器名/ID
① docker attach(不推荐)
作用:直接连上容器前台主进程
缺点:输入 exit 退出终端时,容器主进程直接关闭,容器就停止下线,网站 / 服务直接断。
② docker exec -it(推荐)
作用:新建一个独立的终端窗口,和容器主进程分开
优点:输入 exit 只是退出这个临时终端,容器照常后台运行,不会停机。
4.6 rm 容器删除与批量清理
单容器删除语法
bash
docker rm 容器名/ID
说明:仅能删除已停止的容器,运行中容器直接执行会报错
强制删除运行中容器
bash
docker rm -f 容器名/ID
说明:-f 强制参数,先停止容器再删除,不用手动执行 stop
批量清理所有停止容器
bash
docker container prune
说明:一键清空所有状态为 Exited、Created 的无用容器,不会影响正在 Up 运行的容
首先查看所有容器,确认要删的名字 / ID
bash
docker ps -a
发现STATUS中,正在运行的

① Up X hours/minutes
比如 web-nginx:Up 2 hours → 已经持续运行 2 小时,8080 端口正常可访问
② Exited (0) X hours ago
已经停止、下线的废弃容器,图里下面两个都是这种状态:
e5bfd97b5079、2fb906e9d76b 均已停止,没用可以清理
批量一键清理所有 Exited 容器
bash
docker container prune
现在列表里只剩 web-nginx 这一个容器,状态 Up 2 hours,正在正常后台运行,8080 端口网页服务可用,其余废弃停用容器全部清理干净。

批量清理命令只会清除停机容器,不会影响正在运行的服务,日常清理垃圾容器非常方便。
5 容器数据持久化与挂载实战
5.1 容器临时数据丢失机制
容器默认所有数据都存储在容器内部的临时读写层,数据生命周期和容器绑定:
- 容器运行时,在容器内部新建、修改的文件都保存在读写层;
- 容器删除(docker rm)后,读写层随容器一起销毁,所有数据永久丢失;
- 容器重建后,恢复为镜像初始状态,之前的修改全部消失。
验证数据丢失实验
- 启动一个测试容器,在内部创建文件
bash
docker run -d --name test-data nginx:stable-alpine
docker exec -it test-data /bin/sh
echo "测试数据" > /tmp/test.txt
cat /tmp/test.txt
exit
首先我们输入docker images检查一下我们的目录

普通用户已经在 docker 用户组 → 不用 sudo、不用切 root,直接执行所有 docker 命令,不同于上面第4节里面所说的在根目录创建 /www,文件夹归属 root,普通 kali 用户无写入权限,所以当时必须切换到root目录
运行完命令之后可以发现

echo 命令在 /tmp 目录创建 test.txt 文件,cat 命令能正常输出 "测试数据" 三个字,证明文件创建成功
此时这个 test.txt 文件只存在于 test-data 容器的临时读写层中,宿主机磁盘上找不到这个文件,它完全依附于这个容器。
- 删除并重建同名容器
bash
docker rm -f test-data
docker run -d --name test-data nginx:stable-alpine
docker exec -it test-data /bin/sh
cat /tmp/test.txt

重新 ·docker run· 启动一个同名新容器,返回新的容器 ID,这是一个全新的、干净的容器实例
结果:文件不存在,提示 No such file or directory,证明容器数据不持久化。
结论:网页、配置、数据库、日志等需要长期保存的数据,必须通过挂载持久化到宿主机。
5.2 绑定挂载Bind Mount实操
Bind Mount 直接把宿主机的某个目录映射到容器内部,两边文件实时同步。
通用语法
-v 宿主机绝对路径:容器内路径
实操示例(Nginx网页挂载)
bash
docker run -d --name web-nginx -p 8080:80 -v /www:/usr/share/nginx/html nginx:stable-alpine
参数说明
| 参数位置 | 示例值 | 说明 |
|---|---|---|
| 冒号前 | /www | Kali宿主机本地文件夹路径,文件永久保存在这里 |
| 冒号后 | /usr/share/nginx/html | Nginx容器内网页根目录,容器从这里读取网页文件 |
验证挂载效果
- 宿主机创建网页文件
bash
sudo echo "<h1>绑定挂载测试页面</h1>" > /www/index.html
- 进入容器查看,文件已同步
bash
docker exec -it web-nginx /bin/sh
ls /usr/share/nginx/html
cat /usr/share/nginx/html/index.html
exit
- 浏览器访问 http://127.0.0.1:8080,页面显示自定义内容,挂载生效。
| 优点 | 缺点 |
|---|---|
| 宿主机直接可见、可编辑文件,修改立刻生效 | 依赖宿主机固定目录,迁移麻烦 |
| 适合网页、源码、配置文件等需要频繁修改的场景 | 普通用户可能遇到目录权限不足(permission denied) |
5.3 数据卷Volume管理
Volume 是 Docker 官方推荐的持久化方案,由 Docker 统一管理存储,不依赖宿主机具体目录。
- Bind Mount:你手动指定宿主机哪个目录,Docker 直接把这个目录映射进容器,目录位置、权限全由你自己控制;
- Volume:你只需要给卷起个名字,Docker 自动在内部管理目录里创建存储区域,权限、位置全部由 Docker 自动适配,不用手动管。
常用命令
| 命令 | 作用 |
|---|---|
| docker volume create 卷名 | 创建一个数据卷 |
| docker volume ls | 查看所有数据卷列表 |
| docker volume inspect 卷名 | 查看卷的详细信息(存储路径等) |
| docker volume rm 卷名 | 删除指定数据卷 |
| docker volume prune | 批量清理所有未使用的数据卷 |
- 创建数据卷
bash
docker volume create html-data
执行后输出 html-data,代表名为 html-data 的数据卷创建成功。
这一步只是在 Docker 内部注册了一个卷,容器还没启动,卷里是空的。

- 查看数据卷列表
bash
docker volume ls
- DRIVER:卷驱动类型,默认是 local 本地存储;
- VOLUME NAME:卷名,能看到刚才创建的 html-data。
所有数据卷统一由 Docker 管理,不用记宿主机具体路径,通过卷名就能调用。

- 使用数据卷启动容器
bash
docker run -d --name web-nginx -p 8080:80 -v html-data:/usr/share/nginx/html nginx:stable-alpine
注意:前面实验如果没有删除旧的容器的话会报错,删掉就好了docker rm -f web-nginx

然后再次运行上面的命令

语法和 Bind Mount 几乎一样,区别在于冒号前面不是宿主机路径,而是数据卷的名字;Docker 会自动把 html-data 这个卷映射到容器的 /usr/share/nginx/html 目录。
- 查看数据卷详细存储位置
bash
docker volume inspect html-data

输出一大段 JSON 格式信息,其中 Mountpoint 字段就是卷在宿主机上的实际物理存储路径,一般在 /var/lib/docker/volumes/html-data/_data 下。
这个路径由 Docker 自动管理,普通用户一般不需要手动进去改文件,所有操作通过容器或 docker volume 命令完成即可;这也是 Volume 和 Bind Mount 最大的区别之一 ------ 你不用关心文件具体存在宿主机哪个文件夹。
验证数据持久化
前置条件
- 提前创建数据卷:docker volume create html-data
- 启动容器时挂载卷:-v html-data:/usr/share/nginx/html
- 进入容器,在网页目录创建文件
bash
docker exec -it web-nginx /bin/sh
echo "<h1>Volume持久化测试</h1>" > /usr/share/nginx/html/index.html
exit
/usr/share/nginx/html 是我们 -v 绑定的挂载目录,不是容器普通临时目录:
你在容器里创建、修改这个目录下的文件,不会存到容器临时读写层,而是直接写入独立数据卷 html-data。
数据卷是单独存储单元,生命周期和容器完全分离。

直接在宿主机查看数据卷里存了哪些网页文件,验证我们在容器内创建的index.html真实存在宿主机磁盘

- 删除容器,数据卷保留
bash
docker rm -f web-nginx

- 用同一个数据卷重新启动容器
bash
docker run -d --name web-nginx2 -p 8081:80 -v html-data:/usr/share/nginx/html nginx:stable-alpine

- 验证文件仍然存在
bash
docker exec -it web-nginx2 cat /usr/share/nginx/html/index.html

文件内容保留,证明数据卷独立于容器生命周期。
| 优点 | 缺点 |
|---|---|
| Docker统一管理,权限自动适配,不会报权限错误 | 宿主机不能直接编辑文件,需要进容器操作 |
| 不依赖宿主机目录结构,方便迁移、备份 | 不适合需要频繁在宿主机手动修改文件的场景 |
| 适合数据库、缓存等业务数据持久化 |
5.4 渗透场景挂载风险警示
不当的挂载配置会导致严重的安全问题,是渗透测试中容器逃逸的核心手段。
高危挂载场景
| 挂载方式 | 风险等级 | 危害说明 |
|---|---|---|
| -v /:/host | 极高 | 宿主机根目录全盘挂载进容器,容器内可读写宿主机所有文件,直接实现容器逃逸 |
| -v /etc/passwd:/etc/passwd | 高 | 可修改宿主机用户密码文件,新增root权限账号 |
| -v /root/.ssh:/root/.ssh | 高 | 读取宿主机SSH私钥,远程登录宿主机 |
| -v /var/run/docker.sock:/var/run/docker.sock | 极高 | 容器内可控制宿主机整个Docker服务,创建特权容器实现逃逸 |
渗透测试利用思路
- 发现目标容器挂载了宿主机根目录,直接读取 /host/etc/shadow 破解密码;
- 挂载了 docker.sock,在容器内执行 docker 命令创建新的特权容器,接管宿主机;
- 挂载了 SSH 目录,导出私钥进行横向移动。
防御建议:生产环境严格限制容器挂载权限,禁止挂载宿主机敏感目录和 docker.sock,使用最小权限原则。
6 Docker 信息排查与取证命令
前置环境说明
- 存在可操作容器(本章示例统一使用前面实验的
web-nginx/web-nginx2);

当前环境中有
web-nginx2容器正在运行,端口映射 8081→80,挂载了 html-data 数据卷,本章所有排查命令都以这个容器为例演示。
本章常用命令速查
| 命令 | 作用 |
|---|---|
| docker inspect 容器名/镜像名 | 查看容器/镜像/数据卷的完整底层JSON信息 |
| docker logs 容器名 | 查看容器运行日志、报错、访问记录 |
| docker logs -f 容器名 | 实时滚动查看容器日志 |
| docker top 容器名 | 查看容器内部正在运行的所有进程 |
| docker diff 容器名 | 对比容器文件与镜像差异,检测文件篡改 |
6.1 inspect 容器/镜像底层信息解析
docker inspect 是万能详情查看命令,支持查看容器、镜像、数据卷完整底层JSON信息,运维/渗透取证核心命令。
bash
# 查看容器全部信息
docker inspect 容器名/容器ID
# 查看镜像全部信息
docker inspect 镜像名:标签
# 查看数据卷信息(5.3用过)
docker inspect html-data
常用重点查看场景
- 查看容器挂载信息(验证-v挂载目录)
bash
docker inspect web-nginx2 | grep Mounts -A 10

能看到绑定挂载/数据卷映射路径、宿主机真实存储位置。
- 查看容器端口映射
bash
docker inspect web-nginx2 | grep Ports -A 8

- 查看容器IP、网关、网络模式
bash
docker inspect web-nginx2 | grep NetworkSettings -A 15

- 查看镜像创建时间、环境变量、启动命令
bash
docker inspect nginx:stable-alpine

取证用途:可导出完整JSON文件留存证据
docker inspect web-nginx > container-info.json
6.2 logs 容器运行日志查看
容器内程序输出的控制台日志,全部由Docker捕获保存,无需进容器查看日志文件。
常用命令
bash
# 查看全部日志
docker logs web-nginx2
# 实时滚动日志(持续刷新,类似tail -f)
docker logs -f web-nginx2
# 只看最新10行日志
docker logs --tail 10 web-nginx2
# 带时间戳输出日志
docker logs -t web-nginx2
以下只展示一张运行结果

实操场景
- Nginx访问报错、页面打不开,用logs查看404、500错误;
- 容器启动失败,无前台输出,通过日志定位崩溃原因;
- 渗透取证:留存网站访问、报错日志,作为流量证据。
6.3 top 查看容器内部进程
无需进入容器,直接查看容器里正在运行的所有进程,排查恶意程序、异常后台进程。
bash
docker top web-nginx2
输出内容:PID(宿主机PID)、容器内PID、用户、进程命令。

作用
- 快速判断容器运行的程序(nginx、mysql、恶意脚本等);
- 发现隐藏后台木马、挖矿进程;
- 对比正常进程列表,识别篡改新增程序。
补充:交互式查看动态进程
bash
docker exec -it web-nginx2 ps aux

- 查看容器内部独立进程 PID
docker top 显示的是宿主机系统 PID;
这条命令输出的是容器命名空间内 PID,容器内部进程 1 号是 nginx 主进程,容器重启后 PID 会重置,适合容器内部排查。 - 完整查看容器内所有后台程序
能清晰区分:
PID 1 root:nginx master 主进程(管理所有子工作进程)
PID30~37 nginx:nginx worker 工作进程(处理网页访问请求)
PID38 root:你刚执行的 ps aux 临时进程 - 安全取证 / 入侵排查
如果容器被上传木马、挖矿脚本、后门程序,执行 ps aux 能直接看到异常未知进程,对比正常 nginx 进程列表即可快速发现恶意程序。
和 docker top 的区别
- docker top:宿主机视角,显示宿主机全局 PID;不进入容器也能执行;
- docker exec -it xx ps aux:容器内部视角,容器独立 PID,信息更细,适合深度排查。
6.4 diff 检测容器文件篡改痕迹
核心取证命令:对比容器当前文件 与原始镜像文件层的差异,快速找出新增、修改、删除的文件,判断是否被入侵篡改。
bash
docker diff web-nginx2

输出三种标记含义
A= Added:新增文件/文件夹(比如你手动创建的index.html、上传木马)C= Changed:原有文件被修改(nginx配置、系统文件篡改)D= Deleted:原有文件被删除(删日志、删系统命令掩盖痕迹)
结合前面实验演示
你在web-nginx容器新增了index.html,执行docker diff web-nginx2会输出:
A /usr/share/nginx/html/index.html
代表该文件是容器运行后新增,不是镜像自带。
实战取证价值
容器被入侵后,黑客会上传后门、修改配置、删除日志,docker diff一键定位所有改动文件,是容器安全排查关键命令。
| 命令 | 核心用途 | 适用场景 |
|---|---|---|
| inspect | 底层配置、挂载、网络、端口全量信息 | 排查挂载异常、端口冲突、取证容器配置 |
| logs | 程序运行日志、报错、访问记录 | 服务故障排查、网站访问日志取证 |
| top | 容器内所有运行进程 | 排查恶意后台程序、异常进程 |
| diff | 文件增删改对比,识别篡改 | 入侵检测、容器文件篡改取证 |
7 Dockerfile 自定义渗透镜像
本章常用命令速查
| 命令 | 作用 |
|---|---|
| docker build -t 镜像名:标签 . | 根据当前目录 Dockerfile 构建自定义镜像 |
| docker build -f 文件路径 -t 镜像名 . | 指定 Dockerfile 文件路径构建镜像 |
| docker images | 查看本地所有镜像,确认构建结果 |
| docker run -it 自定义镜像名 | 启动自定义镜像并进入交互模式 |
| docker history 镜像名 | 查看镜像分层构建历史,验证分层原理 |
7.1 镜像分层构建原理
Docker 镜像采用分层存储 + 联合文件系统(UnionFS) 机制,每一条 Dockerfile 指令都会生成一个新的镜像层,所有层堆叠组合成最终可用的镜像。
核心特点
- 只读层:除最顶层容器读写层外,所有镜像层都是只读的,构建完成后不可修改;
- 分层复用:多个镜像可以共享相同的底层(如都基于 ubuntu 基础镜像),节省磁盘空间;
- 构建缓存:某一层未发生变化时,后续构建直接复用缓存,大幅提升构建速度;
- 增量更新:修改某一层指令,只重新构建该层及之后的所有层,前面的层保持不变。
查看镜像分层历史
bash
docker history nginx:stable-alpine
输出按层从上到下排列,每一行对应一层,显示该层的创建指令、大小、创建时间。

渗透场景理解:黑客可以通过 docker history 逆向分析自定义镜像的构建过程,逐层还原镜像里安装了哪些工具、修改了哪些配置,判断镜像是否被植入后门。
7.2 高频指令:FROM/RUN/COPY/CMD 详解
Dockerfile 是纯文本文件,每行一条指令,按顺序从上到下执行,构建出自定义镜像。
四个最核心高频指令对比
| 指令 | 执行时机 | 作用 | 常见用法 |
|---|---|---|---|
| FROM | 构建时 | 指定基础镜像,所有镜像必须以 FROM 开头 | FROM ubuntu:22.04 |
| RUN | 构建时 | 在镜像内执行 Shell 命令(安装软件、创建目录等) | RUN apt update && apt install -y curl |
| COPY | 构建时 | 将宿主机文件复制到镜像内部 | COPY ./src /app |
| CMD | 运行时 | 容器启动后默认执行的命令,可被 docker run 覆盖 | CMD "/bin/bash" |
FROM 指令
必须是 Dockerfile 的第一条指令,指定基于哪个基础镜像构建。
bash
FROM kalilinux/kali-rolling
基础镜像选择技巧:做渗透测试镜像优先选 Kali 官方基础镜像,预装大量安全工具;追求体积小选 alpine,只有几 MB。
RUN 指令
构建镜像时执行命令,每一条 RUN 都会生成一个新的镜像层。
bash
RUN apt update && apt install -y nmap sqlmap
优化技巧:多条命令用
&&连接写在同一条 RUN 里,减少镜像层数,减小最终镜像体积;例如:RUN apt update && apt install -y nmap && apt clean
COPY 指令
将宿主机当前目录的文件复制到镜像内部指定路径。
bash
COPY ./wordlist.txt /usr/share/wordlists/
冒号前是宿主机相对路径(相对于构建上下文目录),冒号后是镜像内绝对路径。
渗透场景:可以把自己的字典、脚本、EXP 直接打包进镜像,启动容器就能直接用,不用每次重新下载。
CMD 指令
容器启动后默认执行的命令,一个 Dockerfile 只有最后一条 CMD 生效。
bash
CMD ["/bin/bash"]
CMD 和 RUN 的区别:
RUN 是构建镜像时 执行,结果固化在镜像里;
CMD 是启动容器时执行,每次 docker run 都会运行,可被命令行参数覆盖。
7.3 build 构建自定义镜像
编写好 Dockerfile 后,使用 docker build 命令执行构建,生成自定义镜像。
基础语法
bash
docker build -t 自定义镜像名:标签 .
参数说明
| 参数 | 含义 |
|---|---|
| -t | 给构建好的镜像打标签(名字:版本号) |
| . | 构建上下文路径,代表当前目录,Docker 会从这个目录找 Dockerfile 和要复制的文件 |
| -f | 指定 Dockerfile 文件路径,文件名不叫 Dockerfile 时用 |
完整流程
新建文件夹,进入目录
bash
mkdir kali-build
cd kali-build
创建 Dockerfile 文件,把 FROM/RUN/CMD 全部写进文件
bash
cat > Dockerfile <<EOF
FROM kalilinux/kali-rolling
ENV DEBIAN_FRONTEND=noninteractive
RUN apt update && apt install -y nmap sqlmap
CMD ["/bin/bash"]
EOF
执行构建命令读取 Dockerfile 并生成镜像
bash
docker build -t kali-pentest:v1 .
构建过程会逐层输出,每一步对应一条指令,显示 Step 1/4、Step 2/4、Step 3/4、Step 4/4,第一行 + Building 114.2s (6/6) FINISHED
FINISHED 代表整套构建流程全部执行完毕,无报错终止


- 查看构建好的镜像
bash
docker images | grep kali-pentest
能看到 kali-pentest 镜像,标签为 v1

- 启动容器验证工具是否安装成功
bash
docker run -it --name pentest-test kali-pentest:v1
此处这样就是进入容器了

进入容器后执行
bash
nmap --version
sqlmap --version
两个工具都能正常输出版本号,证明镜像构建成功。

退出容器
bash
exit

缓存机制说明:第二次构建时,如果前面的指令没修改,会直接显示 Using cache,跳过重复构建,速度非常快;
只有修改了对应层的指令(比如在 RUN 里加新工具),才会从那一层开始重新构建。
| 知识点 | 核心要点 |
|---|---|
| 分层原理 | 每条指令生成一层,只读、复用、缓存、增量更新 |
| FROM | 指定基础镜像,必须是第一条指令 |
| RUN | 构建时执行命令,安装软件、配置环境 |
| COPY | 宿主机文件复制进镜像,打包字典/脚本常用 |
| CMD | 容器启动默认命令,运行时执行,可被覆盖 |
| build | docker build -t 镜像名 . ,根据 Dockerfile 构建镜像 |
| 镜像瘦身 | apt clean + 删缓存,一条 RUN 装多工具,减小体积 |
| 渗透实战 | 基于 Kali 基础镜像预装工具+打包自定义资源,打造专属便携渗透环境 |
8 Docker Compose 靶场编排核心
前置环境搭建
安装 Compose V2 插件
bash
apt update
apt install docker-compose-plugin -y

校验安装结果
bash
docker compose version
出现版本号即安装成功。

测试验证 Compose 可用
- 新建测试目录
bash
mkdir compose-test
cd compose-test
- 编写最简编排文件
bash
cat > docker-compose.yml <<EOF
version: "3.8"
services:
web:
image: nginx:stable-alpine
ports:
- "8085:80"
EOF
- 后台启动服务
bash
docker compose up -d

- 查看运行状态
bash
docker compose ps

- 浏览器访问验证
访问 http://127.0.0.1:8085,出现 Nginx 页面代表编排环境搭建完成。

销毁测试环境
场景 1:还要继续用这个靶场,下次接着测(推荐 stop)
docker compose stop
- 仅停止容器,镜像、容器、数据全部保留
- 下次直接 docker compose start 启动,数据不变,不用重新拉取镜像
场景 2:测完这个漏洞,要换另一个漏洞(推荐 down,不加 - v)
docker compose down
- 删除容器 + 专属网络,释放端口
- 数据库数据卷保留,下次重开数据还在
- 镜像全程不动,无需重下载
场景 3:漏洞复现失败,需要全新干净环境(down -v)
docker compose down -v
- 容器、网络、数据库卷全部清空,完全重置环境
- 镜像依旧本地存在,再次 up 秒启动,不用重新下载
安装完成后,才可进行后续 yaml 语法、靶场编排实操。

本章常用命令速查表
| 命令 | 核心作用 |
|---|---|
| docker compose up -d | 后台启动 yml 内全部容器服务 |
| docker compose down | 停止并删除容器、网络(保留镜像/数据卷) |
| docker compose down -v | 彻底销毁,连带数据卷一并删除 |
| docker compose logs -f 服务名 | 实时查看指定靶场服务运行日志 |
| docker compose ps | 查看当前编排内所有容器运行状态 |
| docker compose restart 服务名 | 单独重启某一个靶场服务 |
| docker compose build | 重新构建 yml 内自定义镜像 |
8.1 Compose 适用场景(多服务靶场)
Docker Compose 用于一次性编排、管理一组关联容器,核心解决单条 docker run 无法批量管理多组件靶场的痛点。
核心适用场景(渗透靶场专属)
-
多组件漏洞靶场
绝大多数开源漏洞平台由多服务组成:Web 前端 + MySQL 数据库 + Redis 缓存 + 漏洞应用,单独启动每个容器需要手动配置端口、网络、依赖,Compose 一键启停。
示例:DVWA、WebGoat、Sqli-Labs、Fastjson 靶场、Vulhub 系列。
-
隔离完整渗透环境
一套 yml 文件定义整套靶场,销毁仅需
down命令,不会污染本机环境,复现漏洞无残留。 -
团队统一靶场环境
仅需分发
docker-compose.yml配置文件,所有人一键启动完全一致的漏洞环境,避免环境差异导致漏洞复现失败。 -
批量启停、日志统一查看
无需逐个执行
docker start/stop,一条命令管理全部靶场服务,统一查看所有服务运行日志定位漏洞报错。
不适用场景
单容器独立工具(如之前单 Kali 渗透镜像、单 Nginx 容器),直接使用 docker run 更简洁,无需 Compose。
8.2 yaml 配置文件核心字段解析
编排配置固定命名为 docker-compose.yml,采用 YAML 语法,缩进严格(仅用空格,禁止 Tab)。
基础完整模板
bash
cat > docker-compose.yml <<EOF
services:
mysql:
image: mysql:5.7
restart: always
environment:
MYSQL_ROOT_PASSWORD: root123
MYSQL_DATABASE: target_db
volumes:
- mysql-data:/var/lib/mysql
web:
image: php:apache
ports:
- "8080:80"
environment:
DB_HOST: mysql
DB_USER: root
DB_PASSWORD: root123
DB_NAME: target_db
depends_on:
- mysql
volumes:
mysql-data:
EOF
| 字段 | 层级 | 作用(靶场场景) |
|---|---|---|
| version | 最顶层 | 声明 compose 语法兼容版本,固定 3.8 通用 |
| services | 顶层 | 所有靶场容器统一入口,子项为单个服务名 |
| image | 服务下 | 指定该服务使用的镜像名:标签 |
| build | 服务下 | 本地 Dockerfile 构建自定义镜像(替代 image) |
| ports | 服务下 | 端口映射,对外开放靶场访问端口 |
| environment | 服务下 | 注入数据库账号、密钥、配置参数 |
| volumes | 服务下 | 挂载数据卷/本地目录,持久化靶场数据、字典 |
| depends_on | 服务下 | 定义服务启动顺序,先启动数据库再启动 Web |
| restart | 服务下 | 容器异常自动重启,靶场崩溃自动恢复 |
| volumes | 顶层 | 全局声明持久化存储卷 |
8.3 up/down/logs 核心编排命令
8.3.1. 启动靶场:docker compose up
前台启动,打印实时日志(调试用,关闭终端容器销毁)
bash
docker compose up
后台静默启动(实战靶场必用)
bash
docker compose up -d
执行逻辑:自动创建专属网桥网络、拉取镜像、按 depends_on 顺序启动全部容器,端口、环境变量自动绑定。
8.3.2. 销毁靶场:docker compose down
停止容器,删除容器、专属网络;保留镜像、数据卷
bash
docker compose down
彻底销毁(连带数据卷一并删除,靶场数据清空)
bash
docker compose down -v
渗透测试推荐:漏洞复现完成后执行
down -v,彻底清空靶场残留数据,避免下次复现环境被污染。
8.3.3. 查看日志:docker compose logs
查看全部服务历史日志
bash
docker compose logs
实时滚动查看全部服务日志
bash
docker compose logs -f
只看指定服务日志(如只看数据库报错)
bash
docker compose logs -f mysql
只看最新 20 行日志
bash
docker compose logs --tail 20
靶场报错排查:页面打不开、数据库连不上,优先用 logs 查看对应服务报错信息。
8.3.4. 其他常用编排命令
bash
查看当前编排所有容器状态
docker compose ps
单独重启某一个服务(如修改配置后只重启 Web)
docker compose restart web
重新构建 yml 内自定义镜像(修改 Dockerfile 后用)
docker compose build
进入指定服务容器交互终端
docker compose exec web /bin/bash
8.4 一键部署开源漏洞靶场实操(Vulhub)
Vulhub 是面向渗透测试人员的开源漏洞靶场集合,全部基于 Docker Compose 编排,包含几百个常见漏洞环境,一键启动、一键销毁,是安全从业者必备工具。
步骤 1:安装 git 工具
bash
apt update && apt install git -y
步骤 2:克隆 Vulhub 仓库
bash
git clone https://github.com/vulhub/vulhub.git
cd vulhub

仓库包含大量漏洞环境,按漏洞类型分目录存放,每个目录下都有独立的
docker-compose.yml。
步骤 3:选择漏洞环境并进入目录
以 ThinkPHP 5 远程代码执行漏洞为例(经典 Web 漏洞):
bash
cd thinkphp/5-rce
步骤 4:查看编排配置文件
bash
cat docker-compose.yml

可以看到配置文件中包含 version、services、image、ports 等字段,和 8.2 学过的核心字段完全对应,每个漏洞环境都是一个独立的多服务编排。
步骤 5:一键启动漏洞环境
bash
docker compose up -d
首次启动会自动拉取漏洞镜像,等待拉取完成。

步骤 6:查看服务运行状态
bash
docker compose ps
服务 STATE 显示 Up,代表漏洞环境启动成功。

步骤 7:访问漏洞页面验证
浏览器打开 http://127.0.0.1:8080
出现 ThinkPHP 默认页面代表靶场启动成功,可以开始漏洞复现练习。

步骤 8:销毁漏洞环境
bash
docker compose down -v

使用技巧:
- 每个漏洞目录独立,切换漏洞只需进入新目录执行
up -d;- 复现完成后务必执行
down -v彻底清理,避免端口冲突和资源占用;- Vulhub 覆盖 Web、PWN、中间件、数据库等各类漏洞,后续渗透学习可直接按需启动对应环境。
本章核心总结
| 知识点 | 核心要点 |
|---|---|
| Compose 作用 | 一键编排管理多容器服务,解决多组件靶场部署痛点 |
| yaml 语法 | 缩进严格、空格替代 Tab,version/services/volumes 三大顶层 |
| 核心字段 | image/ports/environment/volumes/depends_on/restart |
| up 命令 | 启动全部服务,-d 后台运行 |
| down 命令 | 停止销毁,-v 连带删除数据卷彻底清空 |
| logs 命令 | 统一查看服务日志,-f 实时滚动,排查靶场报错 |
| 靶场实战 | Vulhub 仓库 → 进入漏洞目录 → docker compose up -d,三步部署任意漏洞环境 |
9 Docker 安全风险与渗透攻防要点
9.1 docker组权限逃逸原理与防御
- 用户加入 docker 用户组后,无需 sudo 即可执行 docker run、docker exec 等全部容器操作;
- Docker Daemon 以 root 权限运行,通过挂载宿主机目录可直接读写宿主机任意文件;
- 逃逸核心 payload:
bash
docker run -v /:/mnt --rm -it alpine chroot /mnt bash
进入容器后等价拿到宿主机最高权限,可读取密码哈希、写入 ssh 公钥、篡改 sudoers。
防御方案
- 非运维用户禁止加入 docker 组,执行 docker 必须 sudo;
- 开启 Docker 授权认证,限制普通用户访问 daemon 套接字 /var/run/docker.sock;
- 生产环境禁用无限制目录挂载,使用只读挂载 -v xxx:/data:ro;
- 审计容器启动命令,监控 -v /:/mnt 类高危挂载行为。
9.2 挂载宿主机目录高危漏洞
风险场景
- 高危挂载 1:挂载 docker.sock,容器内可创建、篡改容器,完全接管宿主机 Docker 服务;
bash
-v /var/run/docker.sock:/var/run/docker.sock
- 高危挂载 2:挂载宿主机根目录、/etc、/root、ssh 密钥目录;
- 高危挂载 3:挂载 sudoers、crontab 定时任务目录,提权持久化;
- 业务漏洞延伸:Web 容器挂载网站源码目录,文件上传 / 路径穿越可写入宿主机后门。
防御
- 禁止挂载 docker.sock,必须使用则配置容器细粒度权限隔离;
- 业务目录统一只读挂载 :ro,拒绝读写系统敏感路径;
- 使用容器运行时限制:AppArmor / Seccomp,阻断危险挂载参数;
- CI/CD 镜像构建阶段校验 compose 配置,拦截高危挂载字段。
9.3 容器内信息搜集与环境探测
- 基础环境探测
bash
# 查看容器内部用户、权限
id; cat /etc/passwd
# 查看挂载(重点寻找宿主机敏感目录挂载)
mount
# 查看环境变量(数据库密码、密钥、宿主机IP常泄露)
env
# 查看网络,探测宿主机、内网其他容器IP
ip a; netstat -antp
- Docker 专属特征探测
- 判断是否在容器:存在 /.dockerenv 文件;
- 读取容器元数据:/proc/1/cgroup,识别容器 ID、镜像名;
- 读取宿主机文件(若存在挂载):/mnt/etc/shadow、ssh 私钥;
- 查看容器启动命令,寻找明文密钥、代理地址。
- 内网横向探测
容器共享宿主机网卡或 docker 网桥,可扫描同网段容器、宿主机端口,攻击数据库、Redis、内网 Web 服务。
9.4 容器逃逸基础前置认知
逃逸核心前置条件(至少满足其一)
- 危险挂载:挂载宿主机根目录、docker.sock、定时任务目录;
- 内核漏洞:宿主机 Linux 内核存在 Dirty Cow、CVE-2022-0811 等容器逃逸内核漏洞;
- 容器权限过高:启动参数添加 --privileged 特权模式,拥有设备读写权限;
- 配置缺陷:未限制 capabilities,保留 CAP_SYS_ADMIN 等高危权限;
- 镜像漏洞:容器内存在可提权 SUID 程序、可控挂载点、恶意插件。
前置探测清单(渗透时优先验证)
- 是否特权容器:capsh --print 查看权限集;
- 是否挂载宿主机敏感路径;
- 宿主机内核版本,匹配对应逃逸 CVE;
- 是否可读写 /dev 下设备文件;
- 是否存在可控 mount 操作、用户自定义挂载。
基础防御前置规范
- 生产容器禁止 --privileged;
- 清理多余 Linux Capability,仅保留业务必需权限;
- 定期更新宿主机内核,修复容器逃逸类内核漏洞;
- 禁用容器内动态挂载设备,限制 mount 系统调用。
总结
Docker 是基于 Linux Namespace 和 Cgroups 的轻量容器技术,共享宿主机内核、启动秒级、开销极低,在渗透场景中既是快速搭建 Vulhub 等漏洞靶场、容器化运行 Kali/MSF/SQLMap 等工具的基础设施,也是红蓝对抗中容器逃逸、挂载漏洞、docker 组权限提升等攻防手法的重要战场,核心围绕镜像、容器、仓库三要素展开,配合数据卷持久化和 Docker Compose 多服务编排,就能完成从环境部署到漏洞复现的全流程,而安全防御的关键在于遵循权限最小、挂载最小、能力最小三原则,禁用特权模式、严控敏感目录挂载、限制普通用户操作 Docker。