图示展示从 Markdown 提交到 Cloudflare Tunnel 公网访问的完整发布链路。
这篇记录这个博客站本身的部署方案:用 Astro 构建纯静态文件,塞进 nginx 镜像,用 Docker Compose 跑在本地服务器上。
整体思路
astro build产出静态文件到dist/pagefind --site dist给dist/生成搜索索引- 把
dist/拷进nginx:alpine镜像 docker compose up -d映射1020:80端口
多阶段 Dockerfile
构建与运行分离,最终镜像只含 nginx 和静态文件,体积很小:
FROM node:22-alpine AS build
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build # astro build && pagefind
FROM nginx:alpine
COPY nginx.conf /etc/nginx/conf.d/default.conf
COPY --from=build /app/dist /usr/share/nginx/html
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
nginx 静态路由
Astro 默认按目录输出 HTML(/blog/foo/ → dist/blog/foo/index.html)。对应的 nginx 路由:
location / {
try_files $uri $uri/ $uri.html =404;
}
$uri/ 让目录请求命中其下的 index.html,$uri.html 兼容无尾斜杠的旧链接。
一键启动
# 构建 + 启动
docker compose up -d --build
# 访问
curl http://服务器IP:1020
日常更新文章
# 写完新 .md 后,重新构建并重启
docker compose up -d --build
因为用了多阶段构建,每次改动都会在容器内重新 npm ci + 构建,所以更新很省心。
完整发布架构
线上链路可以拆成四层:
Cloudflare Tunnel
↓
本地服务器 localhost:1020
↓
Nginx 静态容器 :80
↓
Astro dist/ + Pagefind index
构建阶段和运行阶段完全分离:Node 镜像只在构建时存在,最终运行镜像只保留 Nginx 和静态文件。这样既减少镜像体积,也降低生产容器攻击面。
构建阶段到底产出了什么
npm run build 实际上包含两步:
- Astro 根据 Markdown Content Collections 生成静态 HTML、OG 图片、RSS 和 sitemap。
- Pagefind 扫描带有
data-pagefind-body的页面,生成浏览器端搜索索引。
构建后建议检查:
find dist -maxdepth 2 -type f | sort
curl -I http://127.0.0.1:1020/
curl -I http://127.0.0.1:1020/rss.xml
Nginx 配置要点
除了 try_files,生产配置还应该关注缓存和安全响应头:
location /_astro/ {
add_header Cache-Control "public, max-age=31536000, immutable";
}
location / {
try_files $uri $uri/ $uri.html =404;
add_header X-Content-Type-Options nosniff always;
add_header Referrer-Policy strict-origin-when-cross-origin always;
}
带 hash 的 Astro 静态资源可以长期缓存;HTML 不建议设置过长缓存,否则新文章发布后用户可能看不到最新内容。nosniff 可以减少浏览器 MIME 猜测风险,Referrer-Policy 限制跨域泄露完整路径。
Cloudflare Tunnel 的边界
Tunnel 只负责网络转发,不参与 Astro 的 URL 生成:
- 回源地址可以是
http://localhost:1020。 - canonical、RSS、sitemap、OG 必须使用
https://blog.gotomarry.xyz。 - Cloudflare 侧建议开启 HTTPS、压缩、缓存静态资源和基础 DDoS 防护。
- 不要把管理端口直接暴露到公网,只暴露 Tunnel 或 Nginx 服务。
内容发布流程
推荐把发布过程固定成脚本化流程:
# 1. 本地检查 Markdown 和构建
npm run build
npm run check
# 2. 构建镜像
docker compose build \
--build-arg NPM_REGISTRY=https://repo.huaweicloud.com/repository/npm/
# 3. 重启并检查健康状态
docker compose up -d
docker ps --filter name=personal-blog
curl -f https://blog.gotomarry.xyz/
实际使用时可以把这些命令放进 Makefile 或 CI,避免漏掉 Pagefind、sitemap 或健康检查。
回滚与备份
静态站点回滚很简单:保留上一个镜像 tag 即可。
docker tag personal-blog:latest personal-blog:backup-$(date +%Y%m%d)
# 新版本异常时
docker run -d --name personal-blog-rollback -p 1020:80 personal-blog:backup-20260914
文章源文件和 public/images 应该由 Git 版本管理;Docker 镜像不是源代码备份。每次发布前保留构建日志,出错时可以快速定位是内容、Astro、Pagefind 还是 Nginx 问题。
监控和验收清单
| 检查项 | 命令/方法 |
|---|---|
| 容器健康 | docker ps 显示 healthy |
| 首页 | curl -f https://blog.gotomarry.xyz/ |
| RSS | 浏览器打开 /rss.xml,检查链接为正式域名 |
| Sitemap | 检查不存在 localhost |
| 搜索 | 搜索一篇文章标题 |
| 移动端 | Chrome DevTools 检查 390px 宽度 |
| 缓存 | 检查 /_astro/ 响应头 |
| 回滚 | 定期演练旧镜像启动和切换 |
评论
还没有评论,来留第一条吧。