Files
integral-shop/DOCKER_DEPLOY.md
danaisuiyuan fb76270882 feat(deploy): 完整 Docker 部署方案 — 寄卖商城 + 积分商城
新增两步独立 Docker 部署方案(czleilei240 环境):

步骤一 寄卖商城(integral-resell)
- step1-integral/docker-compose.yml:redis(Alpine自建) + houtai(webman PHP8) + h5(Nginx)
- houtai.Dockerfile:PHP 8.0 + 阿里云镜像源 + webman.bin entrypoint
- h5.Dockerfile:Nginx + configs.js 环境变量动态重写
- redis.Dockerfile:Alpine + apk 构建,绕过 DockerHub 镜像源问题
- 宿主机 bind-mount:/www/wwwroot/leileiadmin.czchunfang.com(FTP可直接更新程序)

步骤二 积分商城(single-shop-22)
- step2-single-shop/docker-compose.yml:redis + admin-api + front-api + admin-web + h5
- Java Dockerfiles:OpenJDK 17 + --add-opens Spring Boot 2.2.6 兼容

公共配置
- nginx/:四个域名宝塔 Nginx 反代配置(HTTP→HTTPS 301、SSL 终止)
- scripts/:sync-to-server.sh / deploy-step1.sh / remote-up.sh
- DOCKER_DEPLOY.md:完整部署文档

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-17 17:24:08 +08:00

21 KiB
Raw Permalink Blame History

Docker 部署方案(寄卖商城 + 积分商城前后端)

本方案覆盖:

  • integral-resell积分商城Webman PHP 后端二进制 + H5 静态站
  • single-shop-22寄卖商城CRMEB Spring Boot 双 jar 后端 + Vue 管理后台 + uni-app H5
  • Redis:每个子栈独立容器(两套互不干扰)

不包含:MER-2.2_2601 多商户、Kafka 同步、MySQL使用 阿里云 RDS for MySQL)。


两步独立部署(推荐)

czleilei240 分支开始,两个商城各自独立部署,互不依赖。

步骤一 寄卖商城 步骤二 积分商城
项目 integral-resell single-shop-22
目录 deploy/docker/step1-integral/ deploy/docker/step2-single-shop/
服务 redis · integral-houtai · integral-h5 redis · single-admin-api · single-front-api · single-admin-web · single-h5
宿主机端口 18080 18081(管理后台) 18082(H5)
compose name resell-czleilei240 jifenmall-czleilei240
详细说明 README README

步骤一 — 寄卖商城integral-resell

cd deploy/docker/step1-integral
cp .env.example .env && cp houtai.env.example houtai.env
# 填写 .env 中的 REDIS_PASSWORD
# 填写 houtai.env 中的 DB_PASSWORD 和 REDIS_PASSWORD两者须一致
docker compose --env-file .env up -d --build

步骤二 — 积分商城single-shop-22

cd deploy/docker/step2-single-shop
cp .env.example .env
# 填写 RDS_PASSWORD、REDIS_PASSWORD
docker compose --env-file .env up -d --build
# Java 首次构建约 10-20 分钟,可用 logs -f 观察进度

下方章节描述的是历史上合并部署时的 docker-compose.ymldeploy/docker/docker-compose.yml),供参考。两步拆分方案已取代合并方案。


一、架构总览

flowchart LR
    user((用户)) -->|H5/管理后台| EdgeLB[(阿里云 SLB / Nginx)]

    subgraph Host [Docker 主机]
      direction TB

      subgraph integralStack [积分商城]
        integral_h5[integral-h5\nNginx :80]
        integral_houtai[integral-houtai\nwebman.bin :8787]
      end

      subgraph singleStack [寄卖商城]
        single_admin_web[single-admin-web\nNginx :80]
        single_h5[single-h5\nNginx :80]
        single_admin_api[single-admin-api\nminiao-admin :30032]
        single_front_api[single-front-api\nminiao-front :30031]
      end

      redis[(redis :6379)]
    end

    EdgeLB -- jf-h5.* --> single_h5
    EdgeLB -- jfadmin.* --> single_admin_web
    EdgeLB -- admin.* --> integral_h5

    integral_h5 -- /api/ --> integral_houtai
    single_admin_web -- /api/ --> single_admin_api
    single_h5 -- /api/ --> single_front_api

    integral_houtai --> redis
    single_admin_api --> redis
    single_front_api --> redis

    integral_houtai --> RDS[(阿里云 RDS MySQL)]
    single_admin_api --> RDS
    single_front_api --> RDS

