Apache JMeter Docker Compose 部署指南
用 Docker Compose 在 Ubuntu 22.04 上编排部署 Apache JMeter 5.6.3,含镜像选型、compose 文件、非 GUI 压测、数据持久化、常用运维命令与 FAQ,均已实测。
Apache JMeter Docker Compose 部署指南
目标:通过 Docker Compose 在 Ubuntu 22.04 上编排部署 Apache JMeter 5.6.3,用非 GUI 模式对容器内 HTTP 服务压测,覆盖镜像选型、compose 编排、结果持久化、JVM 堆限制与常用运维命令。已在 Ubuntu 22.04.5 / Docker 环境实测通过。
一、环境信息
- 操作系统:Ubuntu 22.04.5 LTS(x86_64)
- 容器运行时:Docker + Docker Compose(Compose V2,
docker compose子命令) - 基础镜像:
eclipse-temurin:17-jre(Eclipse Temurin OpenJDK 17,兼容 JMeter 5.6.3) - Apache JMeter:5.6.3(官方
apache-jmeter-5.6.3.tgz) - 编排文件:
/opt/jmeter-compose/docker-compose.yml - 项目目录:
/opt/jmeter-compose - 压测目标:容器内
python3 -m http.server 8080 - 结果目录(宿主机挂载):
/opt/jmeter-compose/results - 测试账号:
root/q1w2e3r4(如涉及)
二、镜像选型说明
JMeter 官方不发布官方 Docker 镜像,社区常用以下两类:
| 方案 | 镜像 | 优点 | 缺点 |
|---|---|---|---|
| A:官方二进制 + 自建镜像 | eclipse-temurin:17-jre(基础)+ 打入 apache-jmeter-5.6.3.tgz | 完全可控、版本精确、体积适中 | 需自行写 Dockerfile |
| B:社区现成镜像 | justb4/jmeter(含 JMeter 5.x 系列) | 开箱即用、无需写 Dockerfile | 版本跟随社区维护节奏 |
💡 说明:本文采用方案 A,基于
eclipse-temurin:17-jre构建,镜像内打入 Apache 官方发布的 5.6.3 二进制,保证版本与官方一致。
三、前置条件
3.1 确认 Docker 与 Compose 已安装
docker --version
docker compose version
回显(示例):
Docker version 24.0.7, build afdd53b
Docker Compose version v2.23.3
3.2 准备项目目录
mkdir -p /opt/jmeter-compose/results
四、部署步骤
4.1 编写 JMeter 基础镜像 Dockerfile
/opt/jmeter-compose/Dockerfile:
FROM eclipse-temurin:17-jre
# 安装 wget 与 python3(压测目标服务用)
RUN apt-get update \
&& apt-get install -y --no-install-recommends wget python3 \
&& rm -rf /var/lib/apt/lists/*
# 下载并解压 Apache JMeter 5.6.3 官方二进制
RUN mkdir -p /opt/jmeter \
&& wget -q https://dlcdn.apache.org//jmeter/binaries/apache-jmeter-5.6.3.tgz -O /tmp/jmeter.tgz \
&& tar -xzf /tmp/jmeter.tgz -C /opt \
&& ln -sf /opt/apache-jmeter-5.6.3 /opt/apache-jmeter \
&& rm -f /tmp/jmeter.tgz
# 限制 JVM 堆为 256MB(编辑 bin/jmeter 脚本内 HEAP 默认值)
RUN sed -i 's|: "${HEAP:="-Xms1g -Xmx1g -XX:MaxMetaspaceSize=256m"}"|: "${HEAP:="-Xms256m -Xmx256m -Xmn128m -XX:MaxMetaspaceSize=256m"}"|' /opt/apache-jmeter/bin/jmeter
WORKDIR /opt/apache-jmeter/bin
CMD ["sh"]
4.2 编写 docker-compose.yml
/opt/jmeter-compose/docker-compose.yml:
services:
jmeter:
build: .
image: jmeter:5.6.3
container_name: jmeter-5-6-3
hostname: jmeter
working_dir: /opt/apache-jmeter/bin
environment:
# JVM 堆限制(与 Dockerfile 内 HEAP 一致,双保险)
HEAP: "-Xms256m -Xmx256m -Xmn128m -XX:MaxMetaspaceSize=256m"
JAVA_HOME: /opt/java/openjdk
volumes:
# 挂载测试计划与结果目录(宿主机持久化)
- ./jmx:/opt/jmx:ro
- ./results:/opt/results
- ./webroot:/opt/webroot:ro
ports:
- "8080:8080"
command: >
sh -c "cd /opt/webroot && nohup python3 -m http.server 8080 >/tmp/http.log 2>&1 &
sleep 2 && cd /opt/apache-jmeter/bin && ./jmeter -n -t /opt/jmx/http_test.jmx -l /opt/results/result.jtl -e -o /opt/results/report"
💡 说明:
command中先启动容器内的 python3 http.server(模拟被测 Web 服务),再运行 JMeter 非 GUI 压测,两者同处一个容器网络,JMeter 通过127.0.0.1:8080或jmeter:8080访问目标均可。
4.3 准备测试计划与目标页面
/opt/jmeter-compose/jmx/http_test.jmx(10 线程、Ramp-Up 2 秒、GET 根路径,节选核心片段):
<jmeterTestPlan version="1.2" properties="5.0" jmeter="5.6.3">
<hashTree>
<TestPlan guiclass="TestPlanGui" testclass="TestPlan" testname="HTTP Test Plan" enabled="true"/>
<hashTree>
<ThreadGroup guiclass="ThreadGroupGui" testclass="ThreadGroup" testname="Thread Group" enabled="true">
<stringProp name="ThreadGroup.num_threads">10</stringProp>
<stringProp name="ThreadGroup.ramp_time">2</stringProp>
<boolProp name="ThreadGroup.scheduler">false</boolProp>
</ThreadGroup>
<hashTree>
<HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="HTTP Request" enabled="true">
<stringProp name="HTTPSampler.domain">127.0.0.1</stringProp>
<stringProp name="HTTPSampler.port">8080</stringProp>
<stringProp name="HTTPSampler.protocol">http</stringProp>
<stringProp name="HTTPSampler.path">/</stringProp>
<stringProp name="HTTPSampler.method">GET</stringProp>
</HTTPSamplerProxy>
<hashTree>
<ResultCollector guiclass="SummaryReport" testclass="ResultCollector" testname="Summary Report" enabled="true"/>
<hashTree/>
</hashTree>
</hashTree>
</hashTree>
</hashTree>
</jmeterTestPlan>
/opt/jmeter-compose/webroot/index.html:
Hello JMeter from target server
4.4 构建并启动
cd /opt/jmeter-compose
docker compose up -d --build
回显(节选):
[+] Building 5.4s (10/10) FINISHED
[+] Running 1/1
✔ Container jmeter-5-6-3 Started
4.5 查看压测结果(宿主机侧持久化)
等待测试跑完后,结果落在挂载的 results 目录:
ls -l /opt/jmeter-compose/results
回显:
-rw-r--r-- 1 root root 1896 Oct 11 11:25 result.jtl
drwxr-xr-x 4 root root 4096 Oct 11 11:25 report
查看 JMeter 非 GUI 汇总(从容器日志):
docker compose -f /opt/jmeter-compose/docker-compose.yml logs jmeter
回显(节选):
jmeter-5-6-3 | summary = 10 in 00:00:02 = 4.7/s Avg: 72 Min: 3 Max: 156 Err: 0 (0.00%)
jmeter-5-6-3 | Tidying up ... @ 2026 Oct 11 11:10:43 GMT
jmeter-5-6-3 | ... end of run
五、数据持久化说明
| 挂载点 | 宿主机路径 | 用途 |
|---|---|---|
/opt/jmx:ro | /opt/jmeter-compose/jmx | 测试计划(.jmx)只读挂入 |
/opt/results | /opt/jmeter-compose/results | 结果 JTL 与 HTML 报告落盘 |
/opt/webroot:ro | /opt/jmeter-compose/webroot | 被测静态页面 |
⚠️ 注意:结果目录必须持久化挂载,否则容器销毁后压测数据丢失。
六、常用环境变量表
| 变量 | 默认值 | 说明 |
|---|---|---|
HEAP | -Xms256m -Xmx256m -Xmn128m -XX:MaxMetaspaceSize=256m | JVM 堆限制,运行时覆盖脚本内默认 |
JAVA_HOME | /opt/java/openjdk | 容器内 Temurin JDK 路径 |
JMETER_LANGUAGE | -Duser.language=en -Duser.region=EN | JMeter 界面语言(脚本内默认) |
GC_ALGO | -XX:+UseG1GC -XX:MaxGCPauseMillis=100 -XX:G1ReservePercent=20 | GC 算法与目标停顿 |
七、常用配置参数说明(command)
Compose 的 command: 支持传入 JMeter 参数:
| 参数 | 含义 | 示例 |
|---|---|---|
-n / --nongui | 非 GUI 模式 | -n |
-t <文件> | 测试计划路径 | -t /opt/jmx/http_test.jmx |
-l <文件> | 结果 JTL 输出路径 | -l /opt/results/result.jtl |
-e | 测试结束后生成 HTML 报告 | -e |
-o <目录> | 报告输出目录 | -o /opt/results/report |
-j <文件> | 日志文件路径 | -j /opt/results/jmeter.log |
-p <文件> | 额外 properties 文件 | -p /opt/jmx/user.properties |
-R <host> | 远程分布式 agent 地址 | -R 192.168.1.10:1099 |
八、配置文件持久化(conf 挂载)
需要自定义 jmeter.properties / user.properties 时,挂载覆盖:
services:
jmeter:
volumes:
- ./conf/user.properties:/opt/apache-jmeter/bin/user.properties:ro
宿主机 /opt/jmeter-compose/conf/user.properties 示例:
# 自定义属性示例
log_level.jmeter=INFO
summariser.interval=5
sampleresult.default.encoding=UTF-8
💡 说明:JMeter 启动时自动加载
bin/user.properties(若存在),优先级高于jmeter.properties同名键。
九、等价 docker run 运行方式
不写 compose 文件时,等价的一条 docker run 命令:
docker run -d --name jmeter-5-6-3 \
-e HEAP="-Xms256m -Xmx256m -Xmn128m -XX:MaxMetaspaceSize=256m" \
-v /opt/jmeter-compose/jmx:/opt/jmx:ro \
-v /opt/jmeter-compose/results:/opt/results \
-v /opt/jmeter-compose/webroot:/opt/webroot:ro \
-p 8080:8080 \
jmeter:5.6.3 \
sh -c "cd /opt/webroot && nohup python3 -m http.server 8080 >/tmp/http.log 2>&1 & sleep 2 && cd /opt/apache-jmeter/bin && ./jmeter -n -t /opt/jmx/http_test.jmx -l /opt/results/result.jtl -e -o /opt/results/report"
十、常用运维命令
# 构建镜像并后台启动服务
cd /opt/jmeter-compose && docker compose up -d --build
# 查看服务状态
docker compose ps
# 跟踪 JMeter 压测日志(实时看 summary)
docker compose logs -f jmeter
# 进入容器交互排查
docker compose exec jmeter bash
# 容器内执行 JMeter 版本验证
docker compose exec jmeter /opt/apache-jmeter/bin/jmeter -v
# 容器内用 jps 确认 JVM 堆参数生效
docker compose exec jmeter jps -v
# 停止并移除容器(保留 results 持久化数据)
docker compose down
# 停止并移除容器 + 网络 + 匿名卷
docker compose down -v
十一、常见问题(FAQ)
Q1:容器启动后立即退出,日志无压测输出
多为 command 中 python3 未就绪或测试计划路径错误。用 docker compose logs jmeter 查看报错;确保挂载的 /opt/jmx/http_test.jmx 存在且权限可读。
Q2:docker compose up 提示端口 8080 被占用
宿主机已有服务占用 8080。改 ports 映射,如 "18080:8080",并同步修改 .jmx 中 HTTPSampler.port 与访问地址。
Q3:容器内 JMeter 堆仍是 1G
镜像构建时 sed 修改未生效,或运行时 HEAP 环境变量未传。检查 Dockerfile 中 sed 行是否正确命中(JMeter 5.6.3 脚本内为 -Xms1g -Xmx1g -XX:MaxMetaspaceSize=256m),并在 compose 中显式传 HEAP。
Q4:如何在分布式压测中指定多个 agent
非 GUI 启动加 -R host1,host2,agent 侧运行 ./jmeter-server(默认端口 1099);确保 jmeter.properties 中 remote_hosts=127.0.0.1 被覆盖为各 agent 地址。
十二、参考链接
- Apache JMeter 官方下载:https://jmeter.apache.org/download_jmeter.cgi
- Docker Compose 文档:https://docs.docker.com/compose/
- Eclipse Temurin 官方镜像:https://hub.docker.com/_/eclipse-temurin
- JMeter 非 GUI 模式:https://jmeter.apache.org/usermanual/get-started.html#non_gui
- JMeter 分布式测试指南:https://jmeter.apache.org/usermanual/remote-test.html