jeepay Docker & Self-Hosted Deployment

GitHub

Jeepay是一套适合互联网企业使用的开源支付系统,支持多渠道服务商和普通商户模式。已对接微信支付,支付宝,云闪付官方接口,支持聚合码支付。

6,465 stars Java Java 14 files · ~15,944 tokens #jeepay#xxpay
RAW Compose
1. Pull Image (DOCKERHUB) docker pull library/${ROCKETMQ_IMAGE
2. Docker Run (1-Click Launch) docker run -d --name jeepay -p 1:1 --restart always ${ROCKETMQ_IMAGE:-swr.cn-south-1.myhuaweicloud.com/jeepay/rocketmq:5.3.1}
3. Podman Run podman run -d --name jeepay -p 1:1 --restart always ${ROCKETMQ_IMAGE:-swr.cn-south-1.myhuaweicloud.com/jeepay/rocketmq:5.3.1}
4. Skopeo Inspect (Zero-Pull Manifest) skopeo inspect docker://docker.io/library/${ROCKETMQ_IMAGE:-swr.cn-south-1.myhuaweicloud.com/jeepay/rocketmq
5. ORAS Pull (OCI Artifact) oras pull ${ROCKETMQ_IMAGE:-swr.cn-south-1.myhuaweicloud.com/jeepay/rocketmq:5.3.1}
6. Compose Deployment docker compose up -d
docker-compose.baota.yml
Download .yml
# 宝塔面板(BaoTa)"Docker 应用"专用 compose 文件
#
# 使用场景:
#   - 宝塔 UI 上架 jeepay 应用,用户点击"安装"即部署
#   - 与 docker-compose.yml(仓库自身的 Compose 部署)不同,宝塔场景下
#     用户不 git clone 源码,所有配置文件通过 jeepay-configs 这个 init
#     容器(alpine/git 镜像)从 git 拉下来再分发到宿主共享卷
#
# 镜像默认仓库:
#   所有业务镜像 + MySQL / Redis / RocketMQ / Nginx 默认走华为云 SWR 公开仓库
#   (swr.cn-south-1.myhuaweicloud.com/jeepay/*),由计全官方维护,国内直拉,
#   不依赖 Docker Hub 加速器。alpine/git 仍用 Docker Hub(体积 < 20MB,一次
#   性拉取)。想回 Docker Hub 上游镜像时,可通过下面的 *_IMAGE 环境变量覆盖。
#
# 环境变量(由宝塔 app 模板声明):
#   VERSION            业务镜像 tag(jeepay-manager/merchant/payment)
#   CONFIG_REF         配置源 git ref(建议与 VERSION 同版本,或 master)
#   UI_RELEASE         前端静态资源 release(默认 V3.0.0)
#   MYSQL_ROOT_PASSWORD MySQL root 密码(默认 jeepaydb123456),同时贯穿到
#                      jeepay-configs 的 sed 替换,保证 yml 里 datasource 密码一致
#   APP_PATH           宿主机部署根目录
#   HOST_IP            对外绑定 IP
#   WEB_HTTP_PORT1/2/3 对外端口(分别映射到 19216 / 19217 / 19218)
#   CPUS / MEMORY_LIMIT nginx 资源限制
#
# 可选环境变量(想改镜像源时覆盖,各自带合理默认值):
#   MYSQL_IMAGE / REDIS_IMAGE / ROCKETMQ_IMAGE / NGINX_IMAGE
#   MANAGER_IMAGE / MERCHANT_IMAGE / PAYMENT_IMAGE
#   JEEPAY_CONFIGS_IMAGE
#
# 首次安装后配置文件都在 ${APP_PATH}/jeepayhomes/jeepayConfigs/,用户可直接
# 编辑;jeepay-configs 用 cp -n 保护已存在文件不被覆盖;最新模板始终同步
# 到 ${APP_PATH}/jeepayhomes/jeepayConfigs/.latest/,升级时 diff 对比。

services:
  # jeepay 配置中心:一次性 init 容器
  # - 从 git 拉 ${CONFIG_REF} tag 的配置文件
  # - cp -n 铺到共享卷,已存在文件跳过(保护用户编辑)
  # - 最新模板同时刷到 .latest/,升级时 diff 对比
  jeepay-configs:
    image: ${JEEPAY_CONFIGS_IMAGE:-alpine/git:v2.45.2}
    container_name: jeepay-configs
    # alpine/git 的 ENTRYPOINT 默认是 git,清空后 command 才能直接 exec sh
    entrypoint: []
    environment:
      # 贯穿到 sed 里替换 yml 的 datasource password(默认 jeepaydb123456)
      MYSQL_ROOT_PASSWORD: "${MYSQL_ROOT_PASSWORD:-jeepaydb123456}"
    volumes:
      - ${APP_PATH}/jeepayhomes/:/jeepayhomes
    command:
      - sh
      - -c
      - |
        set -e
        rm -rf /tmp/jeepay-src
        git clone --branch ${CONFIG_REF:-master} --depth 1 https://gitee.com/jeequan/jeepay.git /tmp/jeepay-src

        mkdir -p /jeepayhomes/jeepayConfigs/db \
                 /jeepayhomes/jeepayConfigs/redis \
                 /jeepayhomes/jeepayConfigs/rocketmq \
                 /jeepayhomes/jeepayConfigs/service/manager \
                 /jeepayhomes/jeepayConfigs/service/merchant \
                 /jeepayhomes/jeepayConfigs/service/payment \
                 /jeepayhomes/jeepayConfigs/nginx/conf.d \
                 /jeepayhomes/jeepayConfigs/nginx/html

        cp -n /tmp/jeepay-src/docs/install/include/my.cnf             /jeepayhomes/jeepayConfigs/db/my.cnf                         || true
        cp -n /tmp/jeepay-src/docs/sql/init.sql                       /jeepayhomes/jeepayConfigs/db/init.sql                       || true
        cp -n /tmp/jeepay-src/docs/install/include/redis.conf         /jeepayhomes/jeepayConfigs/redis/redis.conf                  || true
        cp -n /tmp/jeepay-src/docker/rocketmq/broker/conf/broker.conf /jeepayhomes/jeepayConfigs/rocketmq/broker.conf              || true
        cp -n /tmp/jeepay-src/conf/manager/application.yml            /jeepayhomes/jeepayConfigs/service/manager/application.yml   || true
        cp -n /tmp/jeepay-src/conf/merchant/application.yml           /jeepayhomes/jeepayConfigs/service/merchant/application.yml  || true
        cp -n /tmp/jeepay-src/conf/payment/application.yml            /jeepayhomes/jeepayConfigs/service/payment/application.yml   || true

        # 上游 conf/*/application.yml 里 datasource 密码是占位 "rootroot"(和仓库
        # docker-compose.yml 的默认 MYSQL_ROOT_PASSWORD 一致),宝塔场景下 MySQL
        # 初始化密码由 MYSQL_ROOT_PASSWORD 变量控制(默认 jeepaydb123456),不改
        # 则 Access denied。用 grep 条件做幂等替换,只有还存在 "password: rootroot"
        # 才改,尊重用户后续自定义。$$ 是给 compose 的转义,防止 compose YAML 解析
        # 时把 shell 变量吞掉。
        for svc in manager merchant payment; do
            yml="/jeepayhomes/jeepayConfigs/service/$$svc/application.yml"
            if [ -f "$$yml" ] && grep -q "password: rootroot" "$$yml"; then
                sed -i "s|password: rootroot|password: $${MYSQL_ROOT_PASSWORD}|g" "$$yml"
                echo "$$yml: datasource password rewrote"
            fi
        done
        cp -n /tmp/jeepay-src/docs/install/include/nginx.conf         /jeepayhomes/jeepayConfigs/nginx/nginx.conf                  || true
        # nginx.conf 在 install.sh 场景下用 localhost:921x(nginx --net=host 可达),
        # 但 compose 场景下 nginx 在 bridge 网络,localhost 解析不到后端。只要还能
        # 找到 localhost:921x 就替换成 compose service 名;用户若已改过就不动。
        if grep -q "proxy_pass http://localhost:921" /jeepayhomes/jeepayConfigs/nginx/nginx.conf 2>/dev/null; then
            sed -i \
                -e 's|proxy_pass http://localhost:9216|proxy_pass http://jeepaypayment:9216|g' \
                -e 's|proxy_pass http://localhost:9217|proxy_pass http://jeepaymanager:9217|g' \
                -e 's|proxy_pass http://localhost:9218|proxy_pass http://jeepaymerchant:9218|g' \
                /jeepayhomes/jeepayConfigs/nginx/nginx.conf
            echo "nginx.conf: localhost proxy_pass rewrote to compose service names"
        fi

        rm -rf /jeepayhomes/jeepayConfigs/.latest
        mkdir -p /jeepayhomes/jeepayConfigs/.latest
        cp -r /tmp/jeepay-src/conf                                    /jeepayhomes/jeepayConfigs/.latest/conf
        cp -r /tmp/jeepay-src/docs/install/include                    /jeepayhomes/jeepayConfigs/.latest/include
        cp    /tmp/jeepay-src/docker/rocketmq/broker/conf/broker.conf /jeepayhomes/jeepayConfigs/.latest/broker.conf               || true
        cp    /tmp/jeepay-src/docs/sql/init.sql                       /jeepayhomes/jeepayConfigs/.latest/init.sql                  || true

        # 前端静态资源(jeepay-ui 已打包发布到 gitee release)。目标目录已存在则跳过,
        # 保护用户后续对 html/ 的改动(和 cp -n 同语义)
        if [ ! -f /jeepayhomes/jeepayConfigs/nginx/html/jeepaymanager/index.html ]; then
            echo "Downloading frontend html.tar.gz (release=${UI_RELEASE:-V3.0.0}) ..."
            wget -q -O /tmp/html.tar.gz \
                "https://gitee.com/jeequan/jeepay-ui/releases/download/${UI_RELEASE:-V3.0.0}/html.tar.gz"
            tar xzf /tmp/html.tar.gz -C /jeepayhomes/jeepayConfigs/nginx/html/
            rm -f /tmp/html.tar.gz
            echo "Frontend extracted to nginx/html/"
        else
            echo "Frontend already present, skip download"
        fi

        echo "jeepay-configs ready (user edits preserved; upstream templates in .latest/)"
    labels:
      createdBy: "bt_apps"
    networks:
      - baota_net

  # MySQL
  mysql:
    image: ${MYSQL_IMAGE:-swr.cn-south-1.myhuaweicloud.com/jeepay/mysql:8.0.25}
    container_name: mysql8
    hostname: mysql
    restart: always
    environment:
      LANG: C.UTF-8
      MYSQL_ROOT_PASSWORD: "${MYSQL_ROOT_PASSWORD:-jeepaydb123456}"
      MYSQL_DATABASE: "jeepaydb"
    depends_on:
      jeepay-configs:
        condition: service_completed_successfully
    volumes:
      - /etc/localtime:/etc/localtime:ro
      - ${APP_PATH}/jeepayhomes/mysql/log:/var/log/mysql
      - ${APP_PATH}/jeepayhomes/mysql/data:/var/lib/mysql
      - ${APP_PATH}/jeepayhomes/mysql/mysql-files:/var/lib/mysql-files
      - ${APP_PATH}/jeepayhomes/jeepayConfigs/db:/etc/mysql/conf.d
      - ${APP_PATH}/jeepayhomes/jeepayConfigs/db/init.sql:/docker-entrypoint-initdb.d/init.sql:ro
    healthcheck:
      test: ["CMD-SHELL", "mysqladmin ping -h localhost -uroot -p$${MYSQL_ROOT_PASSWORD}"]
      interval: 15s
      timeout: 10s
      retries: 10
      start_period: 60s
    labels:
      createdBy: "bt_apps"
    networks:
      - baota_net

  # Redis
  redis:
    image: ${REDIS_IMAGE:-swr.cn-south-1.myhuaweicloud.com/jeepay/redis:6.2.14}
    container_name: redis6
    hostname: redis
    restart: always
    depends_on:
      jeepay-configs:
        condition: service_completed_successfully
    volumes:
      - /etc/localtime:/etc/localtime:ro
      - ${APP_PATH}/jeepayhomes/jeepayConfigs/redis/redis.conf:/etc/redis/redis.conf
      - ${APP_PATH}/jeepayhomes/redis/data:/data
    command: redis-server /etc/redis/redis.conf
    healthcheck:
      test: ["CMD", "redis-cli", "ping"]
      interval: 10s
      timeout: 5s
      retries: 10
      start_period: 15s
    labels:
      createdBy: "bt_apps"
    networks:
      - baota_net

  # RocketMQ NameServer
  rocketmq-namesrv:
    image: ${ROCKETMQ_IMAGE:-swr.cn-south-1.myhuaweicloud.com/jeepay/rocketmq:5.3.1}
    platform: linux/amd64
    container_name: rocketmq-namesrv
    hostname: rocketmq-namesrv
    restart: always
    depends_on:
      jeepay-configs:
        condition: service_completed_successfully
    volumes:
      - /etc/localtime:/etc/localtime:ro
      - ${APP_PATH}/jeepayhomes/rocketmq/namesrv/logs:/home/rocketmq/logs
    environment:
      JAVA_OPT_EXT: "-Xms256m -Xmx256m -Xmn128m"
    command: sh mqnamesrv
    healthcheck:
      # rocketmq 镜像里 /bin/sh 是 dash,不支持 /dev/tcp,必须显式走 bash
      test: ["CMD", "bash", "-c", "echo > /dev/tcp/localhost/9876"]
      interval: 10s
      timeout: 5s
      retries: 10
      start_period: 30s
    labels:
      createdBy: "bt_apps"
    networks:
      - baota_net

  # RocketMQ Broker(brokerIP1 = 容器名,不依赖宿主网络布局)
  rocketmq-broker:
    image: ${ROCKETMQ_IMAGE:-swr.cn-south-1.myhuaweicloud.com/jeepay/rocketmq:5.3.1}
    platform: linux/amd64
    container_name: rocketmq-broker
    hostname: rocketmq-broker
    restart: always
    user: "0:0"
    depends_on:
      rocketmq-namesrv:
        condition: service_healthy
      jeepay-configs:
        condition: service_completed_successfully
    volumes:
      - /etc/localtime:/etc/localtime:ro
      - ${APP_PATH}/jeepayhomes/rocketmq/broker/logs:/home/rocketmq/logs
      - ${APP_PATH}/jeepayhomes/rocketmq/broker/store:/home/rocketmq/store
      - ${APP_PATH}/jeepayhomes/jeepayConfigs/rocketmq/broker.conf:/home/rocketmq/rocketmq-5.3.1/conf/broker.conf:ro
    environment:
      NAMESRV_ADDR: "rocketmq-namesrv:9876"
      JAVA_OPT_EXT: "-Xms512m -Xmx512m -Xmn256m"
    command: sh mqbroker -n rocketmq-namesrv:9876 -c /home/rocketmq/rocketmq-5.3.1/conf/broker.conf
    healthcheck:
      test: ["CMD", "bash", "-c", "echo > /dev/tcp/localhost/10911"]
      interval: 15s
      timeout: 5s
      retries: 15
      start_period: 90s
    labels:
      createdBy: "bt_apps"
    networks:
      - baota_net

  # jeepay 运营平台 API
  jeepay-manager:
    image: ${MANAGER_IMAGE:-swr.cn-south-1.myhuaweicloud.com/jeepay/jeepay-manager:${VERSION}}
    container_name: jeepaymanager
    restart: always
    depends_on:
      mysql:
        condition: service_healthy
      redis:
        condition: service_healthy
      rocketmq-broker:
        condition: service_healthy
      jeepay-configs:
        condition: service_completed_successfully
    volumes:
      - /etc/localtime:/etc/localtime:ro
      - ${APP_PATH}/jeepayhomes/service/logs:/jeepayhomes/service/logs
      - ${APP_PATH}/jeepayhomes/service/uploads:/jeepayhomes/service/uploads
      - ${APP_PATH}/jeepayhomes/jeepayConfigs/service/manager/application.yml:/jeepayhomes/service/app/application.yml
    healthcheck:
      test: ["CMD-SHELL", "curl -s -o /dev/null --max-time 3 http://127.0.0.1:9217 || exit 1"]
      interval: 15s
      timeout: 5s
      retries: 12
      start_period: 60s
    labels:
      createdBy: "bt_apps"
    networks:
      - baota_net

  # jeepay 商户平台 API
  jeepay-merchant:
    image: ${MERCHANT_IMAGE:-swr.cn-south-1.myhuaweicloud.com/jeepay/jeepay-merchant:${VERSION}}
    container_name: jeepaymerchant
    restart: always
    depends_on:
      mysql:
        condition: service_healthy
      redis:
        condition: service_healthy
      rocketmq-broker:
        condition: service_healthy
      jeepay-configs:
        condition: service_completed_successfully
    volumes:
      - /etc/localtime:/etc/localtime:ro
      - ${APP_PATH}/jeepayhomes/service/logs:/jeepayhomes/service/logs
      - ${APP_PATH}/jeepayhomes/service/uploads:/jeepayhomes/service/uploads
      - ${APP_PATH}/jeepayhomes/jeepayConfigs/service/merchant/application.yml:/jeepayhomes/service/app/application.yml
    healthcheck:
      test: ["CMD-SHELL", "curl -s -o /dev/null --max-time 3 http://127.0.0.1:9218 || exit 1"]
      interval: 15s
      timeout: 5s
      retries: 12
      start_period: 60s
    labels:
      createdBy: "bt_apps"
    networks:
      - baota_net

  # jeepay 支付网关 API
  jeepay-payment:
    image: ${PAYMENT_IMAGE:-swr.cn-south-1.myhuaweicloud.com/jeepay/jeepay-payment:${VERSION}}
    container_name: jeepaypayment
    restart: always
    depends_on:
      mysql:
        condition: service_healthy
      redis:
        condition: service_healthy
      rocketmq-broker:
        condition: service_healthy
      jeepay-configs:
        condition: service_completed_successfully
    volumes:
      - /etc/localtime:/etc/localtime:ro
      - ${APP_PATH}/jeepayhomes/service/logs:/jeepayhomes/service/logs
      - ${APP_PATH}/jeepayhomes/service/uploads:/jeepayhomes/service/uploads
      - ${APP_PATH}/jeepayhomes/jeepayConfigs/service/payment/application.yml:/jeepayhomes/service/app/application.yml
    healthcheck:
      test: ["CMD-SHELL", "curl -s -o /dev/null --max-time 3 http://127.0.0.1:9216 || exit 1"]
      interval: 15s
      timeout: 5s
      retries: 12
      start_period: 60s
    labels:
      createdBy: "bt_apps"
    networks:
      - baota_net

  # nginx 网关(对外映射 19216 / 19217 / 19218)
  BT_SERVICE_NAME6:
    image: ${NGINX_IMAGE:-swr.cn-south-1.myhuaweicloud.com/jeepay/nginx:1.18.0}
    container_name: nginx118
    restart: always
    deploy:
      resources:
        limits:
          cpus: ${CPUS}
          memory: ${MEMORY_LIMIT}
    depends_on:
      jeepay-payment:
        condition: service_healthy
      jeepay-manager:
        condition: service_healthy
      jeepay-merchant:
        condition: service_healthy
      jeepay-configs:
        condition: service_completed_successfully
    ports:
      - ${HOST_IP}:${WEB_HTTP_PORT1}:19216
      - ${HOST_IP}:${WEB_HTTP_PORT2}:19217
      - ${HOST_IP}:${WEB_HTTP_PORT3}:19218
    volumes:
      - /etc/localtime:/etc/localtime:ro
      - ${APP_PATH}/jeepayhomes/jeepayConfigs/nginx/nginx.conf:/etc/nginx/nginx.conf
      - ${APP_PATH}/jeepayhomes/jeepayConfigs/nginx/conf.d:/etc/nginx/conf.d
      - ${APP_PATH}/jeepayhomes/nginx/logs:/var/log/nginx
      - ${APP_PATH}/jeepayhomes/jeepayConfigs/nginx/html:/usr/share/nginx/html
    labels:
      createdBy: "bt_apps"
    networks:
      - baota_net

networks:
  baota_net:
    external: true