Docker 容器教程(软件测试人员专用)¶
本教程面向软件测试工程师,聚焦测试日常使用场景:快速搭建测试环境、隔离依赖、统一团队环境、CI 集成。
前置要求¶
| 项目 | 要求 | 获取方式 |
|---|---|---|
| Linux 基础 | 熟悉命令行操作、文件系统和进程管理 | Linux实用教程-软件测试版 |
新手导读¶
Docker 对新手来说可以先理解成“把环境打包起来运行”。测试人员使用 Docker,主要是为了快速启动数据库、缓存、接口服务或自动化运行环境。
第一遍重点掌握:
- 镜像和容器的区别。
- 如何
docker run启动一个服务。 - 如何查看日志和进入容器。
- 如何用 Docker Compose 同时启动多个服务。
- 如何停止和清理测试环境。
不要一开始就纠结镜像分层和底层网络,先把常用服务跑起来、会看日志、会排查端口占用。
版本与维护说明¶
| 项目 | 说明 |
|---|---|
| 适用工具 | Docker Engine、Docker Desktop、Docker Compose |
| 使用建议 | 新手优先掌握 docker run、日志查看、端口映射和 Compose 编排 |
| 更新提醒 | 安装方式、Compose 命令和 Linux 发行版仓库会变化,安装前以 Docker 官方文档为准 |
一、Docker 基础¶
1.1 什么是 Docker¶
Docker 是开源的应用容器引擎,将应用及其依赖打包成"容器",实现 一次构建,到处运行。
1.2 测试人员为什么要学 Docker¶
| 场景 | 价值 |
|---|---|
| 快速搭建测试环境 | 一条命令起 MySQL、Redis |
| 隔离依赖 | 不污染本机环境 |
| 团队环境统一 | 避免"我电脑能跑" |
| 多版本测试 | 同时跑 JDK 8、11、17 |
| Mock 服务 | 快速启动假接口 |
| CI 集成 | 与 Jenkins/GitHub Actions 配合 |
| 跨平台 | Windows/Mac/Linux 都能运行 |
1.3 Docker vs 虚拟机¶
虚拟机(VM) Docker
┌──────────────┐ ┌──────────────┐
│ App A │ │ App A │
├──────────────┤ ├──────────────┤
│ Bins/Libs │ │ Bins/Libs │
├──────────────┤ ├──────────────┤
│ Guest OS │ │ │
├──────────────┤ ├──────────────┤
│ Hypervisor │ │ Docker Engine│
├──────────────┤ ├──────────────┤
│ Host OS │ │ Host OS │
└──────────────┘ └──────────────┘
重 / 启动慢 轻 / 秒级启动
| 维度 | VM | Docker |
|---|---|---|
| 启动 | 分钟级 | 秒级 |
| 大小 | GB 级 | MB 级 |
| 资源 | 占用大 | 占用小 |
| 隔离性 | 强 | 中等 |
| 性能 | 较差 | 接近裸机 |
1.4 核心概念¶
- Image(镜像):只读模板,包含应用 + 依赖 + 配置
- Container(容器):镜像的运行实例
- Registry(仓库):镜像存储中心(如 Docker Hub)
- Dockerfile:定义镜像的脚本
- Volume(卷):持久化数据
- Network(网络):容器间通信
1.5 工作流程¶
Dockerfile → docker build → Image → docker push → Registry
↓ docker pull
Image → docker run → Container
二、安装与配置¶
2.1 Windows / Mac¶
下载 Docker Desktop:https://www.docker.com/products/docker-desktop
- 双击安装
- 启动后状态栏出现 Docker 图标(鲸鱼)
- 自动开机启动
注意
Windows 需要开启 Hyper-V 或 WSL2。
2.2 Linux¶
# Ubuntu(系统仓库版本较旧)
sudo apt update
sudo apt install docker.io
# CentOS(推荐 Docker 官方仓库的 docker-ce,系统自带 docker 包已过时)
sudo yum install -y yum-utils
sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
sudo yum install -y docker-ce docker-ce-cli containerd.io
# 通用一键脚本(最简单,安装最新 docker-ce)
curl -fsSL https://get.docker.com | sudo sh
# 启动
sudo systemctl start docker
sudo systemctl enable docker
# 普通用户免 sudo
sudo usermod -aG docker $USER
# 退出重登
curl 参数说明:
参数 含义 -f请求失败时返回错误码(而非输出 HTML 错误页) -s静默模式,不显示进度条和错误信息 -S配合 -s使用,出错时仍显示错误信息-L跟随 HTTP 重定向(301/302)自动跳转
2.3 验证安装¶
docker run hello-world 输出示例:
Hello from Docker!
This message shows that your installation appears to be working correctly.
To generate this message, Docker took the following steps:
1. The Docker client contacted the Docker daemon.
2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
3. The Docker daemon created a new container from that image.
4. The Docker daemon streamed that output to the Docker client.
2.4 配置镜像加速¶
国内访问 Docker Hub 慢,配置镜像加速器:
编辑 /etc/docker/daemon.json(Linux)或 Docker Desktop 设置:
{
"registry-mirrors": [
"https://docker.mirrors.ustc.edu.cn",
"https://hub-mirror.c.163.com",
"https://mirror.baidubce.com"
]
}
重启 Docker:
2.5 Docker Hub 账号(可选)¶
- 注册:
https://hub.docker.com - 登录:
docker login
三、镜像操作¶
3.1 搜索镜像¶
3.2 拉取镜像¶
# 拉默认 latest 标签
docker pull mysql
# 拉指定版本
docker pull mysql:8.0
docker pull mysql:5.7
# 从指定仓库拉
docker pull registry.example.com/myapp:v1.0
3.3 查看本地镜像¶
输出示例:
REPOSITORY TAG IMAGE ID CREATED SIZE
mysql 8.0 abc123def456 2 weeks ago 500MB
nginx latest 789ghi012jkl 1 month ago 140MB
3.4 删除镜像¶
docker rmi mysql:8.0
docker rmi abc123 # 用 ID 删除
docker rmi -f mysql:8.0 # 强制删除(容器在用也删)
# 删除所有 dangling 镜像(无 tag 的)
docker image prune
docker image prune -a # 删所有未使用镜像
3.5 查看镜像详情¶
3.6 镜像导入导出¶
适合无网络环境迁移:
四、容器操作¶
4.1 启动容器(最常用)¶
简单示例:
# 前台运行
docker run hello-world
# 后台运行
docker run -d nginx
# 端口映射
docker run -d -p 8080:80 nginx
# 本机 8080 映射到容器 80
# 命名容器
docker run -d --name mynginx -p 8080:80 nginx
# 交互式(进入 shell)
docker run -it ubuntu /bin/bash
常用参数:
| 参数 | 含义 |
|---|---|
-d |
后台运行 |
-i |
交互式 |
-t |
分配 tty |
-p |
端口映射 hostPort:containerPort |
-P |
随机端口映射 |
--name |
容器名 |
-v |
挂载卷 hostPath:containerPath |
-e |
环境变量 |
--network |
指定网络 |
--rm |
退出自动删除 |
--restart=always |
自动重启 |
-w |
工作目录 |
--cpus |
CPU 限制 |
--memory |
内存限制 |
4.2 查看容器¶
# 运行中的容器
docker ps
# 输出示例:
# CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
# a1b2c3d4e5f6 nginx "/docker-entrypoint.…" 5 minutes ago Up 5 minutes 0.0.0.0:8080->80/tcp mynginx
# f6e5d4c3b2a1 mysql "docker-entrypoint.s…" 2 hours ago Up 2 hours 0.0.0.0:3306->3306/tcp mysql_test
# 所有容器(含已停止)
docker ps -a
# 只显示 ID
docker ps -q
# 输出格式自定义
docker ps --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}"
| 参数 | 含义 |
|---|---|
--format |
自定义输出格式 |
{{.Names}} |
容器名称 |
{{.Status}} |
运行状态 |
{{.Ports}} |
端口映射 |
\t |
制表符(列对齐) |
4.3 启动/停止/重启¶
docker start mynginx
docker stop mynginx
docker restart mynginx
docker kill mynginx # 强制停止
docker pause mynginx # 暂停
docker unpause mynginx
4.4 删除容器¶
docker rm mynginx # 删已停止
docker rm -f mynginx # 强制删(运行中也删)
# 删所有已停止
docker container prune
# 删所有容器
docker rm -f $(docker ps -aq)
4.5 进入容器¶
# 进入运行中容器
docker exec -it mynginx /bin/bash
docker exec -it mynginx /bin/sh # 没 bash 时用 sh
# 进入后做啥都行:cd、ls、cat...
# 退出:exit
4.6 查看日志¶
docker logs mynginx
# 输出示例:
# /docker-entrypoint.sh: /docker-entrypoint.d/ is not empty, will attempt to perform configuration
# /docker-entrypoint.sh: Looking for shell scripts in /docker-entrypoint.d/
# Starting nginx: nginx.
docker logs -f mynginx # 实时跟踪
docker logs --tail 100 mynginx # 看最后 100 行
docker logs -t mynginx # 显示时间戳
docker logs --since 10m mynginx # 最近 10 分钟
4.7 查看容器详情¶
docker inspect mynginx
docker inspect --format='{{.NetworkSettings.IPAddress}}' mynginx
# 资源使用
docker stats # 实时
docker stats --no-stream # 一次快照
# 输出示例:
# CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS
# a1b2c3d4e5f6 mynginx 0.00% 2.5MiB / 7.7GiB 0.03% 1.2kB / 0B 0B / 0B 2
# f6e5d4c3b2a1 mysql_test 0.12% 210MiB / 7.7GiB 2.67% 5.6kB / 3.2kB 12MB / 0B 38
# 进程
docker top mynginx
4.8 文件传输¶
# 本机 → 容器
docker cp test.sql mysql_test:/tmp/
# 容器 → 本机
docker cp mysql_test:/var/log/mysql/error.log ./
4.9 提交为镜像¶
容器中修改后,保存为新镜像:
建议
不推荐这种方式,应该用 Dockerfile(可重复、可追溯)。
五、Dockerfile 编写¶
5.1 Dockerfile 是什么¶
定义镜像的脚本文件,每行一条指令。
5.2 第一个 Dockerfile¶
创建文件 Dockerfile:
# 基础镜像
FROM python:3.10-slim
# 工作目录
WORKDIR /app
# 复制文件
COPY requirements.txt .
# 安装依赖
RUN pip install -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple
# 复制源码
COPY . .
# 暴露端口
EXPOSE 5000
# 启动命令
CMD ["python", "app.py"]
构建镜像:
docker build 参数说明:
参数 含义 -t为镜像指定名称和标签(格式: 名称:标签).指定构建上下文路径,Docker 会将该目录下的文件发送给守护进程
运行:
5.3 常用指令¶
FROM: 基础镜像
WORKDIR: 工作目录
COPY / ADD: 复制文件
RUN: 构建时执行命令
RUN apt-get update && apt-get install -y curl
RUN pip install -r requirements.txt
RUN mkdir -p /var/log/app
# 多条命令合并(减少层数)
RUN apt-get update && \
apt-get install -y curl vim && \
rm -rf /var/lib/apt/lists/*
ENV: 环境变量
EXPOSE: 声明端口(仅文档作用)
VOLUME: 数据卷
USER: 切换用户
ARG: 构建参数
CMD vs ENTRYPOINT: 启动命令
# CMD:默认命令,可被覆盖
CMD ["python", "app.py"]
# ENTRYPOINT:固定入口,参数可追加
ENTRYPOINT ["python"]
CMD ["app.py"]
# 启动等价于:python app.py
# docker run myapp other.py → python other.py
5.4 Dockerfile 完整示例¶
Python 接口自动化测试:
FROM python:3.10-slim
LABEL maintainer="tester@company.com"
LABEL description="API automation test image"
ENV PYTHONDONTWRITEBYTECODE=1 \
PYTHONUNBUFFERED=1 \
PIP_INDEX_URL=https://pypi.tuna.tsinghua.edu.cn/simple
WORKDIR /app
# 系统依赖
RUN apt-get update && \
apt-get install -y --no-install-recommends \
curl \
git \
wget && \
rm -rf /var/lib/apt/lists/*
# 安装 Allure:构建前可到 releases 页面确认最新稳定版
ARG ALLURE_VERSION=2.30.0
RUN wget -O allure.tgz https://github.com/allure-framework/allure2/releases/download/${ALLURE_VERSION}/allure-${ALLURE_VERSION}.tgz && \
tar -zxvf allure.tgz -C /opt && \
ln -sf /opt/allure-${ALLURE_VERSION}/bin/allure /usr/local/bin/allure && \
rm allure.tgz
# Python 依赖
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
# 源码
COPY . .
CMD ["pytest", "--alluredir=./allure-results"]
构建并运行:
参数说明:
参数 含义 -t api-test:v1为镜像命名为 api-test,标签为v1--rm容器退出后自动删除(适合一次性测试任务) -v $(pwd)/reports:/app/allure-results将宿主机的 reports目录挂载到容器内,用于收集测试报告
5.5 优化建议¶
1. 合并 RUN: 减少镜像层数
# ❌ 多层
RUN apt-get update
RUN apt-get install -y curl
RUN apt-get install -y vim
# ✅ 合并
RUN apt-get update && \
apt-get install -y curl vim && \
rm -rf /var/lib/apt/lists/*
2. 利用缓存: 不常变的放前面
# ✅ 先复制 requirements,依赖变化少
COPY requirements.txt .
RUN pip install -r requirements.txt
# 后复制源码
COPY . .
3. 使用 .dockerignore: 排除不需要的文件
4. 多阶段构建: 减小最终镜像
# 构建阶段
FROM golang:1.20 AS builder
WORKDIR /src
COPY . .
RUN go build -o app
# 运行阶段
FROM alpine:latest
COPY --from=builder /src/app /app
CMD ["/app"]
5. 选择小镜像: 用 alpine 或 slim
六、数据卷与持久化¶
6.1 为什么需要卷¶
容器内的数据,容器删除后会丢失。需要持久化的数据(数据库、日志、配置)要用卷。
6.2 三种挂载方式¶
方式 1:Bind Mount(绑定挂载,最常用)
宿主机路径 ↔ 容器路径:
docker run -d \
-v /host/data:/var/lib/mysql \
mysql:8.0
# Windows
docker run -d -v D:/data:/var/lib/mysql mysql:8.0
方式 2:Volume(卷,Docker 管理)
# 创建卷
docker volume create mysql_data
# 使用
docker run -d -v mysql_data:/var/lib/mysql mysql:8.0
# 查看卷
docker volume ls
docker volume inspect mysql_data
# 删除卷
docker volume rm mysql_data
docker volume prune # 删未使用的
方式 3:tmpfs(内存挂载)
临时数据,重启即丢:
6.3 挂载只读¶
6.4 测试常见挂载¶
# 挂载配置文件
docker run -d \
-v $(pwd)/my.cnf:/etc/mysql/my.cnf:ro \
mysql:8.0
# 挂载初始化脚本
docker run -d \
-v $(pwd)/init.sql:/docker-entrypoint-initdb.d/init.sql:ro \
mysql:8.0
# 挂载日志目录
docker run -d \
-v $(pwd)/logs:/var/log/nginx \
nginx
七、网络管理¶
7.1 默认网络¶
输出示例:
NETWORK ID NAME DRIVER SCOPE
8a7b6c5d4e3f bridge bridge local
1f2e3d4c5b6a host host local
9c8b7a6f5e4d none null local
| 网络 | 用途 |
|---|---|
bridge |
默认,单机容器互通 |
host |
共享宿主机网络 |
none |
无网络 |
7.2 端口映射¶
# -p hostPort:containerPort
docker run -d -p 8080:80 nginx
# 访问 http://localhost:8080
# 指定主机 IP
docker run -d -p 192.168.1.100:8080:80 nginx
# 随机端口
docker run -d -P nginx
docker port <container> # 查看映射
7.3 自定义网络¶
容器间互通推荐用自定义 bridge:
# 创建网络
docker network create mynet
# 启动容器加入网络
docker run -d --name mysql --network mynet mysql:8.0
docker run -d --name app --network mynet myapp
# app 容器可通过名字访问 mysql:
# DB_HOST=mysql:3306
7.4 网络模式 host¶
容器与宿主机共享网络(无端口映射):
7.5 容器间通信¶
# 同网络下,容器名作为 hostname
docker exec app ping mysql
# 不同网络需要连接:
docker network connect mynet mycontainer
八、Docker Compose¶
8.1 为什么需要¶
启动多容器应用(如 App + MySQL + Redis)用命令行太繁琐,Docker Compose 用 YAML 一键管理。
8.2 安装¶
Docker Desktop 自带。Linux 单独装 V2 插件(推荐):
# Ubuntu/Debian
sudo apt install docker-compose-plugin
# CentOS
sudo yum install docker-compose-plugin
# 验证
docker compose version
注意
旧的独立二进制 docker-compose(V1,命令带短横)已停止维护,应使用 docker compose(V2,作为 docker 子命令)。本教程后续示例都用 docker compose。
8.3 第一个 docker-compose.yml¶
兼容性说明
Compose V2 已忽略 version 字段并发出弃用警告,新写的文件不要再加。本教程保留作示意,实际可删。
# version: '3.8' # V2 已弃用,可删除
services:
mysql:
image: mysql:8.0
container_name: my_mysql
restart: always
environment:
MYSQL_ROOT_PASSWORD: root123
MYSQL_DATABASE: testdb
ports:
- "3306:3306"
volumes:
- mysql_data:/var/lib/mysql
- ./init.sql:/docker-entrypoint-initdb.d/init.sql
redis:
image: redis:7
container_name: my_redis
restart: always
ports:
- "6379:6379"
app:
build: .
container_name: my_app
depends_on:
- mysql
- redis
environment:
DB_HOST: mysql
DB_PORT: 3306
REDIS_HOST: redis
ports:
- "8080:8080"
volumes:
mysql_data:
8.4 常用命令¶
# 启动所有服务(后台)
docker compose up -d
# 输出示例:
# [+] Running 4/4
# ✔ Network myproject_default Created 0.1s
# ✔ Container my_mysql Started 2.3s
# ✔ Container my_redis Started 0.8s
# ✔ Container my_app Started 1.5s
# 停止
docker compose stop
# 启动已停止的
docker compose start
# 重启
docker compose restart
# 停止并删除容器
docker compose down
# 同时删除卷
docker compose down -v
# 看状态
docker compose ps
# 输出示例:
# NAME IMAGE COMMAND SERVICE STATUS PORTS
# my_mysql mysql:8.0 "docker-entrypoint.s…" mysql running 0.0.0.0:3306->3306/tcp
# my_redis redis:7 "docker-entrypoint.s…" redis running 0.0.0.0:6379->6379/tcp
# my_app myproject-app "python app.py" app running 0.0.0.0:8080->8080/tcp
# 看日志
docker compose logs
docker compose logs -f app # 单个服务
# 进入容器
docker compose exec mysql bash
# 重建(Dockerfile 变了)
docker compose build
docker compose up -d --build
8.5 配置详解¶
services:
myapp:
image: nginx:latest # 用现有镜像
# 或
build: # 从 Dockerfile 构建
context: .
dockerfile: Dockerfile
args:
VERSION: 1.0
container_name: my_app # 容器名
restart: always # 重启策略
# always / on-failure / unless-stopped / no
ports: # 端口映射
- "8080:80"
- "443:443"
environment: # 环境变量
- APP_ENV=production
- DB_HOST=mysql
# 或
env_file:
- .env
volumes: # 挂载
- ./logs:/var/log
- mydata:/data
depends_on: # 启动顺序
- mysql
- redis
networks: # 加入网络
- mynet
healthcheck: # 健康检查
test: ["CMD", "curl", "-f", "http://localhost/health"]
interval: 30s
timeout: 10s
retries: 3
deploy: # 资源限制
resources:
limits:
cpus: '0.5'
memory: 512M
volumes:
mydata:
networks:
mynet:
driver: bridge
九、测试环境搭建¶
9.1 一键起 MySQL¶
docker run -d \
--name mysql_test \
-e MYSQL_ROOT_PASSWORD=root123 \
-e MYSQL_DATABASE=testdb \
-e MYSQL_USER=test \
-e MYSQL_PASSWORD=test123 \
-p 3306:3306 \
-v mysql_data:/var/lib/mysql \
mysql:8.0
# 连接
docker exec -it mysql_test mysql -uroot -proot123
9.2 一键起 Redis¶
docker run -d \
--name redis_test \
-p 6379:6379 \
redis:7
# 连接
docker exec -it redis_test redis-cli
9.3 一键起 RabbitMQ¶
docker run -d \
--name rabbit_test \
-p 5672:5672 \
-p 15672:15672 \
-e RABBITMQ_DEFAULT_USER=admin \
-e RABBITMQ_DEFAULT_PASS=admin \
rabbitmq:3-management
# 管理界面:http://localhost:15672
9.4 一键起 MongoDB¶
docker run -d \
--name mongo_test \
-p 27017:27017 \
-e MONGO_INITDB_ROOT_USERNAME=admin \
-e MONGO_INITDB_ROOT_PASSWORD=admin \
mongo:6
9.5 一键起 Elasticsearch¶
docker run -d \
--name es_test \
-p 9200:9200 \
-p 9300:9300 \
-e "discovery.type=single-node" \
-e "xpack.security.enabled=false" \
-e "ES_JAVA_OPTS=-Xms512m -Xmx512m" \
elasticsearch:8.10.0
注意
ES 默认堆内存较大,单机测试建议显式限制 ES_JAVA_OPTS,否则容易 OOM 或启动失败。
9.6 完整测试环境¶
docker-compose.yml:
services:
mysql:
image: mysql:8.0
environment:
MYSQL_ROOT_PASSWORD: root123
MYSQL_DATABASE: testdb
ports: ["3306:3306"]
volumes:
- ./mysql/init.sql:/docker-entrypoint-initdb.d/init.sql
- mysql_data:/var/lib/mysql
redis:
image: redis:7
ports: ["6379:6379"]
rabbitmq:
image: rabbitmq:3-management
ports: ["5672:5672", "15672:15672"]
environment:
RABBITMQ_DEFAULT_USER: admin
RABBITMQ_DEFAULT_PASS: admin
nginx:
image: nginx:alpine
ports: ["80:80"]
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf
volumes:
mysql_data:
启动:
十、测试场景实战¶
10.1 场景一:跑接口自动化测试¶
将 Python 自动化项目容器化:
Dockerfile:
FROM python:3.10-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt \
-i https://pypi.tuna.tsinghua.edu.cn/simple
COPY . .
CMD ["pytest", "--alluredir=./allure-results", "-v"]
执行:
10.2 场景二:多版本兼容性测试¶
测试代码在 Python 3.8 / 3.10 / 3.12 上是否兼容:
for ver in 3.8 3.10 3.12; do
docker run --rm \
-v $(pwd):/app -w /app \
python:$ver \
sh -c "pip install -r requirements.txt && pytest"
done
10.3 场景三:搭建 Selenium Grid¶
分布式 UI 测试环境:
services:
selenium-hub:
image: selenium/hub:latest
ports:
- "4442:4442"
- "4443:4443"
- "4444:4444"
chrome:
image: selenium/node-chrome:latest
shm_size: 2gb
depends_on:
- selenium-hub
environment:
SE_EVENT_BUS_HOST: selenium-hub
SE_EVENT_BUS_PUBLISH_PORT: 4442
SE_EVENT_BUS_SUBSCRIBE_PORT: 4443
firefox:
image: selenium/node-firefox:latest
shm_size: 2gb
depends_on:
- selenium-hub
environment:
SE_EVENT_BUS_HOST: selenium-hub
SE_EVENT_BUS_PUBLISH_PORT: 4442
SE_EVENT_BUS_SUBSCRIBE_PORT: 4443
启动:
Grid 控制台:http://localhost:4444
10.4 场景四:Mock 服务¶
启动 WireMock:
docker run -d \
--name wiremock \
-p 8080:8080 \
-v $(pwd)/mappings:/home/wiremock/mappings \
wiremock/wiremock
mappings/get_user.json:
{
"request": {
"method": "GET",
"url": "/api/user/1"
},
"response": {
"status": 200,
"headers": {"Content-Type": "application/json"},
"jsonBody": {
"id": 1,
"name": "test user",
"email": "test@example.com"
}
}
}
测试:
10.5 场景五:测试环境快速重置¶
# 一键销毁
docker compose down -v
# 一键重建
docker compose up -d
# 重置一个服务
docker compose down mysql
docker compose up -d mysql
10.6 场景六:在 Jenkins 中用 Docker 跑测试¶
Jenkinsfile:
pipeline {
agent any
stages {
stage('Build') {
steps {
sh 'docker build -t api-test:${BUILD_NUMBER} .'
}
}
stage('Test') {
steps {
sh '''
docker run --rm \
-v $WORKSPACE/reports:/app/allure-results \
api-test:${BUILD_NUMBER}
'''
}
}
}
post {
always {
sh 'docker rmi api-test:${BUILD_NUMBER} || true'
allure results: [[path: 'reports']]
}
}
}
十一、常见问题排查¶
11.1 容器启动后立即退出¶
11.2 端口占用¶
# 报错:port is already allocated(端口被占用)
# 找出是谁占了 8080 端口
netstat -anp | grep 8080 # Linux / Mac(显示进程 PID)
netstat -ano | findstr :8080 # Windows(显示 PID,再用 tasklist 查进程名)
lsof -i:8080 # Linux / Mac(直接显示进程名,更直观)
# 找到后:改端口映射(如 -p 8081:80)或停止占用的程序
11.3 磁盘空间不足¶
# 看 Docker 占用
docker system df
# 一键清理
docker system prune -a # 删未用镜像/容器/网络
docker system prune -a --volumes # 含卷
⚠️ 生产环境慎用!
-a和--volumes会删除大量资源,可能导致数据丢失。
| 参数 | 含义 |
|---|---|
prune |
清理无用资源 |
-a |
删除所有未使用的镜像(不仅是悬空的) |
--volumes |
同时删除未使用的卷(数据会丢失!) |
11.4 容器无法访问外网¶
# 检查 DNS
docker run --rm alpine nslookup baidu.com
# 修复(Linux)
# 编辑 /etc/docker/daemon.json
{
"dns": ["8.8.8.8", "114.114.114.114"]
}
sudo systemctl restart docker
11.5 容器间无法通信¶
# 检查是否同网络
docker network inspect bridge
# 用自定义网络
docker network create mynet
docker run -d --network mynet --name db mysql
docker run -d --network mynet --name app myapp
# app 中用 db:3306 连接
11.6 挂载目录权限问题¶
# 容器内写文件失败:Permission denied
# Linux 常见,UID 不匹配
# 方案 1:指定运行用户
docker run -u $(id -u):$(id -g) ...
# 方案 2:宿主机改权限
chmod -R 777 ./data
11.7 时区不对¶
11.8 镜像拉取慢¶
11.9 Docker 命令权限不足¶
11.10 容器健康但应用不健康¶
# 容器 running,但服务不可用
# 看日志
docker logs --tail 100 container
# 进容器排查
docker exec -it container bash
# 内部 curl localhost:8080
十二、最佳实践¶
12.1 开发测试规范¶
- 一个容器一个进程
- 镜像版本固定(用
mysql:8.0,不用mysql:latest) - 数据持久化用卷
- 配置外部化(环境变量、配置文件)
- 用 docker-compose 编排
- 定期清理资源
12.2 资源限制¶
docker run -d \
--cpus="0.5" \ # 最多用 0.5 个 CPU
--memory="512m" \ # 内存上限
--memory-swap="1g" \ # 含 swap
nginx
| 参数 | 含义 |
|---|---|
--cpus |
限制 CPU 核数(0.5 = 半核) |
--memory |
内存上限 |
--memory-swap |
内存+swap 总上限(1g 表示 swap 可用 512m) |
12.3 安全建议¶
- 不用 root 用户运行
- 不在镜像里放密码
- 镜像来源可信
- 及时更新基础镜像(修补漏洞)
- 不要
--privileged
12.4 命令速查¶
# 镜像
docker pull/push/build/tag/rmi/images/search/inspect
# 容器
docker run/start/stop/restart/rm/ps/logs/exec/inspect
# 卷
docker volume create/ls/inspect/rm/prune
# 网络
docker network create/ls/inspect/rm/connect
# Compose
docker compose up/down/start/stop/restart/ps/logs/exec/build
# 清理
docker system prune
docker volume prune
docker image prune
docker container prune
12.5 推荐学习资源¶
- 官方文档:
https://docs.docker.com/ - Docker Hub:
https://hub.docker.com/ - 《Docker 实践》《Docker 从入门到实践》
- Play with Docker(在线练习):
https://labs.play-with-docker.com/
测试纪律
Docker 容器是测试人员的瑞士军刀,正确使用能极大提升效率。但要养成清理习惯,避免磁盘占满;密码等敏感信息不要硬编码在 Dockerfile,用环境变量或秘钥管理。