服务清单

服务 镜像构建来源 容器内端口 默认宿主机端口 说明
redis 官方 redis:6.2-alpine 6379 6379 (可不暴露) 持久化 AOF挂卷 redis-data
integral-houtai integral-resell/houtai/ 8787 (不暴露) Webman 静态 ELF同容器写 runtime/public/upload/
integral-h5 integral-resell/h5/ 80 18080 服务静态站;/api/ 反代到 integral-houtai;启动时根据 env 重写 static/configs.js
single-admin-api single-shop-22/backend/crmeb-admin 30032 (不暴露) 多阶段 Maven 构建出 miao-admin-2.2.jar
single-front-api single-shop-22/backend/crmeb-front 30031 (不暴露) 多阶段 Maven 构建出 miao-front-2.2.jar
single-admin-web single-shop-22/backend-adminend 80 18081 多阶段 Node 构建 dist/api/ 反代到 single-admin-api
single-h5 single-shop-22/single_uniapp22miao 80 18082 多阶段 Node 构建 unpackage/dist/build/h5/api/ 反代到 single-front-api

域名/端口策略:建议在 docker 主机前再放一层 Nginx 或阿里云 SLB按域名分发到 18080/18081/18082下面的 compose 默认把这三个静态站暴露在宿主机不同端口。

共享资源 / 卷

卷 / 目录 容器内挂载点 用途
redis-data /data Redis AOF 持久化
integral-runtime /app/runtime Webman 运行时session、views 缓存等)
integral-upload /app/public/upload 积分商城上传图片
single-images /usr/local/crmeb/crmebimage 寄卖商城 imagePathadmin/front 两个 jar 共享
single-logs /app/log Spring Boot 日志(按需保留)

与外部资源的关系

资源 地址来源 说明
阿里云 RDS MySQL .envRDS_* RDS 白名单需放通宿主机出口 IP建议同地域 VPC
OSS可选 .envOSS_* 不配置时积分商城走本地 public/upload;寄卖商城用 admin 后台界面里配置
短信(可选) .envSMS_* 仅积分商城 .env 用到

二、目录布局

integral-shop/
├── DOCKER_DEPLOY.md                 ← 本文档
├── deploy/
│   └── docker/
│       ├── docker-compose.yml
│       ├── .env.example
│       ├── README.md                ← 一键启动说明(简版)
│       ├── redis/
│       │   └── redis.conf
│       ├── integral-resell/
│       │   ├── houtai.Dockerfile
│       │   ├── h5.Dockerfile
│       │   ├── nginx-h5.conf
│       │   ├── .env.template        ← Webman 后端运行时 .env 模板
│       │   └── docker-entrypoint-h5.sh   ← 启动时根据 env 改写 configs.js
│       └── single-shop/
│           ├── admin-api.Dockerfile
│           ├── front-api.Dockerfile
│           ├── admin-web.Dockerfile
│           ├── h5.Dockerfile
│           ├── application-docker.yml    ← Spring Boot docker profile
│           ├── nginx-admin-web.conf
│           └── nginx-h5.conf
├── integral-resell/                 ← 源码(不改动)
└── single-shop-22/                  ← 源码(不改动)

所有 Dockerfile / compose 都只读访问源码目录,不会修改它们。


三、配置与环境变量

复制一份 deploy/docker/.env.exampledeploy/docker/.env 并按下面表格修改。

