# 生产环境部署
本文说明如何把平台部署到服务器上正式使用。
旧版安装包不再适用
早期文档介绍的 muyantech/installer 一体化安装包(Docker Swarm + GlusterFS)基于 JDK 11,无法运行 1.0 版本的后端(需要 Java 25),请不要再使用。
推荐的方式是:在服务器上用与 Docker 部署 相同的 Docker Compose 配置运行平台,前面再加一层带 HTTPS 的反向代理。
提示
如果您从 https://muyan.io 购买了系统,可以向我们的技术支持团队获取帮助。
# 目标读者
本系统的实施和运维人员。
# 前置条件
- 一台安装了 Docker 和 Docker Compose v2 的 Linux 服务器。
- 平台配置仓库
muyantech/platform的访问权限,以及服务器上可用的 GitHub SSH 密钥(见 Docker 部署)。 - 一个指向该服务器的域名和 HTTPS 证书,下文以
erp.example.com为例。
# 安装步骤
# 1. 获取配置并登录镜像仓库
git clone [email protected]:muyantech/platform.git
cd platform
cat token.txt | docker login -u muyantech --password-stdin
2
3
先不要启动,按下面的步骤改好配置再启动。
# 2. 设置 JWT_SECRET(必须)
JWT_SECRET 是登录令牌的签名密钥。不设置时后端使用镜像内置的默认值,这个值是公开的,拿到它就能伪造任意用户的登录令牌。公网部署必须设置。
在
platform目录下新建.env:echo "JWT_SECRET=$(openssl rand -hex 32)" >> .env1密钥至少 32 个字节(256 位)。太短时后端无法启动,日志中会出现
KeyLengthException: The secret length must be at least 256 bits。.env中保存的是密钥,不要提交到 git。platform仓库的.gitignore没有忽略.env,建议执行echo .env >> .git/info/exclude把它排除在本地 git 之外,避免git add .时误提交。.env不受 git 跟踪,git pull、git stash都不会改动它。在
docker-compose.yml的server服务environment中加一行,把变量传给后端容器:- JWT_SECRET=${JWT_SECRET:?请在 .env 中设置 JWT_SECRET}1:?的写法保证.env中没有设置时docker compose up直接报错,不会误用默认值。
修改 JWT_SECRET 后,之前签发的令牌全部失效,用户需要重新登录。
# 3. 修改数据库密码
在 docker-compose.yml 中把以下两处改成同一个强密码:
database服务的POSTGRES_PASSWORDserver服务的JDBC_DATABASE_PASSWORD
POSTGRES_PASSWORD 只在数据库首次初始化(runtime/database/data 为空)时生效。数据库已经初始化后再改密码,要先在数据库里执行 ALTER USER postgres PASSWORD '...',再改这两处配置。
同时修改 runtime/pgadmin/pgpass 中的密码(格式为 database:5432:application:postgres:<密码>),否则 pgAdmin 预置的数据库连接会认证失败。
pgAdmin 的登录密码 PGADMIN_DEFAULT_PASSWORD 也请一并修改。
# 4. 收紧对外端口
默认配置是为本机开发准备的,部署到服务器前请调整 docker-compose.yml:
- 关闭远程调试:删除
server服务ports中的5005:5005,并删除JAVA_OPTS里的-agentlib:jdwp=...参数。远程调试端口可以在服务器上执行任意代码,不能暴露到公网。 - pgAdmin 只监听本机:把
"5433:80"改为"127.0.0.1:5433:80",需要时通过 SSH 隧道访问;不需要时直接删掉pgadmin服务。 - 平台入口只监听本机:把
proxy服务的9080:80改为127.0.0.1:9080:80,由宿主机上的反向代理对外提供 HTTPS。
PostgreSQL(5432)、Redis(6379)、后端(8080)默认不映射到宿主机,保持不变即可。
GRAILS_ENV 请保持 docker-compose.yml 中的默认值 development,这是平台当前唯一经过验证的运行配置,不要在不了解影响的情况下修改。
# 5. 启动
docker compose up -d
docker compose ps # server 显示 healthy 即启动完成
2
启动后确认 JWT_SECRET 已经传进后端容器(只判断是否设置,不打印密钥):
docker compose exec server sh -c 'test -n "$JWT_SECRET" && echo "JWT_SECRET 已设置" || echo "JWT_SECRET 未设置"'
输出 JWT_SECRET 未设置 时,说明第 2 步没有生效,后端仍在使用公开的默认密钥,请检查 .env 和 docker-compose.yml 后重新执行 docker compose up -d。
后端日志中含有密钥
当前版本的后端镜像在启动时会先执行 printenv,把全部环境变量(包括 JDBC_DATABASE_PASSWORD、JWT_SECRET)写进容器日志。这是当前版本的问题。请注意:
- 不要把
docker compose logs server的输出原样贴到公开渠道、聊天群或工单里,后端每次启动都会在日志中输出一段环境变量(docker compose restart server之后日志中间也会再出现一段),需要提供日志时要删掉所有这些段落,或者只提供出错时间点附近的片段。 - 限制能执行
docker命令、能读取容器日志的服务器账号;如果把日志转发到了集中式日志系统,同样要限制访问权限。 - 怀疑日志外泄时,按第 2、3 步更换
JWT_SECRET和数据库密码。
# 6. 修改默认账号密码
用 [email protected] / password 登录,在 业务配置 > 用户 中修改所有默认用户的密码,不需要的示例用户([email protected]、[email protected])可以删除。默认账号列表见 Docker 部署。
# 配置 HTTPS 反向代理
在宿主机上用 nginx(或其他反向代理)终止 HTTPS,再转发到 127.0.0.1:9080。
# 宿主机 nginx 示例
server {
listen 443 ssl;
server_name erp.example.com;
ssl_certificate /etc/ssl/erp.example.com/fullchain.pem;
ssl_certificate_key /etc/ssl/erp.example.com/privkey.pem;
client_max_body_size 10M;
location / {
proxy_pass http://127.0.0.1:9080;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
Host 和 X-Forwarded-Proto 两个请求头必须传递。上传附件的大小上限是 10MB(后端 maxFileSize 为 10485760),代理的 client_max_body_size 不要小于这个值。
# 让平台识别 HTTPS
平台自带的 runtime/proxy/conf.d/default.conf 用 $scheme 生成后端地址。HTTPS 在外层终止时,容器内收到的是 http 请求,前端拿到的后端地址会是 http://erp.example.com/api,浏览器会因混合内容拒绝请求。
需要让它改用外层传入的 X-Forwarded-Proto:
在
default.conf开头(resolver一行之前)加入:map $http_x_forwarded_proto $external_scheme { default $scheme; https https; http http; }1
2
3
4
5把文件中所有
$scheme://替换为$external_scheme://:sed -i 's/\$scheme:\/\//$external_scheme:\/\//g' runtime/proxy/conf.d/default.conf1检查并重新加载:
docker compose exec proxy nginx -t docker compose exec proxy nginx -s reload curl -s -H 'X-Forwarded-Proto: https' -H 'Host: erp.example.com' http://127.0.0.1:9080/backendUrl # 应输出 https://erp.example.com/api1
2
3
4
# 备份
需要备份的数据:
| 内容 | 位置 | 说明 |
|---|---|---|
| 数据库 | database 容器 | 用 pg_dump 导出,见下方命令 |
| 上传的附件 | ./runtime/attachments | 附件使用本地存储时,文件都在这里 |
| 应用种子数据 | ./codes/data | 建议纳入自己的 git 仓库管理 |
| 部署配置 | docker-compose.yml、.env、runtime/proxy/conf.d | .env 中有密钥,注意保管 |
数据库备份与恢复:
# 备份(custom 格式,便于 pg_restore)
docker compose exec -T database pg_dump -U postgres -Fc application > backup_$(date +%F).dump
# 恢复到同名数据库(会覆盖现有数据,请先停止后端)
docker compose stop server
docker compose exec -T database pg_restore -U postgres -d application --clean --if-exists --no-owner < backup_2026-01-01.dump
docker compose start server
2
3
4
5
6
7
建议用 cron 每天执行备份,并把备份文件复制到另一台机器或对象存储。
# 升级
git pull && docker compose pull && docker compose up -d
本地改过的 docker-compose.yml、default.conf 在 git pull 时可能冲突,升级前先 git stash,拉取后 git stash pop 并检查差异。升级前请先备份数据库,并阅读 升级说明。
# 运维命令
# 查看容器状态
docker compose ps
# 查看后端日志
docker compose logs -f --tail 200 server
# 重启后端
docker compose restart server
# 查看运行中的镜像版本
docker compose images
# 进入数据库
docker compose exec database psql -U postgres -d application
2
3
4
5
6
7
8
9
10
11
12
13
14
← 💻 Dokku 部署 ⬆️ 升级说明 →