Add local-network deployment automation and tighten runtime defaults
This commit adds the first complete local-network deployment path for the project. It normalizes the runtime contract around a fixed container listener on 0.0.0.0:10000, binds the published compose port to 127.0.0.1, and keeps the image/build workflow aligned with the released container image. It also introduces an installation script, an nginx reverse-proxy template, and a safer SQLite backup flow based on sqlite3 .backup with retention and optional rclone upload support. Deployment-oriented configuration has been consolidated into .env.example, repository-local .env files are now ignored, and the deployment scripts are executable. In addition, the frontend mixed-content issue is fixed by switching the stylesheet reference to a root-relative static path, with tests updated to cover the regression. README guidance has been expanded to document the new install, nginx, backup, and restore conventions.
This commit is contained in:
@@ -138,6 +138,9 @@ Box
|
||||
├── scripts
|
||||
│ ├── backup_db.sh
|
||||
│ └── deploy.sh
|
||||
│ ├── install.sh
|
||||
│ └── nginx
|
||||
│ └── moving-helper.nginx.template
|
||||
├── tests
|
||||
├── .dockerignore
|
||||
├── .env.example
|
||||
@@ -152,12 +155,15 @@ Box
|
||||
|
||||
项目通过环境变量支持以下部署时真正需要关心的配置:
|
||||
|
||||
- `HOST`
|
||||
- `PORT`
|
||||
- `DATABASE_URL`
|
||||
- `HOST_DOMAIN`
|
||||
- `SSL_PATH`
|
||||
- `APP_DIR`
|
||||
- `BACKUP_DIR`
|
||||
- `BACKUP_REMOTE`
|
||||
- `APP_PORT`
|
||||
- `DATA_DIR`
|
||||
- `UID`
|
||||
- `GID`
|
||||
- `DATABASE_URL`
|
||||
- `COMPOSE_PROJECT_NAME`
|
||||
|
||||
推荐从示例文件开始:
|
||||
|
||||
@@ -168,20 +174,25 @@ cp .env.example .env
|
||||
默认值如下:
|
||||
|
||||
```env
|
||||
HOST=0.0.0.0
|
||||
PORT=10000
|
||||
HOST_DOMAIN=moving-helper.lan
|
||||
SSL_PATH=/etc/acme.sh/$HOST_DOMAIN
|
||||
APP_DIR=$HOME/.local/share/moving-helper
|
||||
BACKUP_DIR=$HOME/.local/backup/moving-helper
|
||||
BACKUP_REMOTE=
|
||||
APP_PORT=10000
|
||||
DATABASE_URL=sqlite:////app/data/app.db
|
||||
DATA_DIR=./data
|
||||
UID=1000
|
||||
GID=1000
|
||||
COMPOSE_PROJECT_NAME=moving-helper
|
||||
```
|
||||
|
||||
说明:
|
||||
|
||||
- 本地开发默认数据库仍然是 `./data/app.db`
|
||||
- Docker 内建议继续使用 `sqlite:////app/data/app.db`
|
||||
- `DATA_DIR` 控制宿主机上的持久化目录
|
||||
- `UID/GID` 用来让容器内文件权限更贴近宿主机用户
|
||||
- 容器内应用固定监听 `0.0.0.0:10000`
|
||||
- `APP_PORT` 只控制宿主机暴露端口,nginx 默认反代到这个端口
|
||||
- `APP_DIR` 是安装脚本复制 compose、`.env`、备份脚本等运行资产的目标目录
|
||||
- `DATA_DIR` 默认为相对路径 `./data`,安装后会相对于 `APP_DIR` 解析
|
||||
- `SSL_PATH` 由用户自行准备证书目录,安装脚本不会签发证书
|
||||
- `.env` 会被 shell 脚本直接 `source`,请保持 shell 兼容写法
|
||||
|
||||
## 本地开发模式
|
||||
|
||||
@@ -227,6 +238,13 @@ Docker / Compose 是这个项目面向长期运行环境的方式。
|
||||
- `image`:固定指向 `code.wanderingbadger.dev/tliu93/2026-moving-helper:latest`
|
||||
- `build`:用于本地开发时从当前代码构建镜像
|
||||
|
||||
当前部署约定已经收敛为:
|
||||
|
||||
- 容器内应用固定监听 `0.0.0.0:10000`
|
||||
- compose 固定使用 `user: 1000:1000`
|
||||
- 宿主机仅在 `127.0.0.1:${APP_PORT}` 暴露后端端口
|
||||
- SQLite 固定写入容器内 `/app/data/app.db`
|
||||
|
||||
### 首次准备
|
||||
|
||||
```bash
|
||||
@@ -271,10 +289,10 @@ http://localhost:10000
|
||||
|
||||
当前 `docker-compose.yml` 保持尽量简单:
|
||||
|
||||
- 默认镜像地址来自 `REGISTRY_HOST / IMAGE_NAME / IMAGE_TAG`
|
||||
- 默认暴露 `10000` 端口
|
||||
- 固定镜像地址为 `code.wanderingbadger.dev/tliu93/2026-moving-helper:latest`
|
||||
- 宿主机默认仅在 `127.0.0.1:10000` 暴露容器 `10000`
|
||||
- `restart: unless-stopped`
|
||||
- 容器用户来自 `UID:GID`
|
||||
- 容器固定使用 `1000:1000`
|
||||
- 宿主机 `DATA_DIR` 挂载到容器内 `/app/data`
|
||||
- SQLite 默认写入 `/app/data/app.db`
|
||||
|
||||
@@ -285,7 +303,33 @@ http://localhost:10000
|
||||
|
||||
## 自动化部署
|
||||
|
||||
这个项目没有复杂 CI/CD,只提供一个适合家用项目的轻量部署脚本:
|
||||
这个项目现在额外提供一个面向本地网络环境的最小安装脚本:
|
||||
|
||||
```bash
|
||||
sh scripts/install.sh
|
||||
```
|
||||
|
||||
安装脚本会执行:
|
||||
|
||||
1. 检查项目根目录下是否存在 `.env`
|
||||
2. 读取 `.env`
|
||||
3. 把 `docker-compose.yml`、`.env` 和渲染后的 `backup_db.sh` 复制到 `APP_DIR`
|
||||
4. 用 `HOST_DOMAIN`、`SSL_PATH`、`APP_PORT` 渲染 nginx 配置
|
||||
5. 写入 `/etc/nginx/sites-available/moving-helper-nginx`
|
||||
6. 创建到 `/etc/nginx/sites-enabled/` 的符号链接
|
||||
7. 执行 `nginx -t` 并 reload nginx
|
||||
8. 在 `APP_DIR` 下执行 `docker compose pull` 和 `docker compose up -d`
|
||||
9. 为当前用户写入每日 `02:10` 的 backup cron
|
||||
|
||||
其中以下步骤需要 root 或 sudo:
|
||||
|
||||
- 写入 nginx 配置
|
||||
- 执行 `nginx -t`
|
||||
- reload nginx
|
||||
|
||||
如果 `.env` 不存在,脚本会直接退出,不会继续做任何安装动作。
|
||||
|
||||
如果你只想在仓库目录里做一次手动更新,也保留了一个轻量部署脚本:
|
||||
|
||||
```bash
|
||||
./scripts/deploy.sh
|
||||
@@ -296,7 +340,8 @@ http://localhost:10000
|
||||
1. 检查 `.env`
|
||||
2. 准备数据目录
|
||||
3. 如果当前目录是 git 仓库,执行 `git pull --ff-only`
|
||||
4. 执行 `docker compose up -d --build`
|
||||
4. 执行 `docker compose pull web`
|
||||
5. 执行 `docker compose up -d`
|
||||
5. 输出容器状态
|
||||
6. 输出最近日志
|
||||
|
||||
@@ -305,7 +350,8 @@ http://localhost:10000
|
||||
如果你不想自动拉代码,也可以直接手动运行:
|
||||
|
||||
```bash
|
||||
docker compose up -d --build
|
||||
docker compose pull
|
||||
docker compose up -d
|
||||
```
|
||||
|
||||
## 数据持久化
|
||||
@@ -335,32 +381,83 @@ ${DATA_DIR:-./data}
|
||||
|
||||
## 备份与恢复
|
||||
|
||||
### 最简单的备份方式
|
||||
### 备份机制
|
||||
|
||||
直接复制 SQLite 文件即可:
|
||||
安装脚本会把渲染后的备份脚本安装到:
|
||||
|
||||
- `APP_DIR/backup_db.sh`
|
||||
|
||||
并为当前用户创建一条 cron:
|
||||
|
||||
- `10 2 * * *`
|
||||
|
||||
备份行为如下:
|
||||
|
||||
- 目标目录是 `BACKUP_DIR`
|
||||
- 备份文件名带时间戳,例如 `app-20260421-021000.db`
|
||||
- 最多保留 5 个本地备份
|
||||
- 如果 `BACKUP_REMOTE` 非空,会在本地备份完成后调用 `rclone copyto`
|
||||
|
||||
SQLite 一致性策略:
|
||||
|
||||
- 备份脚本优先使用 `sqlite3` 的 `.backup`
|
||||
- 不停容器
|
||||
- 不直接 `cp` 正在写入的数据库文件
|
||||
|
||||
这样可以在应用仍然运行时生成事务一致的快照,避免简单文件复制带来的损坏风险。
|
||||
|
||||
### 手动执行备份
|
||||
|
||||
如果你想手动触发一次备份:
|
||||
|
||||
```bash
|
||||
cp data/app.db backups/app.db
|
||||
sh "$APP_DIR/backup_db.sh"
|
||||
```
|
||||
|
||||
或者使用附带脚本:
|
||||
如果当前还没有执行安装脚本,也可以在仓库内手动准备 `.env` 后运行:
|
||||
|
||||
```bash
|
||||
./scripts/backup_db.sh
|
||||
```
|
||||
|
||||
它会在 `backups/` 目录下生成一个带时间戳的副本。
|
||||
前提是先通过安装脚本把它渲染并部署到 `APP_DIR`,因为仓库内版本本身是带占位符的模板。
|
||||
|
||||
### 最简单的恢复方式
|
||||
### 恢复大致步骤
|
||||
|
||||
停止容器后,把备份文件覆盖回去:
|
||||
|
||||
```bash
|
||||
cd "$APP_DIR"
|
||||
docker compose stop
|
||||
cp backups/app-YYYYMMDD-HHMMSS.db data/app.db
|
||||
cp "$BACKUP_DIR/app-YYYYMMDD-HHMMSS.db" "${DATA_DIR:-./data}/app.db"
|
||||
docker compose up -d
|
||||
```
|
||||
|
||||
如果 `DATA_DIR` 是相对路径,记得在 `APP_DIR` 下执行这些命令。
|
||||
|
||||
### nginx 与证书约定
|
||||
|
||||
仓库提供的 nginx 模板位于:
|
||||
|
||||
- `scripts/nginx/moving-helper.nginx.template`
|
||||
|
||||
安装脚本会把它渲染成 Debian / Ubuntu 风格的站点配置:
|
||||
|
||||
- `/etc/nginx/sites-available/moving-helper-nginx`
|
||||
- `/etc/nginx/sites-enabled/moving-helper-nginx`
|
||||
|
||||
模板约定:
|
||||
|
||||
- 80 端口强制跳转到 443
|
||||
- 443 默认启用 SSL
|
||||
- 反代到仅绑定在本机回环地址上的 `127.0.0.1:${APP_PORT}`
|
||||
- `client_max_body_size 0`
|
||||
|
||||
证书文件需要由用户自己准备在 `SSL_PATH` 下,当前模板默认引用:
|
||||
|
||||
- `fullchain.pem`
|
||||
- `privkey.key`
|
||||
|
||||
## 常见排查
|
||||
|
||||
### 1. 查看容器日志
|
||||
|
||||
Reference in New Issue
Block a user