📚 网络安全Kali学习系列 · 模块0-5
18 Docker与容器安全(当前篇)
模块0-4 编程基础已完结:14 Python socket扫描器 / 15 Bash安全自动化 / 16 PHP与Web漏洞 / 17 JavaScript与XSS

Docker与容器安全:从镜像到靶场部署

难度:基础 | 模块0-5 Docker/容器基础 | Docker Engine 29.7.x + Compose v5.x
读完本篇你将能:理解Docker镜像/容器/卷/网络四大核心概念,独立编写Dockerfile构建安全镜像,用docker-compose一键编排多容器服务,掌握容器安全加固的6项关键措施,并在Kali上用Docker部署DVWA漏洞靶场——为后续Web渗透学习搭建实战环境。
📑 本文目录
01Docker核心概念:镜像、容器、卷、网络
02Docker安装与常用命令
03Dockerfile编写与镜像构建
04docker-compose多容器编排
05容器安全:攻击面与防御策略
06实战:用Docker部署DVWA漏洞靶场

前四个模块你掌握了Python、Bash、PHP、JavaScript四种编程语言在安全领域的应用——这些都是"在宿主机上直接运行代码"的方式。但真实的渗透测试和漏洞复现中,你经常需要一个干净、可复现、用完即毁的隔离环境。Docker正是解决这个问题的标准工具:它把应用程序及其所有依赖打包进一个标准化集装箱,在任何机器上都能以完全相同的方式运行。本篇将从安全从业者视角理解Docker的核心概念和操作。

01 Docker核心概念:镜像、容器、卷、网络

把Docker想象成一个标准化实验台系统:镜像(Image)是实验台搭建图纸——定义了需要哪些器材、试剂、工具;容器(Container)是按图纸搭好的实际实验台——可以在上面运行实验;卷(Volume)是实验台旁的储物柜——实验台拆除后储物柜里的数据还在;网络(Network)是实验台之间的通讯管道——让多个实验台能互相传递数据。

1.1 镜像(Image):只读模板

镜像是Docker的构建块,一个镜像是一个分层(layered)的只读文件系统。每个Dockerfile指令创建一个新层,层可以被多个镜像共享复用。例如python:3.12-slim镜像包含Debian基础层 + Python运行时层,你在其上添加的代码构成第三层。

概念 类比 安全意义
镜像 (Image) 实验台搭建图纸 镜像中的漏洞会被所有容器继承
容器 (Container) 搭建好的实验台 运行时隔离边界,逃逸即危及宿主机
卷 (Volume) 储物柜 持久化数据,容器删除后仍存在
网络 (Network) 通讯管道 控制容器间可达性,最小化暴露面

1.2 容器 vs 虚拟机

理解容器和虚拟机的区别,对安全从业者至关重要——隔离强度直接决定了攻击者逃逸后的影响范围。

特性 虚拟机 (VM) 容器 (Container)
隔离层级 硬件级(Hypervisor) 操作系统级(Namespace + Cgroup)
启动速度 分钟级 秒级(甚至毫秒级)
资源开销 每台GB级内存 每台MB级内存
隔离强度 强(独立内核) 弱(共享宿主机内核)

关键安全差异:虚拟机有独立内核,从虚拟机逃逸到宿主机需要攻破Hypervisor(极难);容器共享宿主机内核,从容器逃逸只需要利用内核漏洞或Docker配置失误(相对容易)。这就是为什么容器安全在渗透测试中如此重要。

1.3 Docker架构

Docker采用客户端-守护进程架构:docker命令行客户端通过Unix Socket(/var/run/docker.sock)与Docker Daemon通信,Daemon负责构建、运行、分发容器。

docker CLI
→
docker.sock
→
dockerd (Daemon)
→
Container
💡 小贴士
能访问 docker.sock 就等于拥有宿主机 root 权限。因为你可以用 docker run -v /:/host alpine 挂载宿主机根文件系统,然后任意读写。渗透测试中如果发现目标挂载了 docker.sock,这直接就是宿主机沦陷——在报告里标记为 Critical。

02 Docker安装与常用命令

理解了概念,现在动手在Kali上安装Docker并掌握核心命令。Kali官方文档推荐使用Docker CE(Community Edition)仓库安装,而非Debian自带的docker.io包——后者版本更新滞后且不包含Compose插件。

2.1 在Kali上安装Docker Engine

