快速部署
GrtBlog 使用 Docker Compose 进行一键部署,无需手动配置复杂的运行环境。
环境要求
- 一台 Linux 服务器(推荐 1 核 1G 以上配置,支持 amd64 / arm64)
- 安装 Docker 和 Docker Compose
- 一个域名(可选,但推荐)
方式一:使用预构建镜像(推荐)
每次发布新版本时,GitHub Actions 会自动构建并推送多架构镜像到 GHCR 和 Docker Hub。这是最简单的部署方式,无需克隆完整代码仓库,也无需本地构建。
一键安装
运行以下命令即可自动完成环境检测、镜像源选择、密钥生成、配置下载和服务启动:
bash <(curl -fsSL https://raw.githubusercontent.com/grtsinry43/grtblog/main/deploy/install.sh)
# 国内:
bash <(curl -fsSL https://cnb.cool/grtsinry43/grtblog/-/git/raw/main/deploy/install.sh)也支持非交互模式,通过环境变量传参:
GRTBLOG_NONINTERACTIVE=1 APP_VERSION=2.0.2 \
IMAGE_REPO_PREFIX=docker.cnb.cool/grtsinry43/grtblog/ \
bash <(curl -fsSL https://cnb.cool/grtsinry43/grtblog/-/git/raw/main/deploy/install.sh)1. 准备部署目录
如果不使用一键安装脚本,可以手动下载 deploy 目录和 Nginx 配置:
# 创建部署目录
mkdir -p grtblog && cd grtblog
# 下载所需文件(国际)
BASE_URL="https://raw.githubusercontent.com/grtsinry43/grtblog/main"
# 国内加速:
# BASE_URL="https://cnb.cool/grtsinry43/grtblog/-/git/raw/main"
curl -fsSL "$BASE_URL/deploy/docker-compose.yml" -o docker-compose.yml
curl -fsSL "$BASE_URL/deploy/.env.example" -o .env
mkdir -p nginx
curl -fsSL "$BASE_URL/deploy/nginx/nginx.conf" -o nginx/nginx.conf2. 配置环境变量
编辑 .env,设置镜像来源和版本:
# 镜像来源(三选一)
# Docker Hub(默认):
IMAGE_REPO_PREFIX=grtsinry43/
# GHCR:
# IMAGE_REPO_PREFIX=ghcr.io/grtsinry43/
# CNB(国内推荐):
# IMAGE_REPO_PREFIX=docker.cnb.cool/grtsinry43/grtblog/
APP_VERSION=2.0.2
APP_UPDATE_CHANNEL=stable
# 数据库密码(请设置为强密码)
POSTGRES_PASSWORD=your-secure-password
# 认证密钥(请使用随机字符串)
AUTH_SECRET=your-random-secret-string镜像来源说明
三个源的镜像内容完全一致,区别仅在拉取地址:
| 来源 | IMAGE_REPO_PREFIX | 拉取示例 | 适用场景 |
|---|---|---|---|
| Docker Hub | grtsinry43/ | grtsinry43/grtblog-server:2.0.2 | 国际通用 |
| GHCR | ghcr.io/grtsinry43/ | ghcr.io/grtsinry43/grtblog-server:2.0.2 | 国际通用 |
| CNB | docker.cnb.cool/grtsinry43/grtblog/ | docker.cnb.cool/grtsinry43/grtblog/grtblog-server:2.0.2 | 国内服务器推荐 |
国内服务器推荐使用 CNB 源,直连国内节点,无需配置镜像加速。
Docker Hub 镜像加速
Nginx、PostgreSQL、Redis 等第三方镜像默认从 Docker Hub 拉取。国内服务器如果拉取缓慢,可以设置 DOCKER_MIRROR 使用 毫秒镜像 加速:
DOCKER_MIRROR=docker.1ms.run/设置后,nginx:1.27-alpine 会自动变为 docker.1ms.run/nginx:1.27-alpine。使用一键安装脚本时,国内网络会自动配置此项。
生成随机密钥
可以使用以下命令生成:
openssl rand -hex 32查看可用版本
- GitHub Releases:
https://github.com/grtsinry43/grtblog/releases - Docker Hub:
https://hub.docker.com/r/grtsinry43/grtblog-server/tags - GHCR:
https://github.com/grtsinry43/grtblog/pkgs/container/grtblog-server - CNB:
https://cnb.cool/grtsinry43/grtblog
3. 启动服务
mkdir -p storage/html storage/uploads storage/geoip
docker compose up -d首次启动会自动拉取镜像并完成数据库迁移,无需额外操作。
4. 升级
# 1. 修改 .env 中的 APP_VERSION 为新版本号
# APP_VERSION=2.1.0
# 2. 拉取新镜像并重启
docker compose pull server renderer
docker compose up -d server rendererNginx 无需重启,会通过 Docker DNS 自动发现新容器。数据库迁移在 server 启动时自动执行。
方式二:本地构建
如果你需要自定义构建参数(如修改管理面板配置),或者无法访问 GHCR,可以克隆仓库本地构建。
1. 获取代码
git clone https://github.com/grtsinry43/grtblog.git
# 国内加速:
# git clone https://cnb.cool/grtsinry43/grtblog.git
cd grtblog/deploy2. 配置环境变量
cp .env.example .env编辑 .env 文件,至少修改以下配置:
# 本地构建不需要设置 IMAGE_REPO_PREFIX
IMAGE_REPO_PREFIX=
APP_VERSION=local
# 数据库密码(请设置为强密码)
POSTGRES_PASSWORD=your-secure-password
# 认证密钥(请使用随机字符串)
AUTH_SECRET=your-random-secret-string3. 启动服务
mkdir -p storage/html storage/uploads storage/geoip
docker compose up -d --build首次启动会自动完成数据库迁移,无需额外操作。
4. 升级
# 拉取最新代码并切换到目标版本
git fetch --tags
git checkout v2.1.0
# 重新构建并启动
docker compose up -d --build server renderer验证部署
# 检查服务健康状态
curl -f http://localhost:80/healthz
# 检查后端活性
curl -f http://localhost:80/health/liveness看到正常响应后,即可通过浏览器访问:
- 博客首页:
http://your-server-ip - 管理后台:
http://your-server-ip/admin/
镜像标签说明
| Tag 类型 | 示例 | 说明 |
|---|---|---|
| 完整版本号 | 2.0.2 | 精确版本,推荐生产使用 |
| 主次版本号 | 2.0 | 自动跟随该次版本的最新补丁 |
latest | latest | 最新 stable 版本 |
| 预发布版本 | 2.1.0-beta.1 | 测试版本,不附带 latest 标签 |
预发布版本(含 -alpha / -beta / -rc 后缀)不会更新 latest 和主次版本标签,适合提前测试。
更新通道
GrtBlog 内置更新检查功能,会在管理后台自动提示新版本。通过 .env 中的 APP_UPDATE_CHANNEL 控制检查行为:
| 通道 | 检查来源 | 提示范围 | 适用场景 |
|---|---|---|---|
stable | GitHub Releases | 仅正式版本 | 生产环境,追求稳定 |
preview | Git Tags | 当前 major 内的预发布版本 | 提前测试新功能 |
切换更新通道
编辑 .env 中的 APP_UPDATE_CHANNEL,然后重启 server 即可生效:
# 切换到 preview 通道,接收 alpha / beta / rc 更新提示
# deploy/.env
APP_UPDATE_CHANNEL=preview
docker compose restart server切换回 stable 通道同理,将值改为 stable 后重启。
通道与镜像标签配套使用
更新通道只影响检查和提示,不会自动升级。收到更新提示后,仍需手动修改 APP_VERSION 并拉取新镜像。建议通道与镜像标签保持一致:
| 用途 | 推荐 APP_VERSION | 推荐 APP_UPDATE_CHANNEL |
|---|---|---|
| 生产稳定 | 2.0.2 | stable |
| 预发布验证 | 2.1.0-beta.1 | preview |
| 跟随 stable 滚动 | stable | stable |
| 跟随 preview 滚动 | preview | preview |
关闭更新检查
如不需要更新提示,设置 APP_UPDATE_CHECK_ENABLED=false 即可:
APP_UPDATE_CHECK_ENABLED=false可选配置
Cloudflare Turnstile 验证
启用 Turnstile 人机验证可以提升管理后台的安全性,防止未授权的登录尝试:
TURNSTILE_ENABLED=true
TURNSTILE_SECRET=your-turnstile-secret防止垃圾评论
如需过滤垃圾评论,推荐在管理后台开启评论审核并配置 AI 自动审核:
- 设置 > 评论设置:开启评论审核
- 设置 > AI 配置:配置 AI 服务并开启评论自动审核
开启后系统会对新评论进行智能识别和过滤。
GeoIP 地理定位
启用后可以在管理后台查看访客的地理分布:
GEOIP_DB_URL=https://github.com/P3TERX/GeoLite.mmdb/raw/download/GeoLite2-City.mmdb
GEOIP_ASN_DB_URL=https://github.com/P3TERX/GeoLite.mmdb/raw/download/GeoLite2-ASN.mmdb自定义端口
默认使用 80 端口,可以通过 NGINX_PORT 修改:
NGINX_PORT=8080反向代理与 HTTPS
生产环境建议在前面加一层反向代理(如 Caddy 或 Nginx)来处理 HTTPS。内层 Nginx 已经处理了路由分发,外层只需透传即可,但有几个路径需要特殊配置。
Nginx 示例
server {
listen 80;
server_name yourdomain.com;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl http2;
server_name yourdomain.com;
ssl_certificate /path/to/cert.pem;
ssl_certificate_key /path/to/key.pem;
# 与内层保持一致,否则大文件上传会被外层拦截
client_max_body_size 200M;
# 透传真实 IP(内层通过 X-Real-IP 识别客户端 IP)
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
# WebSocket(实时通知推送)
location /api/v2/ws/ {
proxy_pass http://127.0.0.1:80;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_read_timeout 86400s;
}
# SSE 流式接口(AI 重写 / 摘要生成)
location ~ ^/api/v2/admin/ai/.+/stream$ {
proxy_pass http://127.0.0.1:80;
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_buffering off;
proxy_request_buffering off;
proxy_cache off;
proxy_read_timeout 3600s;
proxy_send_timeout 3600s;
add_header X-Accel-Buffering no;
}
# 默认转发
location / {
proxy_pass http://127.0.0.1:80;
}
}Caddy 示例
Caddy 默认透传 Host 和 X-Forwarded-* 头,配置更简洁:
yourdomain.com {
reverse_proxy localhost:80
}Caddy 注意事项
Caddy 默认的反代超时可能不够长,WebSocket 和 SSE 流式接口需要额外配置超时时间,否则长连接会被提前断开。
关键注意事项
| 项目 | 说明 |
|---|---|
X-Real-IP | 必须设置。内层 Nginx 通过此头获取真实客户端 IP,用于评论显示、访问日志等 |
Host 头 | 必须透传。后端依赖它生成 ActivityPub Actor URL、RSS 链接等 |
| WebSocket | /api/v2/ws/ 需透传 Upgrade + Connection 头,否则实时通知无法工作 |
| SSE 流式 | AI 相关的流式接口使用 SSE,外层必须关闭 proxy_buffering,否则响应会被缓冲导致流式效果失效 |
client_max_body_size | 内层限制 200M,外层应 ≥ 200M |
| ActivityPub | /.well-known/、/ap/、/nodeinfo/ 等联邦路径无需特殊处理,普通转发即可 |
数据备份
重要数据存储在 Docker volumes 中:
| Volume | 内容 |
|---|---|
postgres_data | 数据库(文章、评论等所有数据) |
redis_data | 缓存数据 |
./storage/html | 生成的静态页面与客户端资源 |
./storage/uploads | 上传的图片和文件 |
./storage/geoip | GeoIP 数据库缓存 |
建议定期备份数据库:
docker compose exec postgres pg_dump -U postgres grtblog > backup.sql故障排查
服务无法启动
# 查看容器日志
docker compose logs server
docker compose logs renderer页面显示异常
检查静态文件生成状态:
docker compose logs server | grep -i "isr\|render\|html"数据库迁移问题
查看迁移状态:
docker compose exec server goose -table public.goose_db_version -dir /app/migrations postgres "$DB_DSN" status如需回滚最近一次迁移:
docker compose exec server goose -table public.goose_db_version -dir /app/migrations postgres "$DB_DSN" down