Add Docker Compose deployment setup
This commit is contained in:
parent
74fb6ec0a0
commit
f0a6da915a
|
|
@ -0,0 +1,10 @@
|
||||||
|
node_modules
|
||||||
|
dist
|
||||||
|
.git
|
||||||
|
.gitignore
|
||||||
|
.env
|
||||||
|
.env.*
|
||||||
|
.astro
|
||||||
|
.omc
|
||||||
|
.omx
|
||||||
|
.codex
|
||||||
|
|
@ -0,0 +1,52 @@
|
||||||
|
FROM node:22-alpine AS builder
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
COPY package.json package-lock.json ./
|
||||||
|
RUN npm ci
|
||||||
|
|
||||||
|
COPY . .
|
||||||
|
|
||||||
|
ARG GITEA_BASE_URL=""
|
||||||
|
ARG GITEA_TOKEN=""
|
||||||
|
ARG GITEA_USERNAME=""
|
||||||
|
ARG SEAFILE_BASE_URL=""
|
||||||
|
ARG SEAFILE_TOKEN=""
|
||||||
|
ARG SYNC_OUTPUT_DIR="src/data/generated"
|
||||||
|
ARG STRICT_SYNC="false"
|
||||||
|
ARG SEAFILE_MIRROR_DOWNLOADS="false"
|
||||||
|
ARG DOWNLOADS_OUTPUT_DIR="public/downloads"
|
||||||
|
ARG GITEA_ACTIVITY_DAYS="70"
|
||||||
|
ARG GITEA_ACTIVITY_PER_DAY_LIMIT="50"
|
||||||
|
ARG GITEA_RECENT_ITEM_LIMIT="8"
|
||||||
|
ARG GITEA_REQUEST_TIMEOUT_MS="15000"
|
||||||
|
ARG GITEA_REQUEST_CONCURRENCY="5"
|
||||||
|
ARG SEAFILE_REQUEST_TIMEOUT_MS="15000"
|
||||||
|
|
||||||
|
ENV GITEA_BASE_URL="${GITEA_BASE_URL}" \
|
||||||
|
GITEA_TOKEN="${GITEA_TOKEN}" \
|
||||||
|
GITEA_USERNAME="${GITEA_USERNAME}" \
|
||||||
|
SEAFILE_BASE_URL="${SEAFILE_BASE_URL}" \
|
||||||
|
SEAFILE_TOKEN="${SEAFILE_TOKEN}" \
|
||||||
|
SYNC_OUTPUT_DIR="${SYNC_OUTPUT_DIR}" \
|
||||||
|
STRICT_SYNC="${STRICT_SYNC}" \
|
||||||
|
SEAFILE_MIRROR_DOWNLOADS="${SEAFILE_MIRROR_DOWNLOADS}" \
|
||||||
|
DOWNLOADS_OUTPUT_DIR="${DOWNLOADS_OUTPUT_DIR}" \
|
||||||
|
GITEA_ACTIVITY_DAYS="${GITEA_ACTIVITY_DAYS}" \
|
||||||
|
GITEA_ACTIVITY_PER_DAY_LIMIT="${GITEA_ACTIVITY_PER_DAY_LIMIT}" \
|
||||||
|
GITEA_RECENT_ITEM_LIMIT="${GITEA_RECENT_ITEM_LIMIT}" \
|
||||||
|
GITEA_REQUEST_TIMEOUT_MS="${GITEA_REQUEST_TIMEOUT_MS}" \
|
||||||
|
GITEA_REQUEST_CONCURRENCY="${GITEA_REQUEST_CONCURRENCY}" \
|
||||||
|
SEAFILE_REQUEST_TIMEOUT_MS="${SEAFILE_REQUEST_TIMEOUT_MS}"
|
||||||
|
|
||||||
|
RUN npm run rebuild
|
||||||
|
|
||||||
|
FROM nginx:1.27-alpine AS runtime
|
||||||
|
|
||||||
|
COPY docker/nginx/default.conf /etc/nginx/conf.d/default.conf
|
||||||
|
COPY --from=builder /app/dist /usr/share/nginx/html
|
||||||
|
|
||||||
|
EXPOSE 80
|
||||||
|
|
||||||
|
HEALTHCHECK --interval=30s --timeout=5s --start-period=10s --retries=3 \
|
||||||
|
CMD wget -q -O /dev/null http://127.0.0.1/ || exit 1
|
||||||
19
README.md
19
README.md
|
|
@ -81,6 +81,7 @@ npm run rebuild
|
||||||
- `TODO.md`:当前推进计划
|
- `TODO.md`:当前推进计划
|
||||||
- `docs/rebuild-trigger-spec.md`:AstrBot / cron 重建触发与错误码约定
|
- `docs/rebuild-trigger-spec.md`:AstrBot / cron 重建触发与错误码约定
|
||||||
- `docs/content-sync-guide.md`:环境变量、映射文件、同步脚本职责、故障排查
|
- `docs/content-sync-guide.md`:环境变量、映射文件、同步脚本职责、故障排查
|
||||||
|
- `docs/docker-deploy.md`:Docker / Compose 部署说明
|
||||||
- `docs/ui-design-spec.md`:UI 设计规范
|
- `docs/ui-design-spec.md`:UI 设计规范
|
||||||
|
|
||||||
## 内容入口
|
## 内容入口
|
||||||
|
|
@ -121,6 +122,24 @@ REBUILD_RESULT {...}
|
||||||
|
|
||||||
- `docs/rebuild-trigger-spec.md`
|
- `docs/rebuild-trigger-spec.md`
|
||||||
|
|
||||||
|
## Docker / Compose 部署
|
||||||
|
|
||||||
|
最小启动方式:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker compose up -d --build
|
||||||
|
```
|
||||||
|
|
||||||
|
默认端口:
|
||||||
|
|
||||||
|
```text
|
||||||
|
http://localhost:8080
|
||||||
|
```
|
||||||
|
|
||||||
|
详细说明见:
|
||||||
|
|
||||||
|
- `docs/docker-deploy.md`
|
||||||
|
|
||||||
## 当前实现边界
|
## 当前实现边界
|
||||||
|
|
||||||
- 当前默认策略是失败时回退 seed data,而不是保留上一轮 generated 文件
|
- 当前默认策略是失败时回退 seed data,而不是保留上一轮 generated 文件
|
||||||
|
|
|
||||||
8
TODO.md
8
TODO.md
|
|
@ -89,10 +89,10 @@
|
||||||
|
|
||||||
### 4. 补部署文件与部署说明
|
### 4. 补部署文件与部署说明
|
||||||
|
|
||||||
- [ ] 增加 `Dockerfile`
|
- [x] 增加 `Dockerfile`
|
||||||
- [ ] 增加 `docker-compose.yml`
|
- [x] 增加 `docker-compose.yml`
|
||||||
- [ ] 明确静态产物部署方式
|
- [x] 明确静态产物部署方式
|
||||||
- [ ] 写清部署步骤与重建入口
|
- [x] 写清部署步骤与重建入口
|
||||||
|
|
||||||
### 5. 补运行文档
|
### 5. 补运行文档
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,26 @@
|
||||||
|
services:
|
||||||
|
homepage:
|
||||||
|
build:
|
||||||
|
context: .
|
||||||
|
dockerfile: Dockerfile
|
||||||
|
args:
|
||||||
|
GITEA_BASE_URL: ${GITEA_BASE_URL:-}
|
||||||
|
GITEA_TOKEN: ${GITEA_TOKEN:-}
|
||||||
|
GITEA_USERNAME: ${GITEA_USERNAME:-}
|
||||||
|
SEAFILE_BASE_URL: ${SEAFILE_BASE_URL:-}
|
||||||
|
SEAFILE_TOKEN: ${SEAFILE_TOKEN:-}
|
||||||
|
SYNC_OUTPUT_DIR: ${SYNC_OUTPUT_DIR:-src/data/generated}
|
||||||
|
STRICT_SYNC: ${STRICT_SYNC:-false}
|
||||||
|
SEAFILE_MIRROR_DOWNLOADS: ${SEAFILE_MIRROR_DOWNLOADS:-false}
|
||||||
|
DOWNLOADS_OUTPUT_DIR: ${DOWNLOADS_OUTPUT_DIR:-public/downloads}
|
||||||
|
GITEA_ACTIVITY_DAYS: ${GITEA_ACTIVITY_DAYS:-70}
|
||||||
|
GITEA_ACTIVITY_PER_DAY_LIMIT: ${GITEA_ACTIVITY_PER_DAY_LIMIT:-50}
|
||||||
|
GITEA_RECENT_ITEM_LIMIT: ${GITEA_RECENT_ITEM_LIMIT:-8}
|
||||||
|
GITEA_REQUEST_TIMEOUT_MS: ${GITEA_REQUEST_TIMEOUT_MS:-15000}
|
||||||
|
GITEA_REQUEST_CONCURRENCY: ${GITEA_REQUEST_CONCURRENCY:-5}
|
||||||
|
SEAFILE_REQUEST_TIMEOUT_MS: ${SEAFILE_REQUEST_TIMEOUT_MS:-15000}
|
||||||
|
image: personal-homepage:latest
|
||||||
|
container_name: personal-homepage
|
||||||
|
ports:
|
||||||
|
- "${HOMEPAGE_PORT:-8080}:80"
|
||||||
|
restart: unless-stopped
|
||||||
|
|
@ -0,0 +1,18 @@
|
||||||
|
server {
|
||||||
|
listen 80;
|
||||||
|
listen [::]:80;
|
||||||
|
server_name _;
|
||||||
|
|
||||||
|
root /usr/share/nginx/html;
|
||||||
|
index index.html;
|
||||||
|
|
||||||
|
location / {
|
||||||
|
try_files $uri $uri/ $uri/index.html =404;
|
||||||
|
}
|
||||||
|
|
||||||
|
location = /50x.html {
|
||||||
|
internal;
|
||||||
|
}
|
||||||
|
|
||||||
|
error_page 500 502 503 504 /50x.html;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,195 @@
|
||||||
|
# Docker / Compose 部署说明
|
||||||
|
|
||||||
|
当前提供的是最小可用静态部署方案:
|
||||||
|
|
||||||
|
- 构建阶段:在 Docker build 中执行 `npm run rebuild`
|
||||||
|
- 运行阶段:使用 Nginx 提供 `dist/` 静态文件
|
||||||
|
|
||||||
|
## 文件
|
||||||
|
|
||||||
|
- `Dockerfile`
|
||||||
|
- `docker-compose.yml`
|
||||||
|
- `docker/nginx/default.conf`
|
||||||
|
|
||||||
|
## 使用方式
|
||||||
|
|
||||||
|
### 1. 准备环境变量
|
||||||
|
|
||||||
|
确保仓库根目录有可用的 `.env`,或在执行 `docker compose` 前导出这些变量:
|
||||||
|
|
||||||
|
- `GITEA_BASE_URL`
|
||||||
|
- `GITEA_TOKEN`
|
||||||
|
- `GITEA_USERNAME`
|
||||||
|
- `SEAFILE_BASE_URL`
|
||||||
|
- `SEAFILE_TOKEN`
|
||||||
|
|
||||||
|
可选:
|
||||||
|
|
||||||
|
- `STRICT_SYNC`
|
||||||
|
- `HOMEPAGE_PORT`
|
||||||
|
- 其余同步调优参数
|
||||||
|
|
||||||
|
`docker-compose.yml` 会把这些值作为 **build args** 传给 Dockerfile,用于构建时同步和静态生成。
|
||||||
|
|
||||||
|
### 环境变量是怎么注入的
|
||||||
|
|
||||||
|
当前链路是:
|
||||||
|
|
||||||
|
```text
|
||||||
|
宿主机环境变量 / 项目根目录 .env
|
||||||
|
-> docker compose 读取变量
|
||||||
|
-> docker-compose.yml 的 build.args
|
||||||
|
-> Dockerfile 的 ARG
|
||||||
|
-> Dockerfile 的 ENV
|
||||||
|
-> npm run rebuild
|
||||||
|
```
|
||||||
|
|
||||||
|
也就是说,`docker-compose.yml` 自己并不保存真实值,它只是引用变量,例如:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
args:
|
||||||
|
GITEA_BASE_URL: ${GITEA_BASE_URL:-}
|
||||||
|
```
|
||||||
|
|
||||||
|
含义是:
|
||||||
|
|
||||||
|
- 如果宿主机环境或 `.env` 里有 `GITEA_BASE_URL`,就把它传进去
|
||||||
|
- 如果没有,就用空字符串
|
||||||
|
|
||||||
|
然后 `Dockerfile` 再接住:
|
||||||
|
|
||||||
|
```dockerfile
|
||||||
|
ARG GITEA_BASE_URL=""
|
||||||
|
ENV GITEA_BASE_URL="${GITEA_BASE_URL}"
|
||||||
|
```
|
||||||
|
|
||||||
|
这样 `npm run rebuild` 在镜像构建阶段就能读取到这些变量。
|
||||||
|
|
||||||
|
### `.env` 和 compose 的关系
|
||||||
|
|
||||||
|
当前项目里,同一个 `.env` 同时服务两条路径:
|
||||||
|
|
||||||
|
1. **本地直接执行**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm run rebuild
|
||||||
|
```
|
||||||
|
|
||||||
|
Node 通过:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
--env-file-if-exists=.env
|
||||||
|
```
|
||||||
|
|
||||||
|
读取 `.env`
|
||||||
|
|
||||||
|
2. **Docker Compose 构建**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker compose up -d --build
|
||||||
|
```
|
||||||
|
|
||||||
|
Compose 会自动读取项目根目录 `.env`,并将变量传给 `build.args`
|
||||||
|
|
||||||
|
所以可以把 `.env` 理解成:
|
||||||
|
|
||||||
|
- 本地脚本运行配置
|
||||||
|
- Docker 构建时同步配置
|
||||||
|
|
||||||
|
共用的一份构建环境变量文件。
|
||||||
|
|
||||||
|
### 为什么用 build args 而不是运行时环境变量
|
||||||
|
|
||||||
|
因为这个项目的 Gitea / Seafile token 只在**构建阶段**需要:
|
||||||
|
|
||||||
|
- 构建时同步远端数据
|
||||||
|
- 构建时生成静态页面
|
||||||
|
|
||||||
|
最终运行时容器只是 Nginx 提供 `dist/`,不再访问 Gitea / Seafile,也不需要 token。
|
||||||
|
|
||||||
|
### 修改环境变量后要怎么生效
|
||||||
|
|
||||||
|
因为变量是注入到 **构建阶段** 的,所以修改 `.env` 后需要重新 build:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker compose up -d --build
|
||||||
|
```
|
||||||
|
|
||||||
|
如果只执行:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker compose restart
|
||||||
|
```
|
||||||
|
|
||||||
|
不会重新同步,也不会重新生成静态产物。
|
||||||
|
|
||||||
|
### 2. 构建并启动
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker compose up -d --build
|
||||||
|
```
|
||||||
|
|
||||||
|
默认会把站点暴露到:
|
||||||
|
|
||||||
|
```text
|
||||||
|
http://localhost:8080
|
||||||
|
```
|
||||||
|
|
||||||
|
如需修改端口:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
HOMEPAGE_PORT=80 docker compose up -d --build
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. 查看日志
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker compose logs -f homepage
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4. 停止
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker compose down
|
||||||
|
```
|
||||||
|
|
||||||
|
## 部署方式说明
|
||||||
|
|
||||||
|
当前 compose 方案是:
|
||||||
|
|
||||||
|
1. 构建镜像时执行 `npm run rebuild`
|
||||||
|
2. 生成 `dist/`
|
||||||
|
3. 将 `dist/` 拷贝进 Nginx 容器
|
||||||
|
4. 运行时只提供静态文件服务
|
||||||
|
|
||||||
|
这意味着:
|
||||||
|
|
||||||
|
- 运行中的容器不需要 Gitea / Seafile token
|
||||||
|
- token 只在镜像构建阶段使用
|
||||||
|
- 每次内容更新后,需要重新 build 镜像
|
||||||
|
|
||||||
|
## 与 AstrBot 的配合方式
|
||||||
|
|
||||||
|
如果后续由 AstrBot 触发重建,推荐:
|
||||||
|
|
||||||
|
1. AstrBot 在服务器上拉最新代码
|
||||||
|
2. AstrBot 执行 `docker compose up -d --build`
|
||||||
|
3. AstrBot 根据命令结果发送成功 / 失败通知
|
||||||
|
|
||||||
|
如果你想让 AstrBot 先单独判断同步 / 构建错误码,再决定是否部署,也可以先执行:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm run rebuild
|
||||||
|
```
|
||||||
|
|
||||||
|
通过后再执行:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker compose up -d --build
|
||||||
|
```
|
||||||
|
|
||||||
|
## 当前限制
|
||||||
|
|
||||||
|
- compose 里还没有反向代理、HTTPS、域名配置
|
||||||
|
- 还没有单独拆“构建容器”和“运行容器”的外部流水线
|
||||||
|
- 还没有持久化部署产物或零停机切换策略
|
||||||
Loading…
Reference in New Issue