前四个模块你掌握了Python、Bash、PHP、JavaScript四种编程语言在安全领域的应用——这些都是"在宿主机上直接运行代码"的方式。但真实的渗透测试和漏洞复现中,你经常需要一个干净、可复现、用完即毁的隔离环境。Docker正是解决这个问题的标准工具:它把应用程序及其所有依赖打包进一个标准化集装箱,在任何机器上都能以完全相同的方式运行。本篇将从安全从业者视角理解Docker的核心概念和操作。
把Docker想象成一个标准化实验台系统:镜像(Image)是实验台搭建图纸——定义了需要哪些器材、试剂、工具;容器(Container)是按图纸搭好的实际实验台——可以在上面运行实验;卷(Volume)是实验台旁的储物柜——实验台拆除后储物柜里的数据还在;网络(Network)是实验台之间的通讯管道——让多个实验台能互相传递数据。
镜像是Docker的构建块,一个镜像是一个分层(layered)的只读文件系统。每个Dockerfile指令创建一个新层,层可以被多个镜像共享复用。例如python:3.12-slim镜像包含Debian基础层 + Python运行时层,你在其上添加的代码构成第三层。
| 概念 | 类比 | 安全意义 |
|---|---|---|
| 镜像 (Image) | 实验台搭建图纸 | 镜像中的漏洞会被所有容器继承 |
| 容器 (Container) | 搭建好的实验台 | 运行时隔离边界,逃逸即危及宿主机 |
| 卷 (Volume) | 储物柜 | 持久化数据,容器删除后仍存在 |
| 网络 (Network) | 通讯管道 | 控制容器间可达性,最小化暴露面 |
理解容器和虚拟机的区别,对安全从业者至关重要——隔离强度直接决定了攻击者逃逸后的影响范围。
| 特性 | 虚拟机 (VM) | 容器 (Container) |
|---|---|---|
| 隔离层级 | 硬件级(Hypervisor) | 操作系统级(Namespace + Cgroup) |
| 启动速度 | 分钟级 | 秒级(甚至毫秒级) |
| 资源开销 | 每台GB级内存 | 每台MB级内存 |
| 隔离强度 | 强(独立内核) | 弱(共享宿主机内核) |
关键安全差异:虚拟机有独立内核,从虚拟机逃逸到宿主机需要攻破Hypervisor(极难);容器共享宿主机内核,从容器逃逸只需要利用内核漏洞或Docker配置失误(相对容易)。这就是为什么容器安全在渗透测试中如此重要。
Docker采用客户端-守护进程架构:docker命令行客户端通过Unix Socket(/var/run/docker.sock)与Docker Daemon通信,Daemon负责构建、运行、分发容器。
docker.sock 就等于拥有宿主机 root 权限。因为你可以用 docker run -v /:/host alpine 挂载宿主机根文件系统,然后任意读写。渗透测试中如果发现目标挂载了 docker.sock,这直接就是宿主机沦陷——在报告里标记为 Critical。理解了概念,现在动手在Kali上安装Docker并掌握核心命令。Kali官方文档推荐使用Docker CE(Community Edition)仓库安装,而非Debian自带的docker.io包——后者版本更新滞后且不包含Compose插件。
Kali基于Debian Trixie 13,安装时使用Docker官方Debian仓库。截至2026年8月,Docker Engine最新稳定版为29.7.2,Compose插件最新版为v5.5.0。
安装完成后验证版本号:
sudo usermod -aG docker $USER,然后注销重新登录(或执行 newgrp docker 立即生效)。注意:加入docker组等同于授予root级权限,生产环境慎用。
Docker命令遵循 docker 对象 子命令 参数 的结构。安全测试中最常用的命令分三类:镜像管理、容器生命周期、调试排障。
docker run 是最核心的命令,拆解其参数:-d 后台运行,--name 指定容器名,-p 8080:80 将宿主机8080端口映射到容器80端口。执行后Docker会返回一个容器ID。
docker inspect 在渗透测试中特别有用——它输出容器的完整配置JSON,包括挂载点、网络配置、环境变量(可能包含密码)、用户身份等敏感信息。
docker inspect 配合 --format 可以精确提取字段。例如 docker inspect --format '{{.Config.Env}}' web 直接输出容器环境变量。在CTF中遇到Docker环境时,这是提取Flag的标准姿势之一。掌握了基本命令后,我们来学习如何用Dockerfile自定义镜像。Dockerfile是一个纯文本文件,包含一系列指令,Docker按顺序执行这些指令来构建镜像。安全从业者需要会读会写Dockerfile——既要能构建自己的安全工具镜像,也要能审计他人镜像中的安全隐患。
| 指令 | 作用 | 安全注意 |
|---|---|---|
FROM |
指定基础镜像 | 禁止用latest标签,必须锁定版本 |
RUN |
执行shell命令(构建时) | 合并多条命令减少层数 |
COPY |
复制文件到镜像中 | 禁止COPY敏感文件(密钥、.env) |
USER |
切换运行用户 | 必须切换为非root用户 |
CMD |
容器默认启动命令 | 可被docker run参数覆盖 |
下面编写一个Dockerfile,把Python端口扫描器打包成可分发的镜像。这个Dockerfile演示了版本锁定、非root用户、最小化镜像三项安全实践。
注意第4行先COPY requirements.txt再RUN pip install,然后才COPY scanner.py。这个顺序不是随意的——Docker的层缓存机制决定了:如果scanner.py变了但requirements.txt没变,pip install层会命中缓存跳过执行,构建速度大幅提升。
构建镜像并运行:
latest标签会随时间指向不同版本。今天构建的镜像和下个月构建的可能基于不同的Ubuntu版本,导致依赖断裂或引入新漏洞。FROM ubuntu:24.04 或更精确的 FROM ubuntu@sha256:a3b4c5...(使用digest锁定到确切版本)
当服务由多个容器组成(比如Web应用 + 数据库 + 缓存),逐个docker run不仅繁琐还容易出错。Docker Compose用一个YAML文件定义所有服务、网络、卷,一条命令完成全部编排。
注意:Docker Compose v1(命令带连字符 docker-compose)已于2024年5月停止维护。当前使用的是Compose v2/v5(命令 docker compose,无连字符),作为Docker CLI插件随Engine一起安装。
下面是一个Web应用+数据库的编排文件,展示了services、volumes、networks三大顶级元素的用法。
关键点解读:depends_on只保证启动顺序,不等待db就绪——应用需要自己处理重试逻辑。${DB_PASSWORD}从.env文件读取,避免在YAML中硬编码密码。服务名db自动成为DNS名称——web容器内可以用db:5432连接数据库。
docker compose up -d — 后台启动所有服务
docker compose ps — 查看服务状态
docker compose logs -f — 持续查看所有服务日志
docker compose down — 停止并删除容器、网络(加-v同时删除卷)
docker compose down -v 中的 -v 参数会删除命名卷中的所有数据。在靶场环境中这是好事——每次重置到干净状态。但如果在生产环境误加 -v,数据库会被清空。养成习惯:down 前先看一眼有没有 volume。为什么安全从业者必须理解容器?因为现代企业基础设施高度容器化,渗透测试中遇到Docker环境是常态。容器的隔离边界比虚拟机薄得多——共享内核意味着一个内核漏洞就能从容器逃逸到宿主机。本节聚焦容器安全的6项关键防御措施。
--privileged 容器拥有所有Linux capabilities,可以访问宿主机所有设备(包括磁盘设备文件),直接挂载宿主机文件系统即可逃逸
/var/run/docker.sock 挂载进容器,容器内就能调用Docker API创建新容器并挂载宿主机根目录
CAP_SYS_ADMIN 或 CAP_SYS_PTRACE 等高危权限,攻击者可以利用它们突破隔离
以下加固措施在docker-compose.yml中通过安全选项实现。对比"默认配置"和"加固配置":
逐条解释加固效果:
no-new-privileges阻止通过setuid程序提权
NET_BIND_SERVICE
/tmp用内存文件系统,容器停止即消失
端口映射中的 127.0.0.1: 前缀也很关键——默认的 "5000:5000" 会绑定 0.0.0.0(所有网卡),导致服务暴露到外网。加上 127.0.0.1: 前缀后只允许本机访问,这在部署靶场时尤为重要——你不想让DVWA暴露到公网。
cat /proc/1/cgroup | grep docker 确认是否在容器内;第二步检查 capsh --print 查看当前capabilities;第三步查看 mount 输出中是否挂载了 docker.sock 或宿主机目录。这三步在30秒内完成,能快速判断容器逃逸的可能性。理论学完,现在动手部署DVWA(Damn Vulnerable Web Application)。DVWA是最经典的Web安全练习靶场,内置SQL注入、XSS、文件上传、命令注入等十余种漏洞。用Docker部署只需三条命令,比传统LAMP环境搭建快十倍。
注意端口映射:DVWA在容器内监听80端口,但docker-compose.yml将其映射到宿主机4280端口(避免与本地Web服务冲突)。浏览器访问 http://localhost:4280 即可打开DVWA登录页。默认账号 admin / password。
首次访问DVWA需要初始化数据库。在DVWA首页点击"Create / Reset Database"按钮,然后重新登录。登录后进入"DVWA Security"页面,可以切换三个安全等级:
| 安全等级 | 防护机制 | 练习目标 |
|---|---|---|
| Low | 无任何过滤 | 理解漏洞原理,手工构造Payload |
| Medium | 基本过滤(如str_replace) | 学习绕过简单防护(大小写、编码) |
| High | 强过滤(如htmlspecialchars+mysql_real_escape_string) | 挑战高级绕过技巧 |
练习完毕后清理环境,释放资源:
用同样的方式可以部署Vulhub——一个面向安全研究者的漏洞环境集合,涵盖Apache、Nginx、Tomcat、Struts2等数百个已知CVE的复现环境。Vulhub的使用方式与DVWA完全一致:克隆仓库、进入对应CVE目录、docker compose up -d。这套"克隆→compose→练习→down"的工作流将贯穿你后续所有的Web渗透学习。
docker run -d --name test -p 8080:80 nginx:alpine,然后用浏览器访问 http://localhost:8080。确认看到Nginx欢迎页后,用 docker exec 进入容器,修改 /usr/share/nginx/html/index.html 的内容,刷新页面验证修改生效。alpine:3.20,安装nmap和curl,创建非root用户 scanner,CMD默认执行 nmap --version。构建后运行 docker run --rm myscanner:1.0 -sV 192.168.1.1 验证nmap可用。提示:alpine用 apk add 安装软件包。docker exec -it dvwa-db mysql 进入数据库容器,查看dvwa库的users表结构;③将安全等级调到Medium,分析PHP源码( docker exec dvwa-web cat /var/www/html/vulnerabilities/sqli/source/medium.php ),找出过滤了什么,然后构造绕过Payload。提示:medium级别用了mysql_real_escape_string和str_replace,关注前者防什么后者防什么。