适用场景
本文记录在 Ubuntu 22.04 上使用 Docker Compose 部署 Jeepay 的步骤。Jeepay 是一套开源支付系统,后端仓库是 jeequan/jeepay,前端仓库是 jeequan/jeepay-ui。
官方 Compose 部署方式适合本地、内网测试、功能验证和二次开发环境。它会一次性启动 MySQL、Redis、RocketMQ、支付网关、运营平台、商户系统,以及三个前端入口。
不要把这套默认配置直接暴露到公网生产环境。默认数据库密码、默认管理账号、多个中间件端口和后台入口都需要在上线前重新设计访问边界。
官方参考文档:
- Jeepay 后端仓库:https://github.com/jeequan/jeepay
- Jeepay 前端仓库:https://github.com/jeequan/jeepay-ui
- Docker Compose 部署文档:https://github.com/jeequan/jeepay/blob/V3.2.9/docs/deploy/compose.md
- Docker Ubuntu 安装文档:https://docs.docker.com/engine/install/ubuntu/
前置条件
服务器环境:
- Ubuntu 22.04
- 建议至少 4 核 CPU、8 GB 内存
- 已能访问 GitHub,或自行替换为 Gitee/GitCode 镜像仓库
- 已安装 Docker Engine 和 Docker Compose Plugin
Jeepay 后端使用 JDK 17 构建,前端会在 Docker 构建阶段使用 Node.js 镜像构建,所以宿主机至少需要安装 git、openjdk-17-jdk、maven。
sudo apt update
sudo apt install -y git openjdk-17-jdk maven ca-certificates curl gnupg
验证 Java 和 Maven:
java -version
mvn -version
如果还没有安装 Docker,可以参考本站的 Docker 入门:Ubuntu 安装与基础配置,也可以按 Docker 官方文档安装:
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc
echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu \
$(. /etc/os-release && echo "${UBUNTU_CODENAME:-$VERSION_CODENAME}") stable" | \
sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt update
sudo apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
把当前用户加入 docker 组:
sudo usermod -aG docker "$USER"
newgrp docker
验证 Docker:
docker version
docker compose version
创建部署目录
官方 Compose 默认要求后端目录 jeepay 和前端目录 jeepay-ui 放在同一级目录下。本文统一放在 /opt/jeepay-open:
sudo mkdir -p /opt/jeepay-open
sudo chown -R "$USER:$USER" /opt/jeepay-open
cd /opt/jeepay-open
拉取源码
本文固定使用后端 V3.2.9 标签。GitHub 上的标签名是大写 V3.2.9,也就是常说的 v3.2.9 版本。
后端仓库:
git clone --branch V3.2.9 --depth 1 https://github.com/jeequan/jeepay.git
前端仓库当前没有同名的 V3.2.9 标签,3.2 系列能看到的是 V3.2.0。如果只是按官方 Compose 拉起测试环境,可以先使用前端 V3.2.0 标签:
git clone --branch V3.2.0 --depth 1 https://github.com/jeequan/jeepay-ui.git
如果后续前端仓库发布了 V3.2.9 标签,建议把前端也同步固定到同名标签。不要在长期环境里一直跟随 master,因为 master 后续会变化,重新部署时拿到的代码可能和第一次部署不同。支付系统尤其不适合无意识升级。
查看 Compose 配置
进入后端目录:
cd /opt/jeepay-open/jeepay
官方 Compose 文件在后端仓库根目录:
ls -lh docker-compose.yml
docker compose config
默认端口如下:
| 组件 | 宿主机端口 |
|---|---|
| MySQL | 13306 |
| Redis | 6380 |
| RocketMQ NameServer | 9876 |
| RocketMQ Broker | 10909、10911、10912 |
| 支付网关 payment | 9216 |
| 运营平台后端 manager | 9217 |
| 商户系统后端 merchant | 9218 |
| 收银台前端 | 9226 |
| 运营平台前端 | 9227 |
| 商户系统前端 | 9228 |
这些端口默认会绑定到宿主机所有网卡。如果服务器有公网 IP,务必用防火墙限制来源,或者改成只监听 127.0.0.1 后再通过 Nginx 反向代理暴露必要入口。
镜像版本说明
官方 docker-compose.yml 里有几类镜像需要分开理解:
jeepay-payment:latest、jeepay-manager:latest、jeepay-merchant:latest、jeepay-ui-*.latest是本地构建出来的业务镜像,真正决定代码版本的是你 checkout 的源码版本。- MySQL、Redis、RocketMQ、JDK 基础镜像默认指向华为云 SWR 公开仓库,方便国内环境拉取。
MYSQL_IMAGE默认是swr.cn-south-1.myhuaweicloud.com/jeepay/mysql:8,属于浮动大版本标签。测试环境可以接受,生产环境应在充分验证后固定到明确镜像标签或镜像 digest。
如果要覆盖前端目录位置,可以创建 .env:
cat > .env <<'EOF'
UI_BASE_DIR=..
EOF
默认同级目录结构是 /opt/jeepay-open/jeepay-ui,所以这里保持 .. 即可。
打包后端
Compose 构建后端镜像时会复制各模块 target 目录里的 JAR,所以第一次启动前必须先执行 Maven 打包:
cd /opt/jeepay-open/jeepay
mvn clean package -DskipTests
打包成功后确认 JAR 文件存在:
ls jeepay-payment/target/jeepay-payment.jar
ls jeepay-manager/target/jeepay-manager.jar
ls jeepay-merchant/target/jeepay-merchant.jar
启动 Jeepay
首次启动建议带上 --build,让 Compose 构建后端和前端镜像:
cd /opt/jeepay-open/jeepay
docker compose up -d --build
查看容器状态:
docker compose ps
如果机器配置较低,RocketMQ 和前端构建可能需要等一段时间。可以持续查看核心服务日志:
docker compose logs -f --tail=100 payment manager merchant
查看全部日志:
docker compose logs -f --tail=100
后续如果只是重启,不需要重新构建:
docker compose up -d
如果修改了后端代码,需要重新打包并构建镜像:
mvn clean package -DskipTests
docker compose up -d --build
访问验证
在服务器本机可以这样验证端口:
curl -I http://127.0.0.1:9227
curl -I http://127.0.0.1:9228
curl -I http://127.0.0.1:9226
浏览器访问:
http://<Ubuntu服务器IP>:9227
http://<Ubuntu服务器IP>:9228
http://<Ubuntu服务器IP>:9226
默认入口:
- 运营平台:
http://<Ubuntu服务器IP>:9227 - 商户系统:
http://<Ubuntu服务器IP>:9228 - 收银台:
http://<Ubuntu服务器IP>:9226
默认账号:
| 系统 | 地址 | 默认账号 |
|---|---|---|
| 运营平台 | http://<Ubuntu服务器IP>:9227 | jeepay / jeepay123 |
| 商户系统 | http://<Ubuntu服务器IP>:9228 | 需要先在运营平台创建商户用户,默认密码 jeepay666 |
首次登录后应立即修改默认密码。不要把默认账号暴露在公网。
防火墙配置
如果只是内网测试,可以只允许可信网段访问前端端口。例如只允许 192.168.3.0/24 访问三个前端入口:
sudo ufw allow from 192.168.3.0/24 to any port 9226 proto tcp
sudo ufw allow from 192.168.3.0/24 to any port 9227 proto tcp
sudo ufw allow from 192.168.3.0/24 to any port 9228 proto tcp
sudo ufw status
不建议对公网开放这些端口:
13306:MySQL6380:Redis9876、10909、10911、10912:RocketMQ9216、9217、9218:后端服务直连端口
如果要正式对外访问,建议使用 Nginx、HTTPS、固定域名、最小化端口暴露,并把数据库、Redis、MQ 保持在内网。
如果只是为了让支付宝沙箱回调 Jeepay,可以临时用 ngrok 暴露 payment 服务:
nohup ngrok http --url=maria-salic-lithographically.ngrok-free.dev 9216 \
> /var/log/ngrok-jeepay-payment.log 2>&1 &
这里代理的是 9216 支付 API,不是前端页面。访问 https://maria-salic-lithographically.ngrok-free.dev/ 返回 404 是正常的,因为 payment 服务根路径没有首页;真正给支付宝用的是类似 https://maria-salic-lithographically.ngrok-free.dev/api/pay/notify/alipay 的回调路径。直接用浏览器或 curl 访问这个回调路径,如果没有带支付宝通知参数,通常会看到 order not exists,这反而说明请求已经打到 Jeepay payment 服务。
如果想通过 ngrok 访问页面,需要代理前端端口:9226 是收银台,9227 是运营平台,9228 是商户系统。但支付回调仍然应该指向 9216,不要把前端端口填到支付宝回调地址里。
接入 New-API:Jeepay + KitfoxPay
如果已经有 Jeepay 和 New-API,可以在中间增加 KitfoxPay 做适配。它对 New-API 暴露易支付接口,对下游调用 Jeepay API。这样 New-API 不需要改代码,只需要把易支付地址改成 KitfoxPay。
调用链路如下:
New-API
-> KitfoxPay: 易支付接口 mapi.php / submit.php / api.php
-> Jeepay: /api/pay/unifiedOrder 等接口
-> KitfoxPay: /api/payment/notify
-> New-API: /api/user/epay/notify 或 /api/subscription/epay/notify
注意访问边界:
- New-API 必须能访问 KitfoxPay 的对外地址。
- Jeepay 必须能回调 KitfoxPay 的
/api/payment/notify。 - KitfoxPay 必须能访问 Jeepay 的支付网关地址。
- New-API 的回调地址要是外部能访问的域名,不能只写 Pod、Service 或
127.0.0.1。
准备 Jeepay 参数
登录 Jeepay 运营平台:
http://<Ubuntu服务器IP>:9227
在 Jeepay 里准备或确认这些信息:
商户号:mchNo
应用 ID:appId
商户私钥:privateKey
已启用的支付方式:wayCode
wayCode 很重要。KitfoxPay 当前不会把 alipay、wxpay 转换成 Jeepay 的支付方式,而是直接把 New-API 传来的 payment_method 当成 Jeepay 的 wayCode 透传。也就是说,New-API 支付方式里的 type 要写成 Jeepay 已启用的 wayCode,例如 ALI_PC、ALI_WAP、ALI_QR、WX_NATIVE、WX_H5 等,具体以你在 Jeepay 应用里启用的支付接口为准。
部署 KitfoxPay
本文把 KitfoxPay 放在 /opt/kitfoxpay。KitfoxPay 当前没有 release tag,本文固定到写作时核对过的提交:
862c11bbe5387ded9df5ccf7772ca03ff286f058
部署:
sudo mkdir -p /opt/kitfoxpay
sudo chown -R "$USER:$USER" /opt/kitfoxpay
cd /opt/kitfoxpay
git clone https://github.com/kitfoxai/kitfoxpay.git .
git checkout 862c11bbe5387ded9df5ccf7772ca03ff286f058
如果 GitHub 访问慢,可以用 Gitee 镜像:
git clone https://gitee.com/kitfoxai/kitfoxpay.git .
git checkout 862c11bbe5387ded9df5ccf7772ca03ff286f058
如果要使用 Jeepay 的 ALI_QR,KitfoxPay 需要把 Jeepay 返回的 qr.alipay.com 链接渲染成二维码,所以先把二维码依赖写入 package.json:
docker run --rm \
-v "$PWD:/workspace" \
-w /workspace \
node:20-alpine \
npm pkg set dependencies.qrcode='^1.5.4'
创建 Dockerfile:
cat > Dockerfile <<'EOF'
FROM node:20-alpine
WORKDIR /app
COPY package*.json ./
RUN npm install --omit=dev
COPY . .
EXPOSE 9219
CMD ["npm", "start"]
EOF
这里使用 node:20-alpine,固定了 Node 20 大版本,但仍然不是 digest 级别固定。KitfoxPay 仓库当前没有 package-lock.json,npm install 也会按依赖范围解析版本。生产环境建议先在测试环境生成并验证 package-lock.json,再构建镜像。
创建 KitfoxPay 配置
生成易支付密钥和管理后台密码:
EPAY_KEY=$(openssl rand -hex 24)
ADMIN_PASSWORD=$(openssl rand -base64 24)
echo "EPAY_KEY=$EPAY_KEY"
echo "ADMIN_PASSWORD=$ADMIN_PASSWORD"
创建 config.js:
cat > config.js <<'EOF'
module.exports = {
jeepay: {
baseUrl: 'http://host.docker.internal:9216',
mchNo: '替换成Jeepay商户号',
appId: '替换成Jeepay应用ID',
privateKey: '替换成Jeepay商户私钥'
},
epay: {
pid: 'newapi',
key: '替换成上一步生成的EPAY_KEY'
},
server: {
host: '0.0.0.0',
port: 9219,
siteDomain: 'http://<Ubuntu服务器IP>:9219'
},
admin: {
password: '替换成上一步生成的ADMIN_PASSWORD'
}
};
EOF
如果 KitfoxPay 和 Jeepay 在同一台 Ubuntu 机器上,且 KitfoxPay 运行在单独 Docker Compose 里,baseUrl 可以先用:
http://host.docker.internal:9216
下面的 Compose 会加上 host.docker.internal:host-gateway,让 Linux Docker 容器能访问宿主机上的 9216 端口。
siteDomain 要写 New-API 和 Jeepay 都能访问的地址。内网测试可以先写:
http://192.168.3.213:9219
如果 New-API 已经走公网域名和 HTTPS,KitfoxPay 也建议放到 HTTPS 域名后面,例如:
https://kitfoxpay.example.com
创建 KitfoxPay Compose
cat > compose.yaml <<'EOF'
services:
kitfoxpay:
build:
context: .
dockerfile: Dockerfile
image: kitfoxpay:862c11b
container_name: kitfoxpay
restart: unless-stopped
ports:
- "9219:9219"
volumes:
- ./config.js:/app/config.js
extra_hosts:
- "host.docker.internal:host-gateway"
EOF
启动:
docker compose up -d --build
docker compose ps
docker compose logs -f --tail=100
验证 KitfoxPay:
curl http://127.0.0.1:9219/api/health
正常会返回 JSON,并能看到 Jeepay 的 baseUrl、mchNo、appId 等配置摘要。
管理界面:
http://<Ubuntu服务器IP>:9219
config.js 挂载为可写文件,KitfoxPay 的 Web 管理界面保存配置时会写回这个文件。这个后台不要直接暴露到公网;如果必须公网访问,至少要放到 HTTPS 和访问控制后面,并使用强密码。
配置 New-API
登录 New-API 管理后台,在系统设置或支付设置中配置易支付参数。不同 New-API 版本界面名称可能略有差异,核心字段对应关系如下:
| New-API 字段 | 填写内容 |
|---|---|
| 易支付接口地址 / PayAddress / epay_url | http://<KitfoxPay地址>:9219 |
| 易支付商户 ID / EpayId / pid | newapi |
| 易支付商户密钥 / EpayKey / key | config.js 里的 epay.key |
| 自定义回调地址 / CustomCallbackAddress | New-API 对外访问地址,例如 https://k8s-ai.example.com |
| 支付方式 / PayMethods | type 使用 Jeepay 的 wayCode |
这里特别容易填错的是 CustomCallbackAddress。它必须是 New-API 自己的对外地址,不是 KitfoxPay 地址。例如 New-API 访问地址是:
https://ai.jihw.top
那么 CustomCallbackAddress 就填:
https://ai.jihw.top
不要填成:
http://<KitfoxPay地址>:9219
否则 New-API 创建订单时传给 KitfoxPay 的 notify_url 会变成 KitfoxPay 自己,支付成功后余额不会正确回写到 New-API。
支付方式示例:
[
{
"name": "支付宝扫码",
"icon": "SiAlipay",
"type": "ALI_QR"
}
]
这里的 ALI_QR 只是支付宝扫码示例。实际要填 Jeepay 里当前商户应用已经配置并启用的 wayCode。如果仍然使用 New-API 默认的 alipay、wxpay,KitfoxPay 会把它们原样传给 Jeepay,通常会导致 Jeepay 下单失败。
使用 ALI_QR 扫码支付
ALI_PC 适合浏览器跳转测试,Jeepay 会返回支付宝 PC 收银台地址。ALI_QR 则不同,Jeepay 返回的是 https://qr.alipay.com/... 这类扫码链接,这个链接应该生成二维码让用户用支付宝沙箱 App 扫码。如果 KitfoxPay 直接把浏览器重定向到这个链接,支付宝通常会落到类似下面的提示页:
https://render.alipay.com/p/yuyan/180020040001212700/?cid=wap_dc
所以使用 ALI_QR 时,要改 KitfoxPay 的 epay.js:引入 qrcode,并让 _generatePayForm 在 ALI_QR 时返回二维码 HTML,而不是自动跳转。
先在文件顶部增加:
const QRCode = require('qrcode');
再把生成表单的位置改成 await:
const formHtml = await this._generatePayForm(payUrl, epayParams);
然后把 _generatePayForm 改成异步函数。核心逻辑如下,非 ALI_QR 的支付方式继续保留原来的自动跳转逻辑:
async _generatePayForm(payUrl, params) {
if (!payUrl) {
return '';
}
const isQrPay = params.type === 'ALI_QR' || payUrl.includes('qr.alipay.com');
if (isQrPay) {
const qrDataUrl = await QRCode.toDataURL(payUrl, {
errorCorrectionLevel: 'M',
margin: 2,
width: 260
});
return `<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>支付宝扫码支付</title>
</head>
<body>
<h2>支付宝扫码支付</h2>
<p>请使用支付宝沙箱 App 扫码完成支付</p>
<img src="${qrDataUrl}" alt="支付宝支付二维码">
<p>${params.money || ''} 元</p>
<p>${params.out_trade_no || ''}</p>
<a href="${payUrl}">无法扫码时打开支付链接</a>
</body>
</html>`;
}
return `<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta http-equiv="refresh" content="0;url=${payUrl}">
<title>正在跳转到支付页面...</title>
</head>
<body>
<p>正在跳转到支付页面...</p>
<script>
window.location.href = ${JSON.stringify(payUrl)};
</script>
</body>
</html>`;
}
修改后重建 KitfoxPay:
cd /opt/kitfoxpay
docker compose up -d --build
docker compose logs --tail=100
再次从 New-API 发起充值时,如果支付方式是 ALI_QR,页面应显示二维码;如果是支付宝沙箱环境,要用支付宝开放平台提供的沙箱版支付宝 App 扫码。
默认情况下,扫码页不会在用户支付成功后自动跳转。原因是 ALI_QR 是“另一个设备扫码支付”:支付宝完成支付后走异步通知链路,浏览器里打开的二维码页不会天然收到这个结果。要自动跳回 New-API,需要让二维码页轮询 KitfoxPay 的订单状态,查到支付成功后再跳转到 New-API 传来的 return_url。
不要把 epay.key 写进浏览器页面里去调 api.php?act=order。更稳妥的做法是在 KitfoxPay 增加一个只查询订单状态的公开接口,例如在 index.js 里加:
app.get('/api/payment/status', async (req, res) => {
try {
const outTradeNo = req.query.out_trade_no || '';
const tradeNo = req.query.trade_no || '';
if (!outTradeNo && !tradeNo) {
return res.status(400).json({ code: -1, msg: 'missing order id', paid: false });
}
const order = await jeepay.queryOrder({
payOrderId: tradeNo,
mchOrderNo: outTradeNo
});
const state = String(order.state || '');
res.json({
code: 1,
msg: 'success',
paid: state === '2',
closed: ['3', '4', '6'].includes(state),
state,
trade_no: order.payOrderId || '',
out_trade_no: order.mchOrderNo || ''
});
} catch (error) {
res.json({ code: -1, msg: error.message || 'query failed', paid: false });
}
});
然后在 ALI_QR 的二维码 HTML 里增加轮询脚本:
<div id="pay-status">等待支付结果...</div>
<script>
(function () {
var orderNo = "${params.out_trade_no || ''}";
var returnUrl = "${params.return_url || ''}";
var attempts = 0;
async function checkPayment() {
attempts += 1;
try {
var query = new URLSearchParams({ out_trade_no: orderNo });
var response = await fetch('/api/payment/status?' + query.toString(), { cache: 'no-store' });
var result = await response.json();
if (result.paid) {
window.location.href = returnUrl || '/';
return;
}
if (result.closed) {
document.getElementById('pay-status').textContent = '订单已关闭,请重新创建订单';
return;
}
} catch (error) {
// 查询失败时继续轮询,避免临时网络问题中断支付流程。
}
if (attempts < 180) {
window.setTimeout(checkPayment, 3000);
}
}
if (orderNo) {
window.setTimeout(checkPayment, 3000);
}
})();
</script>
上面这段 HTML 是说明写法。实际放进 epay.js 模板字符串时,orderNo 和 returnUrl 建议用 JSON.stringify(params.out_trade_no || '')、JSON.stringify(params.return_url || '') 输出,避免引号或特殊字符破坏脚本。
如果 New-API 返回类似下面的错误:
{"code":-1,"msg":"Jeepay API 错误: 系统:java.io.IOException ... 504 Gateway Time-out"}
先看 KitfoxPay 日志里支付宝接口的 method。如果是 alipay.trade.precreate,并且 HTML 里出现 openapi-sandbox.dl.alipaydev.com、504 Gateway Time-out,说明 Jeepay 已经请求到了支付宝沙箱,但是支付宝沙箱网关临时超时。可以等待几十秒后重新创建订单;同时用下面命令确认服务器能访问沙箱网关:
curl -k -I --connect-timeout 10 --max-time 20 \
https://openapi-sandbox.dl.alipaydev.com/gateway.do
只要 ALI_PC 能正常下单,ALI_QR 偶发这个 504 通常不是 KitfoxPay 的签名或二维码渲染问题。
如果 New-API 是 HTTPS 站点,而 PayAddress 使用 http://<KitfoxPay地址>:9219,浏览器提交支付表单时可能会遇到 HTTP/HTTPS 混合内容限制或不安全表单提示。内网测试可以先接受;正式使用建议给 KitfoxPay 也配置 HTTPS 域名,然后把 PayAddress 改成 HTTPS 地址。
如果 New-API 部署在 Kubernetes,可以先从集群里测试它是否能访问 KitfoxPay:
KITFOXPAY_URL="http://192.168.3.213:9219"
kubectl -n new-api run kitfoxpay-test \
--rm -it --restart=Never \
--image=curlimages/curl:8.10.1 \
-- "$KITFOXPAY_URL/api/health"
如果 New-API 是多副本,修改支付配置后建议重启一次:
kubectl -n new-api rollout restart deploy/new-api
kubectl -n new-api rollout status deploy/new-api --timeout=300s
验证支付链路
- 在 New-API 前台用普通用户发起一笔小额充值。
- New-API 应跳转到 KitfoxPay,再由 KitfoxPay 创建 Jeepay 订单。
- 在 KitfoxPay 日志里查看下单和通知:
cd /opt/kitfoxpay
docker compose logs -f --tail=100
- 在 Jeepay 运营平台查看支付订单。
- 支付完成后,确认 New-API 用户余额增加。
如果 New-API 没有收到回调,优先检查三处地址:
- KitfoxPay
server.siteDomain是否是 Jeepay 能访问的地址。 - New-API
CustomCallbackAddress是否是 KitfoxPay 能访问的地址。 - 防火墙或 Ingress 是否允许
/api/payment/notify、/api/user/epay/notify、/api/subscription/epay/notify这些回调路径。
KitfoxPay 常用维护
cd /opt/kitfoxpay
docker compose ps
docker compose logs -f --tail=100
docker compose restart
docker compose down
docker compose up -d
备份配置:
cp config.js config.js.$(date +%F).bak
升级 KitfoxPay 前先备份 config.js,再在测试环境确认 New-API 支付、Jeepay 下单和异步通知都正常。
修改配置后重启
后端配置文件在后端仓库的 conf 目录下:
conf/payment/application.yml
conf/manager/application.yml
conf/merchant/application.yml
修改配置后重启对应服务:
docker compose restart payment
docker compose restart manager
docker compose restart merchant
如果改了 MQ 类型,不只要改 conf/*.yml,还要同步修改 docker-compose.yml 中的 MQ 服务。官方默认使用 RocketMQ。
常用维护命令
进入部署目录:
cd /opt/jeepay-open/jeepay
查看容器:
docker compose ps
查看日志:
docker compose logs -f --tail=100 payment
docker compose logs -f --tail=100 manager
docker compose logs -f --tail=100 merchant
重启单个服务:
docker compose restart payment
docker compose restart manager
docker compose restart merchant
停止全部服务:
docker compose stop
重新启动:
docker compose start
停止并删除容器、网络,但保留数据卷:
docker compose down
备份和恢复
Compose 使用 Docker named volume 保存 MySQL、Redis、RocketMQ 数据。重点要备份 MySQL。
备份 Jeepay 数据库:
cd /opt/jeepay-open/jeepay
docker exec jeepay-mysql mysqldump -uroot -prootroot jeepaydb > jeepaydb_$(date +%F).sql
恢复前先确认目标环境,避免覆盖已有数据:
cat jeepaydb_2026-06-22.sql | docker exec -i jeepay-mysql mysql -uroot -prootroot jeepaydb
这里使用的是官方 Compose 默认数据库密码 rootroot。如果你已经修改过密码,要同步替换命令里的密码。
卸载
停止并删除容器、网络,保留数据卷:
cd /opt/jeepay-open/jeepay
docker compose down
连同 Docker volume 一起删除:
docker compose down -v
down -v 会删除 MySQL、Redis、RocketMQ 等数据卷。执行前务必确认已经备份数据库。
如果还要删除源码目录:
sudo rm -rf /opt/jeepay-open
常见注意事项
前端目录找不到
如果启动时报错找不到 jeepay-ui,先确认目录结构:
find /opt/jeepay-open -maxdepth 2 -type d | sort
应该类似:
/opt/jeepay-open
├── jeepay
└── jeepay-ui
如果前端目录不在后端同级目录,编辑 /opt/jeepay-open/jeepay/.env:
UI_BASE_DIR=/实际存放前端仓库的父目录
注意这里填的是包含 jeepay-ui 的父目录,不是 jeepay-ui 目录本身。
后端镜像构建失败
如果出现找不到 JAR 的错误,通常是没有先打包后端:
cd /opt/jeepay-open/jeepay
mvn clean package -DskipTests
docker compose up -d --build
exec format error
如果构建后端镜像时报错:
exec /bin/sh: exec format error
一般是服务器 CPU 架构和基础镜像架构不匹配。例如宿主机是 x86_64,但后端 Dockerfile 默认使用的 swr.cn-south-1.myhuaweicloud.com/jeepay/eclipse-temurin:17-jre 实际拉到了 linux/arm64 镜像,构建时执行 /bin/sh 就会失败。
先确认宿主机架构和当前基础镜像架构:
uname -m
docker info --format '{{.Architecture}}'
docker pull swr.cn-south-1.myhuaweicloud.com/jeepay/eclipse-temurin:17-jre
docker image inspect swr.cn-south-1.myhuaweicloud.com/jeepay/eclipse-temurin:17-jre \
--format '{{.Os}}/{{.Architecture}}'
如果宿主机架构和基础镜像架构不一致,建议用 docker-compose.override.yml 覆盖有问题的镜像,不直接改官方 docker-compose.yml。下面这个覆盖文件做两件事:
- MySQL 改用 Docker Hub 官方
mysql:8.0多架构镜像。 - 三个后端服务的 JDK 基础镜像改用
eclipse-temurin:17-jre-jammy多架构镜像。
cat > docker-compose.override.yml <<'EOF'
services:
mysql:
image: mysql:8.0
payment:
build:
args:
BASE_IMAGE: eclipse-temurin:17-jre-jammy
manager:
build:
args:
BASE_IMAGE: eclipse-temurin:17-jre-jammy
merchant:
build:
args:
BASE_IMAGE: eclipse-temurin:17-jre-jammy
EOF
也可以把同样的内容手动写成 YAML:
services:
mysql:
image: mysql:8.0
payment:
build:
args:
BASE_IMAGE: eclipse-temurin:17-jre-jammy
manager:
build:
args:
BASE_IMAGE: eclipse-temurin:17-jre-jammy
merchant:
build:
args:
BASE_IMAGE: eclipse-temurin:17-jre-jammy
然后重新构建:
docker compose build --no-cache payment manager merchant
docker compose up -d --build
如果 MySQL 已经用错误架构镜像启动失败,并且是刚初始化的测试环境,可以删除失败容器和数据卷后再启动:
docker compose rm -sf mysql
docker volume rm jeepay_mysql
docker compose up -d
docker volume rm jeepay_mysql 会删除 MySQL 数据,只适合确认没有有效数据的新部署环境。
如果仍然有 RocketMQ、Redis 或前端镜像的架构问题,再看对应服务是否需要 platform: linux/amd64 或替换为支持 ARM64 的镜像。用 amd64 模拟运行可以解决一部分兼容问题,但性能和稳定性不如直接使用当前架构镜像。
端口被占用
检查端口占用:
sudo ss -lntp | grep -E '13306|6380|9876|10909|10911|10912|9216|9217|9218|9226|9227|9228'
如果宿主机已有 MySQL、Redis 或其他服务占用端口,可以修改 docker-compose.yml 左侧的宿主机端口。例如:
ports:
- "23306:3306"
冒号右侧是容器内端口,通常不要改;冒号左侧是宿主机端口,可以按需要调整。
默认密码风险
官方 Compose 默认包含这些测试密码:
- MySQL root 密码:
rootroot - MySQL 业务用户:
jeepay/jeepay - 运营平台:
jeepay/jeepay123 - 商户用户默认密码:
jeepay666
这些默认值只适合本地或内网测试。只要环境会被多人访问,至少要修改数据库密码、后台账号密码,并限制后台入口访问来源。