Kali基于Debian Trixie 13,安装时使用Docker官方Debian仓库。截至2026年8月,Docker Engine最新稳定版为29.7.2,Compose插件最新版为v5.5.0。

Bash · Kali Linux 终端
1
2
3
4
5
6
7
8
9
10
11
12
13
# 1. 添加Docker官方GPG密钥
sudo curl -fsSL https://download.docker.com/linux/debian/gpg \
  -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc
# 2. 添加Docker仓库(Kali对应Debian Trixie)
echo "deb [arch=$(dpkg --print-architecture) \
signed-by=/etc/apt/keyrings/docker.asc] \
https://download.docker.com/linux/debian trixie stable" \
  | sudo tee /etc/apt/sources.list.d/docker.list
# 3. 安装Docker Engine + Compose插件
sudo apt update && sudo apt install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin

安装完成后验证版本号:

Bash · 验证安装
docker --version
Docker version 29.7.2, build 1f23a3b
docker compose version
Docker Compose version v5.5.0
docker run hello-world
Hello from Docker!
⚠️ 常见错误
docker: permission denied while trying to connect to the Docker daemon socket
原因:当前用户不在 docker 组中。Docker守护进程默认只允许root和docker组成员访问。
✓ 修复:sudo usermod -aG docker $USER,然后注销重新登录(或执行 newgrp docker 立即生效)。注意:加入docker组等同于授予root级权限,生产环境慎用。

2.2 核心命令速查

Docker命令遵循 docker 对象 子命令 参数 的结构。安全测试中最常用的命令分三类:镜像管理、容器生命周期、调试排障。

Bash · Docker核心命令
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# --- 镜像管理 ---
docker pull nginx:alpine        # 拉取镜像
docker images                 # 列出本地镜像
docker rmi nginx:alpine        # 删除镜像
# --- 容器生命周期 ---
docker run -d --name web -p 8080:80 nginx:alpine
docker ps                    # 查看运行中容器
docker ps -a                # 含已停止容器
docker stop web              # 停止容器
docker rm web               # 删除容器
# --- 调试排障 ---
docker exec -it web sh        # 进入容器shell
docker logs web              # 查看容器日志
docker inspect web           # 查看容器详情(JSON)

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的标准姿势之一。

03 Dockerfile编写与镜像构建

掌握了基本命令后,我们来学习如何用Dockerfile自定义镜像。Dockerfile是一个纯文本文件,包含一系列指令,Docker按顺序执行这些指令来构建镜像。安全从业者需要会读会写Dockerfile——既要能构建自己的安全工具镜像,也要能审计他人镜像中的安全隐患。

3.1 Dockerfile核心指令

指令 作用 安全注意
FROM 指定基础镜像 禁止用latest标签,必须锁定版本
RUN 执行shell命令(构建时) 合并多条命令减少层数
COPY 复制文件到镜像中 禁止COPY敏感文件(密钥、.env)
USER 切换运行用户 必须切换为非root用户
CMD 容器默认启动命令 可被docker run参数覆盖

3.2 实战:构建安全扫描工具镜像

下面编写一个Dockerfile,把Python端口扫描器打包成可分发的镜像。这个Dockerfile演示了版本锁定、非root用户、最小化镜像三项安全实践。

Dockerfile
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 锁定基础镜像版本(禁止用latest)
FROM python:3.12-slim
# 设置工作目录
WORKDIR /app
# 先复制依赖文件(利用层缓存)
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
# 复制源代码
COPY scanner.py .
# 创建非root用户并切换
RUN useradd -m scanner
USER scanner
# 默认启动命令
CMD ["python", "scanner.py"]

注意第4行先COPY requirements.txt再RUN pip install,然后才COPY scanner.py。这个顺序不是随意的——Docker的层缓存机制决定了:如果scanner.py变了但requirements.txt没变,pip install层会命中缓存跳过执行,构建速度大幅提升。

构建镜像并运行:

Bash · 构建并运行
# 构建镜像,-t 指定名称:标签
docker build -t portscanner:1.0 .
# 查看镜像大小
docker images portscanner:1.0
REPOSITORY TAG SIZE
portscanner 1.0 52MB
# 运行容器(--rm表示退出后自动删除)
docker run --rm portscanner:1.0 --target 192.168.1.0/24
⚠️ 常见错误
FROM ubuntu:latest
问题:latest标签会随时间指向不同版本。今天构建的镜像和下个月构建的可能基于不同的Ubuntu版本,导致依赖断裂或引入新漏洞。
✓ 正确:FROM ubuntu:24.04 或更精确的 FROM ubuntu@sha256:a3b4c5...(使用digest锁定到确切版本)

