617 lines
21 KiB
Bash
Executable File
617 lines
21 KiB
Bash
Executable File
#!/usr/bin/env bash
|
||
set -euo pipefail
|
||
|
||
VERSION="0.1.0"
|
||
OUTPUT_DIR=""
|
||
SKIP_BUILD=0
|
||
SKIP_PULL=0
|
||
|
||
usage() {
|
||
cat <<'EOF'
|
||
Usage: ./scripts/package-offline-server.sh [options]
|
||
|
||
Options:
|
||
--version VERSION Image/package version, default: 0.1.0
|
||
--output-dir DIR Output package directory, default: ./dist/SimCAEServerDockerPackage
|
||
--skip-build Do not build simcae-update-server image
|
||
--skip-pull Do not pull MinIO images
|
||
-h, --help Show this help
|
||
EOF
|
||
}
|
||
|
||
while [[ $# -gt 0 ]]; do
|
||
case "$1" in
|
||
--version)
|
||
VERSION="${2:?--version requires a value}"
|
||
shift 2
|
||
;;
|
||
--output-dir)
|
||
OUTPUT_DIR="${2:?--output-dir requires a value}"
|
||
shift 2
|
||
;;
|
||
--skip-build)
|
||
SKIP_BUILD=1
|
||
shift
|
||
;;
|
||
--skip-pull)
|
||
SKIP_PULL=1
|
||
shift
|
||
;;
|
||
-h|--help)
|
||
usage
|
||
exit 0
|
||
;;
|
||
*)
|
||
echo "Unknown option: $1" >&2
|
||
usage >&2
|
||
exit 1
|
||
;;
|
||
esac
|
||
done
|
||
|
||
require_file() {
|
||
local path="$1"
|
||
local message="$2"
|
||
if [[ ! -e "$path" ]]; then
|
||
echo "$message" >&2
|
||
exit 1
|
||
fi
|
||
}
|
||
|
||
require_cmd() {
|
||
local name="$1"
|
||
if ! command -v "$name" >/dev/null 2>&1; then
|
||
echo "Required command is missing: $name" >&2
|
||
exit 1
|
||
fi
|
||
}
|
||
|
||
require_cmd docker
|
||
require_cmd tar
|
||
|
||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||
PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
|
||
|
||
if [[ -z "$OUTPUT_DIR" ]]; then
|
||
OUTPUT_DIR="$PROJECT_ROOT/dist/SimCAEServerDockerPackage"
|
||
fi
|
||
|
||
IMAGE_NAME="simcae-update-server:$VERSION"
|
||
MINIO_IMAGE="minio/minio:RELEASE.2025-04-22T22-12-26Z"
|
||
MC_IMAGE="minio/mc:RELEASE.2025-04-16T18-13-26Z"
|
||
PACKAGE_DIR="$OUTPUT_DIR"
|
||
IMAGES_DIR="$PACKAGE_DIR/images"
|
||
KEYS_DIR="$PACKAGE_DIR/keys"
|
||
TAR_FILE="$IMAGES_DIR/simcae-server-all-images_$VERSION.tar"
|
||
ARCHIVE_FILE="$PACKAGE_DIR.tar.gz"
|
||
|
||
require_file "$PROJECT_ROOT/Dockerfile" "Dockerfile is missing."
|
||
require_file "$PROJECT_ROOT/docker-compose.image.yml" "docker-compose.image.yml is missing."
|
||
require_file "$PROJECT_ROOT/.env.docker.example" ".env.docker.example is missing."
|
||
require_file "$PROJECT_ROOT/admin-ui/package.json" "admin-ui/package.json is missing."
|
||
require_file "$PROJECT_ROOT/keys/manifest_private_key.pem" "keys/manifest_private_key.pem is missing."
|
||
require_file "$PROJECT_ROOT/keys/manifest_public_key.pem" "keys/manifest_public_key.pem is missing."
|
||
|
||
if [[ "$SKIP_BUILD" -eq 0 ]]; then
|
||
docker build -t "$IMAGE_NAME" -f "$PROJECT_ROOT/Dockerfile" "$PROJECT_ROOT"
|
||
fi
|
||
|
||
if [[ "$SKIP_PULL" -eq 0 ]]; then
|
||
docker pull "$MINIO_IMAGE"
|
||
docker pull "$MC_IMAGE"
|
||
fi
|
||
|
||
rm -rf "$PACKAGE_DIR"
|
||
mkdir -p "$IMAGES_DIR" "$KEYS_DIR"
|
||
|
||
cp "$PROJECT_ROOT/docker-compose.image.yml" "$PACKAGE_DIR/docker-compose.yml"
|
||
cp "$PROJECT_ROOT/.env.docker.example" "$PACKAGE_DIR/.env.example"
|
||
cp "$PROJECT_ROOT/keys/manifest_private_key.pem" "$KEYS_DIR/manifest_private_key.pem"
|
||
cp "$PROJECT_ROOT/keys/manifest_public_key.pem" "$KEYS_DIR/manifest_public_key.pem"
|
||
|
||
cat > "$PACKAGE_DIR/README.md" <<'EOF_README'
|
||
# SimCAE 服务端 Docker 打包和部署指南
|
||
|
||
本文从“维护者打包”到“使用者部署”完整说明 SimCAE 服务端 Docker 包的交付流程。
|
||
|
||
服务端 Docker 包用于把 SimCAE 自动升级服务端部署到你的服务器。包里已经包含后端 API、pure-admin(Vue3 + Element Plus)管理后台、MinIO 对象存储、初始化工具、配置模板、签名密钥和 Docker 编排文件;目标服务器即使不能联网,也可以按本文完成部署。
|
||
|
||
如果你是维护者,要先按“一、维护者:生成 Docker 离线部署包”打包。如果你已经拿到 `SimCAEServerDockerPackage.tar.gz`,直接从“三、使用者:最小部署流程”开始。
|
||
|
||
## 先看这里:你要做哪件事
|
||
|
||
| 你的目标 | 直接看哪一节 |
|
||
| --- | --- |
|
||
| 从源码重新生成离线部署包 | 一、维护者:生成 Docker 离线部署包 |
|
||
| 了解交付包里有哪些文件 | 二、这个包里面有什么 |
|
||
| 在服务器上部署并启动 | 三、使用者:最小部署流程 |
|
||
| 修改 `.env` 配置 | 四、.env 配置怎么填 |
|
||
| 发布 Windows/Linux 客户端版本 | 六、发布新版本 |
|
||
| 查看日志、重启、备份、升级 | 七、常用命令 |
|
||
|
||
## 一、维护者:生成 Docker 离线部署包
|
||
|
||
在服务端源码所在机器上执行。通常这台机器是 Ubuntu,并且已经安装 Docker。
|
||
|
||
进入服务端源码目录:
|
||
|
||
```bash
|
||
cd update-server
|
||
```
|
||
|
||
执行打包脚本:
|
||
|
||
```bash
|
||
bash ./scripts/package-offline-server.sh \
|
||
--version __VERSION__ \
|
||
--output-dir ./dist/SimCAEServerDockerPackage
|
||
```
|
||
|
||
脚本会做这些事情:
|
||
|
||
```text
|
||
1. 构建 simcae-update-server:__VERSION__ 镜像。
|
||
2. 拉取 MinIO 和 MinIO Client 镜像。
|
||
3. 复制 docker-compose.yml、.env.example、签名密钥和部署说明。
|
||
4. 把 API、MinIO、MinIO Client 三个镜像保存到 images/simcae-server-all-images___VERSION__.tar。
|
||
5. 生成完整目录 dist/SimCAEServerDockerPackage/。
|
||
6. 生成最终交付压缩包 dist/SimCAEServerDockerPackage.tar.gz。
|
||
```
|
||
|
||
打包完成后,重点确认这两个输出:
|
||
|
||
```text
|
||
dist/SimCAEServerDockerPackage/
|
||
dist/SimCAEServerDockerPackage.tar.gz
|
||
```
|
||
|
||
通常只需要把下面这个文件发给部署人员或拷贝到目标服务器:
|
||
|
||
```text
|
||
dist/SimCAEServerDockerPackage.tar.gz
|
||
```
|
||
|
||
如果只是重新打包已有镜像,可以使用:
|
||
|
||
```bash
|
||
bash ./scripts/package-offline-server.sh \
|
||
--version __VERSION__ \
|
||
--output-dir ./dist/SimCAEServerDockerPackage \
|
||
--skip-build
|
||
```
|
||
|
||
如果打包机器不能联网,但 MinIO 镜像已经提前存在本机,可以使用:
|
||
|
||
```bash
|
||
bash ./scripts/package-offline-server.sh \
|
||
--version __VERSION__ \
|
||
--output-dir ./dist/SimCAEServerDockerPackage \
|
||
--skip-pull
|
||
```
|
||
|
||
注意:`keys/manifest_private_key.pem` 会被放进部署包,用于服务端发布版本时签名 Manifest。这个私钥必须保护好,不要公开上传。
|
||
|
||
## 二、这个包里面有什么
|
||
|
||
解压后目录结构如下:
|
||
|
||
```text
|
||
SimCAEServerDockerPackage/
|
||
README.md 当前说明文档
|
||
docker-compose.yml 容器编排文件
|
||
.env.example 环境变量模板
|
||
load-images.sh 导入 Docker 镜像并创建 .env 的脚本
|
||
images/
|
||
simcae-server-all-images___VERSION__.tar Docker 镜像包,包含 api、minio、minio-init
|
||
keys/
|
||
manifest_private_key.pem 服务端 Manifest 签名私钥
|
||
manifest_public_key.pem 与客户端配套的验签公钥
|
||
```
|
||
|
||
这些文件的关系可以这样理解:
|
||
|
||
```text
|
||
images/*.tar 程序镜像包,相当于安装材料
|
||
docker-compose.yml 容器部署图纸,说明启动哪些服务、端口怎么映射、目录怎么挂载
|
||
.env 你的实际配置,第一次运行 load-images.sh 时由 .env.example 生成
|
||
keys/ 发布版本时用于签名 Manifest,客户端用对应公钥验签
|
||
runtime/ 启动后自动生成,保存服务端数据库、上传临时文件、崩溃报告等
|
||
minio_data/ 启动后自动生成,保存升级包文件
|
||
```
|
||
|
||
## 三、使用者:最小部署流程
|
||
|
||
先把 `SimCAEServerDockerPackage.tar.gz` 拷贝到要部署的 Ubuntu 服务器上,然后执行:
|
||
|
||
```bash
|
||
tar -xzf SimCAEServerDockerPackage.tar.gz
|
||
cd SimCAEServerDockerPackage
|
||
pwd
|
||
ls
|
||
```
|
||
|
||
你需要确认当前目录就是解压后的 `SimCAEServerDockerPackage` 目录,并且能看到:
|
||
|
||
```text
|
||
docker-compose.yml
|
||
.env.example
|
||
load-images.sh
|
||
images/
|
||
keys/
|
||
```
|
||
|
||
后面所有 `docker compose` 命令都要在这个目录执行,因为 `docker-compose.yml` 和 `.env` 都在这里。
|
||
|
||
继续在 `SimCAEServerDockerPackage` 目录执行:
|
||
|
||
```bash
|
||
bash ./load-images.sh
|
||
```
|
||
|
||
这个脚本会做两件事:
|
||
|
||
```text
|
||
1. docker load 导入 images/simcae-server-all-images___VERSION__.tar 里的镜像
|
||
2. 如果当前目录没有 .env,就从 .env.example 复制一份 .env
|
||
3. 自动创建 runtime/、minio_data/ 等运行目录,并尽量修正目录权限
|
||
```
|
||
|
||
然后修改 `.env`:
|
||
|
||
```bash
|
||
nano .env
|
||
```
|
||
|
||
最少只需要把 `MINIO_PUBLIC_ENDPOINT` 改成客户端能访问到的服务器地址:
|
||
|
||
```text
|
||
MINIO_PUBLIC_ENDPOINT=http://你的服务器IP:9000
|
||
```
|
||
|
||
例如服务器 IP 是 `192.168.229.128`:
|
||
|
||
```text
|
||
MINIO_PUBLIC_ENDPOINT=http://192.168.229.128:9000
|
||
```
|
||
|
||
启动服务:
|
||
|
||
```bash
|
||
docker compose up -d
|
||
```
|
||
|
||
查看状态和后端日志:
|
||
|
||
```bash
|
||
docker compose ps
|
||
docker compose logs -f api
|
||
```
|
||
|
||
浏览器访问:
|
||
|
||
```text
|
||
后台/API: http://你的服务器IP:8000/
|
||
MinIO 控制台: http://你的服务器IP:9001/
|
||
```
|
||
|
||
如果服务器开启防火墙,至少放行:
|
||
|
||
```text
|
||
8000 后台/API
|
||
9000 客户端下载升级文件
|
||
9001 MinIO 控制台,可选
|
||
```
|
||
|
||
## 四、.env 配置怎么填
|
||
|
||
`.env.example` 里已经给了一组能直接试跑的默认值。下面按重要程度说明。
|
||
|
||
### 必须确认或修改
|
||
|
||
| 字段 | 是否必填 | 默认能否直接用 | 怎么填 |
|
||
| --- | --- | --- | --- |
|
||
| `MINIO_PUBLIC_ENDPOINT` | 必填 | 不能直接用于正式环境 | 改成客户端能访问到的 MinIO 地址,格式是 `http://服务器IP:9000`。客户端会用这个地址下载升级文件。 |
|
||
| `SERVER_PORT` | 必填 | 可以 | 后台/API 端口,默认 `8000`。如果服务器 8000 被占用,可以改成其他端口。 |
|
||
| `PUBLIC_API_BASE_URL` | 可不填 | 可以 | 管理页生成 qrc 服务端配置 `server_config.json` 时使用的后端 API 地址。不填时自动使用当前访问后台的地址;如果经过域名、反向代理或端口映射,建议填成客户端实际能访问的地址,例如 `http://服务器IP:8000`。 |
|
||
| `RELEASE_MAIN_EXECUTABLE` | 必填 | SimCAE 默认可以 | 发布包里主程序的相对路径。Windows 示例:`bin/SimCAE.exe`;Linux 示例:`bin/SimCAE`。 |
|
||
| `CLIENT_API_TOKEN` | 必填 | 可以 | 客户端访问服务端 API 的令牌。必须和客户端 `config/app_config.json` 里的 `client_token` 完全一致。 |
|
||
| `ADMIN_USERNAME` / `ADMIN_PASSWORD` | 必填 | 可以 | 管理后台初始用户名和密码。首次启动且数据库里没有管理员用户时,会自动创建这个账号。网页登录时输入这组账号密码。 |
|
||
| `ADMIN_JWT_SECRET` | 必填 | 可以 | 管理后台 JWT 签名密钥。正式部署建议改成随机长字符串,并长期保持不变;改掉后旧登录 token 会失效。 |
|
||
| `ADMIN_TOKEN` | 必填 | 可以 | 服务端兜底令牌。管理后台不再用它直接登录;它仍用于 `ADMIN_JWT_SECRET` 未设置时的默认签名密钥,以及 `CRASH_ADMIN_TOKEN` 为空时的崩溃报告管理兜底令牌。 |
|
||
| `LICENSE_KEY_ENCRYPTION_SECRET` | 必填 | 可以 | 后台授权列表显示 License Key 时使用的加密密钥。正式部署建议修改,并且部署后长期保持不变;如果后续改掉它,旧 License 仍可用于客户端校验,但后台无法再显示旧 License Key 原文。 |
|
||
| `MINIO_ACCESS_KEY` | 必填 | 可以 | MinIO 用户名。默认可试跑,正式环境建议改。 |
|
||
| `MINIO_SECRET_KEY` | 必填 | 可以 | MinIO 密码。默认可试跑,正式环境建议改。 |
|
||
|
||
### 通常不用改
|
||
|
||
| 字段 | 作用 | 默认值说明 |
|
||
| --- | --- | --- |
|
||
| `SIMCAE_UPDATE_SERVER_IMAGE` | API 镜像名称 | 打包脚本会自动写成当前版本,例如 `simcae-update-server:__VERSION__`。 |
|
||
| `APP_UID` / `APP_GID` | API 容器写入 `runtime/` 时使用的用户 ID | `load-images.sh` 会尽量自动改成当前服务器用户。遇到权限问题时再检查。 |
|
||
| `SERVICE_TITLE` | 管理后台标题 | 默认 `SimCAE Update Service`。 |
|
||
| `CORS_ALLOW_ORIGINS` | 跨域来源 | 内网部署保持 `*` 即可。 |
|
||
| `TARGET_PLATFORM` / `TARGET_ARCH` | 发布包目标平台 | Windows x64 填 `windows` / `x64`;Linux x64 填 `linux` / `x64`。 |
|
||
| `SIGNING_KEY_ID` | Manifest 签名密钥编号 | 默认 `manifest-key-v1`。只有更换签名体系时才需要改。 |
|
||
| `MINIO_API_PORT` | MinIO 文件下载端口 | 默认 `9000`。客户端下载升级文件要能访问这个端口。 |
|
||
| `MINIO_CONSOLE_PORT` | MinIO 控制台端口 | 默认 `9001`。不需要控制台时可以不开放到外部。 |
|
||
| `MINIO_BUCKET` | MinIO 存储桶名 | 默认 `updates`。 |
|
||
| `SIGN_EXPIRE_MIN` | 升级文件下载链接有效期 | 默认 `60` 分钟。 |
|
||
| `MINIO_CONNECT_TIMEOUT_SEC` / `MINIO_READ_TIMEOUT_SEC` / `MINIO_RETRY_TOTAL` / `MINIO_HEALTH_TIMEOUT_SEC` | MinIO 连接超时与重试 | 默认适合内网部署。 |
|
||
|
||
### 发布保护参数
|
||
|
||
这些字段用于防止上传超大目录导致服务器磁盘、内存压力过大。默认一般不用改。
|
||
|
||
| 字段 | 作用 | 默认值 |
|
||
| --- | --- | --- |
|
||
| `PUBLISH_MAX_REQUEST_MB` | 单次发布请求最大大小,单位 MB | `4096` |
|
||
| `PUBLISH_MAX_FILES` | 单次发布最多文件数 | `20000` |
|
||
| `PUBLISH_MAX_FIELDS` | 表单字段数上限,通常要大于文件数 | `20100` |
|
||
| `UPLOAD_SPACE_RESERVE_MB` | 上传时额外保留的磁盘空间,单位 MB | `256` |
|
||
|
||
如果正式发布目录超过 4GB,可以在确认服务器磁盘空间足够后调大 `PUBLISH_MAX_REQUEST_MB`。如果页面提示空间不足,优先清理旧版本、扩容磁盘,或把服务端部署到更大的数据盘。
|
||
|
||
### 崩溃报告接口参数
|
||
|
||
| 字段 | 是否必填 | 默认能否直接用 | 怎么填 |
|
||
| --- | --- | --- | --- |
|
||
| `CRASH_SERVICE_VERSION` | 必填 | 可以 | 崩溃报告接口版本,默认 `1.0.0`。 |
|
||
| `CRASH_REPORT_TOKEN` | 必填 | 可以 | 客户端上传崩溃报告时使用的令牌。正式环境建议改。 |
|
||
| `CRASH_SYMBOL_TOKEN` | 必填 | 可以 | 上传符号文件时使用的令牌。正式环境建议改。 |
|
||
| `CRASH_ADMIN_TOKEN` | 可不填 | 可以 | 崩溃报告管理令牌。不填时使用 `ADMIN_TOKEN`。 |
|
||
| `CRASH_METADATA_MAX_KB` | 必填 | 可以 | 崩溃报告 metadata 最大大小。 |
|
||
| `CRASH_MINIDUMP_MAX_MB` | 必填 | 可以 | minidump 最大大小。 |
|
||
| `CRASH_ATTACHMENTS_MAX_MB` | 必填 | 可以 | 附件最大大小。 |
|
||
| `CRASH_REQUEST_MAX_MB` | 必填 | 可以 | 崩溃报告完整请求最大大小。 |
|
||
| `CRASH_SYMBOLS_MAX_MB` | 必填 | 可以 | 符号文件最大大小。 |
|
||
|
||
## 五、客户端配置要同步哪些值
|
||
|
||
推荐直接使用后台页面生成:
|
||
|
||
```text
|
||
1. 登录后台
|
||
2. 选择应用和渠道
|
||
3. 如需预置授权,先创建或选择一个 License,页面会自动把可查看的 License 填入“客户端配置生成”
|
||
4. 打开“客户端配置生成”
|
||
5. 点击“生成配套配置”
|
||
6. 点击“复制配置”,粘贴到客户端 `bin/config/app_config.json`
|
||
7. 点击“复制 qrc 配置”,粘贴到客户端源码 `config/server_config.json`
|
||
8. 重新编译 Launcher / Updater / Bootstrap,让 `api_base_url` 通过 qrc 编进程序
|
||
```
|
||
|
||
客户端 `config/app_config.json` 至少要和服务端保持这个值一致:
|
||
|
||
```json
|
||
{
|
||
"client_token": "和服务端 CLIENT_API_TOKEN 一样"
|
||
}
|
||
```
|
||
|
||
如果服务端 `.env` 里保持默认:
|
||
|
||
```text
|
||
CLIENT_API_TOKEN=SimCAEClientToken2026
|
||
```
|
||
|
||
客户端就填:
|
||
|
||
```json
|
||
"client_token": "SimCAEClientToken2026"
|
||
```
|
||
|
||
`api_base_url` 是后端 API 地址,走 `SERVER_PORT`,不是 MinIO 地址。它现在位于客户端源码 `config/server_config.json`,并通过 qrc 编译进程序,不再写入客户端 `app_config.json` 或注册表。
|
||
|
||
## 六、发布新版本
|
||
|
||
进入后台后,“发布新版本”支持两种方式:
|
||
|
||
```text
|
||
1. 选择软件发布根目录,例如 SimCAE 目录。Windows 目录内应包含 bin/SimCAE.exe;Linux 目录内应包含 bin/SimCAE
|
||
2. 上传压缩发布包,支持 zip、tar.gz、tgz、tar.bz2、tbz2、rar
|
||
```
|
||
|
||
点击“发布版本”后,浏览器会先把文件上传到服务端。上传完成后,服务端会创建后台发布任务,继续执行解压、Manifest 校验、数据库写入和 MinIO 上传;管理页面会轮询并显示任务状态。这样可以减少大版本发布时长时间占用同一个 HTTP 请求的问题。
|
||
|
||
压缩发布包上传到服务器后,服务端会先解压,再校验是否包含 `.env` 中 `RELEASE_MAIN_EXECUTABLE` 指定的主程序路径。Windows 默认是:
|
||
|
||
```text
|
||
RELEASE_MAIN_EXECUTABLE=bin/SimCAE.exe
|
||
```
|
||
|
||
Linux 客户端部署时建议改成:
|
||
|
||
```text
|
||
TARGET_PLATFORM=linux
|
||
RELEASE_MAIN_EXECUTABLE=bin/SimCAE
|
||
CLIENT_MAIN_EXECUTABLE=SimCAE
|
||
CLIENT_LAUNCHER_EXECUTABLE=Launcher
|
||
CLIENT_UPDATER_EXECUTABLE=Updater
|
||
CLIENT_BOOTSTRAP_EXECUTABLE=Bootstrap
|
||
```
|
||
|
||
`.rar` 需要服务器镜像内有 rar 解压工具。当前 Docker 镜像已内置 `bsdtar`;如果某些 rar 变体仍然解压失败,请改用 zip/tar.gz/tar.bz2,或在服务器镜像中补充 `unrar`/`7z`。
|
||
|
||
## 七、常用命令
|
||
|
||
确认你仍然在 `SimCAEServerDockerPackage` 目录:
|
||
|
||
```bash
|
||
pwd
|
||
```
|
||
|
||
启动:
|
||
|
||
```bash
|
||
docker compose up -d
|
||
```
|
||
|
||
查看状态:
|
||
|
||
```bash
|
||
docker compose ps
|
||
```
|
||
|
||
查看后端日志:
|
||
|
||
```bash
|
||
docker compose logs -f api
|
||
```
|
||
|
||
查看所有容器日志:
|
||
|
||
```bash
|
||
docker compose logs -f
|
||
```
|
||
|
||
重启后端:
|
||
|
||
```bash
|
||
docker compose restart api
|
||
```
|
||
|
||
停止服务:
|
||
|
||
```bash
|
||
docker compose down
|
||
```
|
||
|
||
如果提示 `docker: 'compose' is not a docker command`,说明服务器没有安装 Docker Compose plugin,需要先安装它。
|
||
|
||
## 八、数据、备份和迁移
|
||
|
||
运行后会生成这些目录或文件:
|
||
|
||
```text
|
||
.env 当前服务器实际配置
|
||
runtime/ 服务端数据库、上传临时目录、崩溃报告等
|
||
minio_data/ MinIO 对象数据,也就是上传后的升级文件
|
||
keys/ Manifest 签名密钥
|
||
```
|
||
|
||
备份或迁移正式环境时,重点备份:
|
||
|
||
```text
|
||
.env
|
||
runtime/
|
||
minio_data/
|
||
keys/
|
||
docker-compose.yml
|
||
```
|
||
|
||
不要只备份容器。容器可以由镜像重新创建,真正重要的数据在上面这些挂载目录里。
|
||
|
||
## 九、常见问题
|
||
|
||
### 启动后看不到后端日志
|
||
|
||
`docker compose up -d` 是后台启动,不会持续打印日志。用下面命令看后端日志:
|
||
|
||
```bash
|
||
docker compose logs -f api
|
||
```
|
||
|
||
### API 容器反复重启,提示 Permission denied: '/data/uploads'
|
||
|
||
这是 `runtime/` 目录权限不对。进入 `SimCAEServerDockerPackage` 目录后执行:
|
||
|
||
```bash
|
||
docker compose down
|
||
mkdir -p runtime/uploads runtime/upload_spool runtime/crash_storage
|
||
sudo chown -R $(id -u):$(id -g) runtime
|
||
docker compose up -d
|
||
```
|
||
|
||
### 网页能打开,但客户端提示令牌校验失败
|
||
|
||
检查客户端 `config/app_config.json`:
|
||
|
||
```json
|
||
"client_token": "..."
|
||
```
|
||
|
||
必须和服务端 `.env`:
|
||
|
||
```text
|
||
CLIENT_API_TOKEN=...
|
||
```
|
||
|
||
完全一致。
|
||
|
||
### 客户端能连 API,但下载升级文件失败
|
||
|
||
检查 `.env`:
|
||
|
||
```text
|
||
MINIO_PUBLIC_ENDPOINT=http://你的服务器IP:9000
|
||
```
|
||
|
||
这个地址必须从客户端能访问。还要确认服务器防火墙放行了 `9000` 端口。
|
||
|
||
## 十、安全提醒
|
||
|
||
`keys/manifest_private_key.pem` 是服务端签 Manifest 的私钥,必须保护好。客户端 SDK 里的 `manifest_public_key.pem` 必须和这个私钥配套,否则客户端会 Manifest 验签失败。
|
||
|
||
默认用户名、默认密码、默认 token 和默认 MinIO 密码可以直接试跑。正式部署建议改掉,避免多个环境共用同一套公开示例值。
|
||
EOF_README
|
||
|
||
python3 - "$PACKAGE_DIR/README.md" "$VERSION" <<'PYREADME'
|
||
from pathlib import Path
|
||
import sys
|
||
path = Path(sys.argv[1])
|
||
version = sys.argv[2]
|
||
text = path.read_text(encoding='utf-8').replace('__VERSION__', version)
|
||
path.write_text(text, encoding='utf-8')
|
||
PYREADME
|
||
|
||
cat > "$PACKAGE_DIR/load-images.sh" <<EOF
|
||
#!/usr/bin/env bash
|
||
set -euo pipefail
|
||
|
||
docker load -i ./images/simcae-server-all-images_$VERSION.tar
|
||
if [[ ! -f .env ]]; then
|
||
cp .env.example .env
|
||
sed -i "s/^APP_UID=.*/APP_UID=\$(id -u)/" .env
|
||
sed -i "s/^APP_GID=.*/APP_GID=\$(id -g)/" .env
|
||
echo "Created .env from .env.example. Edit .env before starting services."
|
||
else
|
||
echo ".env already exists. Keeping existing file."
|
||
fi
|
||
|
||
APP_UID_VALUE="\$(grep -E '^APP_UID=' .env | tail -n 1 | cut -d= -f2-)"
|
||
APP_GID_VALUE="\$(grep -E '^APP_GID=' .env | tail -n 1 | cut -d= -f2-)"
|
||
APP_UID_VALUE="\${APP_UID_VALUE:-\$(id -u)}"
|
||
APP_GID_VALUE="\${APP_GID_VALUE:-\$(id -g)}"
|
||
|
||
mkdir -p ./runtime/uploads ./runtime/upload_spool ./runtime/crash_storage ./minio_data
|
||
|
||
if [[ -w ./runtime ]]; then
|
||
chown -R "\$APP_UID_VALUE:\$APP_GID_VALUE" ./runtime 2>/dev/null || true
|
||
else
|
||
echo "Warning: ./runtime is not writable by the current user."
|
||
echo "Run: sudo chown -R \$APP_UID_VALUE:\$APP_GID_VALUE ./runtime"
|
||
fi
|
||
|
||
echo "Next: edit .env, then run: docker compose up -d"
|
||
EOF
|
||
chmod +x "$PACKAGE_DIR/load-images.sh"
|
||
|
||
python3 - "$PACKAGE_DIR/.env.example" "$IMAGE_NAME" <<'PYENV'
|
||
from pathlib import Path
|
||
import sys
|
||
path = Path(sys.argv[1])
|
||
image = sys.argv[2]
|
||
text = path.read_text(encoding='utf-8')
|
||
text = text.replace('SIMCAE_UPDATE_SERVER_IMAGE=simcae-update-server:0.1.0', f'SIMCAE_UPDATE_SERVER_IMAGE={image}')
|
||
path.write_text(text, encoding='utf-8')
|
||
PYENV
|
||
|
||
docker save -o "$TAR_FILE" "$IMAGE_NAME" "$MINIO_IMAGE" "$MC_IMAGE"
|
||
|
||
rm -f "$ARCHIVE_FILE"
|
||
tar -czf "$ARCHIVE_FILE" -C "$(dirname "$PACKAGE_DIR")" "$(basename "$PACKAGE_DIR")"
|
||
|
||
echo "Offline package directory: $PACKAGE_DIR"
|
||
echo "Offline package archive: $ARCHIVE_FILE"
|
||
echo "Images tar: $TAR_FILE"
|