变量 用途 示例
TZ 容器时区 Asia/Shanghai
RDS_HOST 阿里云 RDS 外网/内网地址 rm-bp1a178eq62lxba9xbo.mysql.rds.aliyuncs.com
RDS_PORT RDS 端口 3306
RDS_INTEGRAL_DB 积分商城数据库 yangtangyoupin
RDS_INTEGRAL_USER / RDS_INTEGRAL_PASS 积分商城账号 默认 yangtangyoupin / 来自原 sxsy80
RDS_SINGLE_DB 寄卖商城数据库(与积分共库) yangtangyoupin
RDS_SINGLE_USER / RDS_SINGLE_PASS 寄卖商城账号 同上
REDIS_PASSWORD 容器 Redis 密码 123456
REDIS_INTEGRAL_DB 积分商城使用的 Redis db 0
REDIS_SINGLE_ADMIN_DB 寄卖 admin Redis db 25
REDIS_SINGLE_FRONT_DB 寄卖 front Redis db 26
INTEGRAL_API_PUBLIC_URL H5 调用后端的对外 URL https://admin.example.com
INTEGRAL_IMG_PUBLIC_URL H5 引用图片的对外 URL https://admin.example.com
INTEGRAL_H5_PUBLIC_URL H5 自身对外 URL https://h5.example.com/
INTEGRAL_SN_ID configs.jssn_id 17533260260405
INTEGRAL_APP_STR configs.jsappStr与寄卖 APP_SECRET 必须一致 ZFyTNQTWEkCBczKzyUDJWE9Ecx260405
SINGLE_ADMIN_BASE_API 寄卖管理后台调用 API 的域名/路径 留空走同域 /api/ 即可
SINGLE_H5_DOMAIN uni-app H5 调用 API 的域名 留空走同域 /api/ 即可
SYNC_SOURCE_ID / SYNC_TARGET_MER_ID 多商户同步配置(无 MER 时留空) "" / 0

关键一致性:积分商城 configs.js#appStr ↔ 积分商城 Webman .env#APP_SECRET ↔ 寄卖商城 admin 后台中的 appStr 必须一致;否则双向调用会鉴权失败。


四、镜像构建策略

0. 基础镜像选型(与主机对齐)

