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`:当前推进计划
|
||||
- `docs/rebuild-trigger-spec.md`:AstrBot / cron 重建触发与错误码约定
|
||||
- `docs/content-sync-guide.md`:环境变量、映射文件、同步脚本职责、故障排查
|
||||
- `docs/docker-deploy.md`:Docker / Compose 部署说明
|
||||
- `docs/ui-design-spec.md`:UI 设计规范
|
||||
|
||||
## 内容入口
|
||||
|
|
@ -121,6 +122,24 @@ REBUILD_RESULT {...}
|
|||
|
||||
- `docs/rebuild-trigger-spec.md`
|
||||
|
||||
## Docker / Compose 部署
|
||||
|
||||
最小启动方式:
|
||||
|
||||
```bash
|
||||
docker compose up -d --build
|
||||
```
|
||||
|
||||
默认端口:
|
||||
|
||||
```text
|
||||
http://localhost:8080
|
||||
```
|
||||
|
||||
详细说明见:
|
||||
|
||||
- `docs/docker-deploy.md`
|
||||
|
||||
## 当前实现边界
|
||||
|
||||
- 当前默认策略是失败时回退 seed data,而不是保留上一轮 generated 文件
|
||||
|
|
|
|||
8
TODO.md
8
TODO.md
|
|
@ -89,10 +89,10 @@
|
|||
|
||||
### 4. 补部署文件与部署说明
|
||||
|
||||
- [ ] 增加 `Dockerfile`
|
||||
- [ ] 增加 `docker-compose.yml`
|
||||
- [ ] 明确静态产物部署方式
|
||||
- [ ] 写清部署步骤与重建入口
|
||||
- [x] 增加 `Dockerfile`
|
||||
- [x] 增加 `docker-compose.yml`
|
||||
- [x] 明确静态产物部署方式
|
||||
- [x] 写清部署步骤与重建入口
|
||||
|
||||
### 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