04 docker-compose多容器编排

当服务由多个容器组成(比如Web应用 + 数据库 + 缓存),逐个docker run不仅繁琐还容易出错。Docker Compose用一个YAML文件定义所有服务、网络、卷,一条命令完成全部编排。

注意:Docker Compose v1(命令带连字符 docker-compose)已于2024年5月停止维护。当前使用的是Compose v2/v5(命令 docker compose,无连字符),作为Docker CLI插件随Engine一起安装。

4.1 docker-compose.yml结构

下面是一个Web应用+数据库的编排文件,展示了services、volumes、networks三大顶级元素的用法。

YAML · docker-compose.yml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
services:
  web:
    build: .
    ports:
      - "5000:5000"
    depends_on:
      - db
    environment:
      DB_HOST: db
      DB_PASS: ${DB_PASSWORD}
  db:
    image: postgres:16-alpine
    environment:
      POSTGRES_PASSWORD: ${DB_PASSWORD}
    volumes:
      - db_data:/var/lib/postgresql/data
volumes:
  db_data:

关键点解读:depends_on只保证启动顺序,不等待db就绪——应用需要自己处理重试逻辑。${DB_PASSWORD}从.env文件读取,避免在YAML中硬编码密码。服务名db自动成为DNS名称——web容器内可以用db:5432连接数据库。

4.2 Compose核心命令

1 docker compose up -d — 后台启动所有服务
2 docker compose ps — 查看服务状态
3 docker compose logs -f — 持续查看所有服务日志
4 docker compose down — 停止并删除容器、网络(加-v同时删除卷)
💡 小贴士
docker compose down -v 中的 -v 参数会删除命名卷中的所有数据。在靶场环境中这是好事——每次重置到干净状态。但如果在生产环境误加 -v,数据库会被清空。养成习惯:down 前先看一眼有没有 volume。

05 容器安全:攻击面与防御策略

为什么安全从业者必须理解容器?因为现代企业基础设施高度容器化,渗透测试中遇到Docker环境是常态。容器的隔离边界比虚拟机薄得多——共享内核意味着一个内核漏洞就能从容器逃逸到宿主机。本节聚焦容器安全的6项关键防御措施。

5.1 容器逃逸的常见路径

• 特权模式逃逸:--privileged 容器拥有所有Linux capabilities,可以访问宿主机所有设备(包括磁盘设备文件),直接挂载宿主机文件系统即可逃逸
• Docker Socket挂载:将 /var/run/docker.sock 挂载进容器,容器内就能调用Docker API创建新容器并挂载宿主机根目录
• 内核漏洞利用:容器与宿主机共享内核。DirtyPipe (CVE-2022-0847)、Dirty COW (CVE-2016-5195)等内核漏洞可直接从容器内攻击宿主机内核
• capabilities滥用:如果容器保留了 CAP_SYS_ADMIN 或 CAP_SYS_PTRACE 等高危权限,攻击者可以利用它们突破隔离

5.2 六项容器加固措施

以下加固措施在docker-compose.yml中通过安全选项实现。对比"默认配置"和"加固配置":

YAML · 容器安全加固
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
services:
  app:
    image: myapp:1.0
    user: "1000:1000"  # ① 非root运行
    read_only: true        # ② 只读文件系统
    security_opt:
      - no-new-privileges:true  # ③ 禁止提权
    cap_drop:
      - ALL                 # ④ 丢弃所有capabilities
    cap_add:
      - NET_BIND_SERVICE  # ⑤ 仅保留必需权限
    tmpfs:
      - /tmp                 # ⑥ 临时目录用tmpfs
    ports:
      - "127.0.0.1:5000:5000"  # 仅本地暴露
    mem_limit: 256m         # 资源限制

逐条解释加固效果:

• ①非root运行:即使攻击者拿到容器内shell,也只是普通用户权限,无法修改系统文件
• ②只读文件系统:攻击者无法在容器内植入后门或修改二进制文件
• ③禁止提权:no-new-privileges阻止通过setuid程序提权
• ④⑤capabilities精简:先丢弃全部Linux capabilities,再仅加回绑定1024以下端口所需的NET_BIND_SERVICE
• ⑥tmpfs临时目录:/tmp用内存文件系统,容器停止即消失