服务 基础镜像 libc 选择理由
redis redis:6.2-alpine musl Redis 官方推荐,无 native 依赖
integral-houtai php:8.0-cli-bullseye (Debian 11) glibc 与宝塔 PHP 8.0.26 版本对齐;已装 pdo_mysql / redis / gd / imagick 等 webman 常用扩展
integral-h5 nginx:1.25-alpine musl 纯静态文件 + nginx无字体/native 依赖
single-admin-api / single-front-api 构建 maven:3.8.8-eclipse-temurin-17 (Debian) glibc 与部署环境 OpenJDK 17.0.x 对齐pom.xml source/target=1.8Java 17 编译器向下兼容
single-admin-api / single-front-api 运行 eclipse-temurin:17-jre-jammy (Ubuntu 22.04) glibc 匹配主机 openjdk 17.0.18Spring Boot 2.2.6 + Java 17 需额外 --add-opens JVM 参数(已写入 JAVA_OPTS预装 fonts-dejavu + fonts-wqy-zenhei
single-admin-web / single-h5 构建 node:16-alpine musl 仅打包 JS/CSS无 native 依赖
single-admin-web / single-h5 运行 nginx:1.25-alpine musl 同上

主机环境Debian-classLinux kernel 6.1.164/ x86_64 / Docker + BuildKit。 所有 --platform=linux/amd64 在主机上都是原生执行,无 QEMU 模拟;只有在 Apple Silicon 上本地 build 时才会走 QEMU。 Java 后端最终镜像在 glibc 上运行,与主机 OS 完全同源;这样可避免 Alpine + musl 时验证码 / 中文字体 / POI 个别场景的兼容性问题。

1. integral-houtaiPHP Webman 二进制)

  • 基础镜像:debian:bookworm-slimwebman.bin 为 ELF x86_64静态链接glibc 兼容)。
  • 直接拷贝 webman.binpublic/runtime/views 模板进镜像。
  • .env 不打进镜像,通过 docker-composedeploy/docker/integral-resell/.env.template 渲染后挂进 /app/.env
  • 启动命令:./webman.bin start -d业主指定的守护模式entrypoint 在后台 tail -F runtime/logs/*.log 把日志接到容器 stdout并监听主进程退出。收到 SIGTERM 时执行 ./webman.bin stop 优雅退出。

2. integral-h5静态站

  • 基础镜像:nginx:1.25-alpine
  • 直接拷贝 integral-resell/h5//usr/share/nginx/html/
  • docker-entrypoint-h5.sh 在启动时根据环境变量重写 static/configs.js:把 BASE_URL/IMG_URL/H5_URL/sn_id/appStr 替换为部署值,无需重新构建前端

3. single-admin-api / single-front-apiSpring Boot

  • 多阶段构建
    • 构建阶段:maven:3.8.8-eclipse-temurin-17mvn package -pl crmeb-admin -am -DskipTestsfront 同理。pom.xml 已配置 source/target=1.8Java 17 编译器向下兼容,产物字节码级别不变。
    • 运行阶段:eclipse-temurin:17-jre-jammyUbuntu 22.04 / glibc与部署环境 openjdk 17.0.18 对齐;预装 fontconfig + fonts-dejavu + fonts-wqy-zenhei
  • Java 17 兼容性Spring Boot 2.2.6 使用 cglib、Druid、Quartz 等大量反射Java 17 强模块封装会报 InaccessibleObjectException。已在 JAVA_OPTS 中加入 7 条 --add-opens,覆盖已知触发点(java.lang / reflect / util / io / math / sun.net.util / net)。若运行时出现新的 InaccessibleObjectException,按报错包名继续追加 --add-opens
  • 通过 --spring.profiles.active=docker + --spring.config.additional-location=file:/config/ 加载 application-docker.yml,所有 DB/Redis/端口参数从 .env 注入。
  • imagePath 指向 /usr/local/crmeb/crmebimage/(挂卷 single-images,两个 jar 共享)。

4. single-admin-webVue 管理后台)

  • 多阶段构建
    • 构建阶段:node:16-alpinenpm ci && npm run build:prodVUE_APP_BASE_API 设为空,走同域 /api/)。
    • 运行阶段:nginx:1.25-alpine/api/ 反代到 single-admin-api:30032
  • 若想直接复用源码里现成的 dist/可改用「fast」分支见 Dockerfile 注释)。

5. single-h5uni-app H5

  • 同样多阶段:node:16-alpinenpm install && npm run build:h5,再 nginx 服务。
  • config/app.jsdomain 硬编码,需在构建前注入:通过 ARG H5_API_DOMAIN 做字符串替换,或留空让同域生效(推荐)。

五、Spring Boot 接 RDS / Redis 的细节

寄卖商城原本通过 spring.profiles.active=byjyw149 / miao80 等加载不同 yml。Docker 部署用全新 profile docker

# deploy/docker/single-shop/application-docker.yml
spring:
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://${MYSQL_HOST}:${MYSQL_PORT:3306}/${MYSQL_DATABASE}?useUnicode=true&characterEncoding=utf8&serverTimezone=GMT%2B8&useSSL=false
    username: ${MYSQL_USERNAME}
    password: ${MYSQL_PASSWORD}
  redis:
    host: ${REDIS_HOST}
    port: ${REDIS_PORT:6379}
    password: ${REDIS_PASSWORD:}
    database: ${REDIS_DATABASE:0}

通过 docker-compose 注入:

MYSQL_HOST=${RDS_HOST}
MYSQL_DATABASE=${RDS_SINGLE_DB}
MYSQL_USERNAME=${RDS_SINGLE_USER}
MYSQL_PASSWORD=${RDS_SINGLE_PASS}
REDIS_HOST=redis
REDIS_PASSWORD=${REDIS_PASSWORD}
REDIS_DATABASE=${REDIS_SINGLE_ADMIN_DB}

数据库初始化:首次部署前请用 db/ 下的 SQL推荐 db/yangtangyoupin.sqldb/shop22-v2.sql 等)在 RDS 中初始化对应库;本方案不在容器中建库,避免误覆盖现网数据


六、首次部署步骤

# 1. 准备环境变量
cd integral-shop/deploy/docker
cp .env.example .env
vim .env                                    # 填入 RDS / Redis / 域名等

# 2. 准备积分商城 Webman .env容器运行时挂载
cp integral-resell/.env.template integral-resell/.env
vim integral-resell/.env                    # 至少配置 DB_*、APP_SECRET、SMS_*

# 3. 在阿里云 RDS 上提前导入数据
#    - 积分商城db/yangtangyoupin.sql
#    - 寄卖商城db/shop22-v2.sql / db/jjy153-mysql.sql (按实际版本)

# 4. 构建并启动
docker compose --env-file .env build
docker compose --env-file .env up -d

# 5. 健康检查
docker compose ps
docker compose logs -f single-admin-api    # 看到 "Started CrmebAdminApplication" 即成功
docker compose logs -f integral-houtai     # 看到 "Webman start success" 即成功
curl -I http://localhost:18080             # 积分商城 H5
curl -I http://localhost:18081             # 寄卖管理后台
curl -I http://localhost:18082             # 寄卖用户 H5

七、日常运维

场景 操作
拉取最新源码后重建 docker compose build --no-cache <service> 然后 docker compose up -d <service>
只重启某服务 docker compose restart single-admin-api
看日志 docker compose logs -f --tail 200 single-front-api
进入容器 docker compose exec single-admin-api sh
备份用户上传 docker run --rm -v integral-upload:/d -v $(pwd):/b alpine tar czf /b/upload.tgz -C /d .
备份寄卖商城图片 同上,卷名 single-images
切换到外部 Redis .envREDIS_HOST 改成外部地址,并在 compose 里把 redis 服务注释
切换到 Java 17 运行寄卖商城 eclipse-temurin:8-jre-alpine 改成 17-jre;本工程经验依旧建议 8

八、性能与资源建议

容器 CPU 内存(建议)
redis 0.2 256 MB
integral-houtai 0.51 256512 MBwebman 多 worker 时 ↑)
integral-h5 0.1 64 MB
single-admin-api 1 JVM -Xmx512m,容器 limit 768 MB
single-front-api 1 JVM -Xmx768m,容器 limit 1 GB
single-admin-web 0.1 64 MB
single-h5 0.1 64 MB

最低配宿主机:2 vCPU / 4 GB(建议 4 vCPU / 8 GB 起)。


九、上线检查清单

  • 阿里云 RDS 白名单已放通 Docker 主机出口 IP
  • RDS 中已导入对应库的 SQL账号/密码权限正确
  • .env 中无明文敏感信息提交到 git.gitignore
  • INTEGRAL_APP_STR 与寄卖商城 admin 后台 + Webman .env#APP_SECRET 三处一致
  • 域名 / SSL 在外层 Nginx 或阿里云 SLB 完成 443 卸载
  • OSS 与 SMS 等第三方密钥若启用,已写入对应位置
  • 备份策略RDS 自动备份 + integral-upload / single-images 卷定期 tar 备份

十、远端 116.62.83.240 一键部署

服务器已具备的环境(来自宝塔软件商店截图):

  • Docker节点管理 → Docker 已部署)
  • Nginx 1.28.1未使用,本方案的 Nginx 在容器内)
  • MySQL 5.7.44未使用,本方案走阿里云 RDS
  • Redis 8.0.5默认未使用,容器内自带 Redis想复用宿主 Redis 见下方"复用宿主 Redis"
  • PHP 8.0.26未使用webman 走静态二进制)
  • rsync 已安装、SSH root / A@123456

1. 本机一次性配置

cd deploy/docker/scripts
cp server.env.example server.env
$EDITOR server.env                # 默认已写好 116.62.83.240 / root / A@123456

强烈建议先用 SSH key 替代密码ssh-copy-id root@116.62.83.240 后把 server.env 里的 SSHPASS= 注释掉即可。脚本会自动切回 SSH key 通道。

2. 全量同步并启动

./sync-to-server.sh up

脚本流程:

  1. SSH 登录 116.62.83.240,确保 /root/integral-shop 目录存在;
  2. rsync 增量同步整个工程(自动排除 node_modules / target / .git / runtime/logs / MER-2.2_2601 等大目录);
  3. 在远端 cd /root/integral-shop/deploy/docker && docker compose build && docker compose up -d
  4. 输出 docker compose ps 结果。

首次会要求你先在远端把 .env / integral-resell/.env 改成真实值(如未做,运行下面这一步):

./bootstrap-remote-env.sh         # 在远端基于模板创建 .env再 ssh 上去填写

3. 日常运维(无需登录服务器)

./remote-up.sh ps                            # 服务状态
./remote-up.sh logs single-admin-api         # 跟随日志
./remote-up.sh restart single-front-api      # 重启某服务
./remote-up.sh build single-admin-web        # 只重建某镜像
./remote-up.sh exec single-admin-api sh      # 进容器
./remote-up.sh ssh                           # 直接登录服务器
./sync-to-server.sh up                       # 改了代码后再同步+重启

4. 端口规划与宝塔放行

宿主机暴露端口(来自 .env.example,可改):

端口 服务 用途
18080 integral-h5 积分商城 H5
18081 single-admin-web 寄卖管理后台
18082 single-h5 寄卖用户 H5
6379 redis (生产建议关闭)REDIS_HOST_PORT= 留空即不暴露

安全组 / 防火墙:阿里云安全组放通 18080-18082宝塔面板 → 安全 → 放行同样端口。强烈建议在前面再挂一层域名 + SSL(宝塔自带 Nginx 反代 / 阿里云 SLB / Cloudflare 都行)。

5. 复用宿主已有 Redis 8.0.5(可选)

若想节省一份 Redis直接用宿主机的 Redis

# 1) 远端编辑 deploy/docker/.env
REDIS_PASSWORD=宿主-Redis-的密码

# 2) 远端编辑 deploy/docker/docker-compose.yml
#    a. 注释掉 redis: 整个服务块(包括 healthcheck
#    b. single-admin-api / single-front-api 把 REDIS_HOST: redis 改成 172.17.0.1
#       docker bridge 网关;宝塔默认端口 6379先确保 Redis 监听 0.0.0.0 且防火墙放行 6379 to docker subnet
#    c. integral-resell/.env 把 REDIS_HOST=redis 同步改为 172.17.0.1

# 3) 同步重启
./sync-to-server.sh up

6. 阿里云 RDS 白名单

到 RDS 控制台 → 白名单 → 加入 116.62.83.240(如果 RDS 与 ECS 同 VPC 则用内网地址 + 内网白名单更优)。

7. 数据库初始化

# 本地把 SQL 上传到服务器(默认 db/ 已被 rsync 同步过去)
./remote-up.sh ssh
# 远端
mysql -h <RDS_HOST> -u <RDS_USER> -p<RDS_PASS> < /root/integral-shop/db/yangtangyoupin.sql
mysql -h <RDS_HOST> -u <RDS_USER> -p<RDS_PASS> < /root/integral-shop/db/shop22-v2.sql

也可以用宝塔自带的 phpMyAdmin 直接连 RDS 导入。


十一、各文件清单一览

参见 deploy/docker/ 下:

  • docker-compose.yml ← 编排入口
  • .env.example ← 环境变量模板
  • redis/redis.conf
  • integral-resell/houtai.Dockerfile
  • integral-resell/h5.Dockerfile
  • integral-resell/nginx-h5.conf
  • integral-resell/.env.template
  • integral-resell/docker-entrypoint-h5.sh
  • single-shop/admin-api.Dockerfile
  • single-shop/front-api.Dockerfile
  • single-shop/admin-web.Dockerfile
  • single-shop/h5.Dockerfile
  • single-shop/application-docker.yml
  • single-shop/nginx-admin-web.conf
  • single-shop/nginx-h5.conf
  • scripts/server.env.example ← 远端 SSH 配置模板
  • scripts/sync-to-server.sh ← rsync 增量同步 + 触发远端部署
  • scripts/remote-up.sh ← 远端 docker compose 操作up/build/restart/logs/ps/exec/ssh
  • scripts/bootstrap-remote-env.sh ← 首次在远端生成 .env 模板

每个文件都已生成可直接使用的版本。