端口映射中的 127.0.0.1: 前缀也很关键——默认的 "5000:5000" 会绑定 0.0.0.0(所有网卡),导致服务暴露到外网。加上 127.0.0.1: 前缀后只允许本机访问,这在部署靶场时尤为重要——你不想让DVWA暴露到公网。

💡 小贴士
渗透测试中检查Docker环境的"三步快查法":第一步执行 cat /proc/1/cgroup | grep docker 确认是否在容器内;第二步检查 capsh --print 查看当前capabilities;第三步查看 mount 输出中是否挂载了 docker.sock 或宿主机目录。这三步在30秒内完成,能快速判断容器逃逸的可能性。

06 实战:用Docker部署DVWA漏洞靶场

理论学完,现在动手部署DVWA(Damn Vulnerable Web Application)。DVWA是最经典的Web安全练习靶场,内置SQL注入、XSS、文件上传、命令注入等十余种漏洞。用Docker部署只需三条命令,比传统LAMP环境搭建快十倍。

6.1 部署DVWA

Bash · 部署DVWA靶场
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 1. 克隆DVWA仓库(内置docker-compose.yml)
git clone https://github.com/digininja/DVWA.git
cd DVWA
# 2. 一键启动(Web + MySQL两个容器)
docker compose up -d
[+] Running 3/3
✔ Network dvwa_default Created
✔ Container dvwa-db Started
✔ Container dvwa-web Started
# 3. 验证服务状态
docker compose ps
NAME STATUS PORTS
dvwa-web Up 30s 0.0.0.0:4280->80/tcp
dvwa-db Up 30s 3306/tcp

注意端口映射:DVWA在容器内监听80端口,但docker-compose.yml将其映射到宿主机4280端口(避免与本地Web服务冲突)。浏览器访问 http://localhost:4280 即可打开DVWA登录页。默认账号 admin / password。

6.2 DVWA初始化与安全配置

首次访问DVWA需要初始化数据库。在DVWA首页点击"Create / Reset Database"按钮,然后重新登录。登录后进入"DVWA Security"页面,可以切换三个安全等级:

安全等级 防护机制 练习目标
Low 无任何过滤 理解漏洞原理,手工构造Payload
Medium 基本过滤(如str_replace) 学习绕过简单防护(大小写、编码)
High 强过滤(如htmlspecialchars+mysql_real_escape_string) 挑战高级绕过技巧

6.3 清理与重置

练习完毕后清理环境,释放资源:

Bash · 清理DVWA环境
# 停止并删除容器和网络(保留数据卷)
docker compose down
# 彻底清除(含数据卷,重置到干净状态)
docker compose down -v
# 清理悬空镜像(释放磁盘空间)
docker image prune -f

用同样的方式可以部署Vulhub——一个面向安全研究者的漏洞环境集合,涵盖Apache、Nginx、Tomcat、Struts2等数百个已知CVE的复现环境。Vulhub的使用方式与DVWA完全一致:克隆仓库、进入对应CVE目录、docker compose up -d。这套"克隆→compose→练习→down"的工作流将贯穿你后续所有的Web渗透学习。

📖 知识回顾
镜像/容器/卷/网络 容器 vs 虚拟机 Dockerfile指令 docker-compose编排 容器逃逸路径 六项加固措施 DVWA靶场部署 docker.sock安全风险
✏️ 动手练习
🟢 基础验证
在Kali上安装Docker后,执行 docker run -d --name test -p 8080:80 nginx:alpine,然后用浏览器访问 http://localhost:8080。确认看到Nginx欢迎页后,用 docker exec 进入容器,修改 /usr/share/nginx/html/index.html 的内容,刷新页面验证修改生效。
🟡 组合应用
编写一个Dockerfile,构建一个包含nmap的安全工具镜像。要求:基础镜像使用 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 安装软件包。
🔴 开放挑战
部署DVWA后,在安全等级Low下完成SQL Injection模块。要求:①手工构造Payload绕过登录(不用sqlmap);②用 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,关注前者防什么后者防什么。
下篇预告 · 进入第一大阶段
模块1 信息收集与侦察:nmap主动扫描
基础模块全部完结,即将进入攻击技术体系。将从信息收集开始——渗透测试的第一步,学习nmap的SYN扫描、版本探测、NSE脚本,配合本篇部署的DVWA靶场进行实战演练
关注公众号持续获取系列更新