Epic Stack 部署指南:基于 Fly.io 与 LiteFS 的生产级全栈部署实战 Epic Stack 部署指南基于 Fly.io 与 LiteFS 的生产级全栈部署实战【免费下载链接】epic-stackThis is a Full Stack app starter with the foundational things setup and configured for you to hit the ground running on your next EPIC idea.项目地址: https://gitcode.com/GitHub_Trending/ep/epic-stack本文以 Epic Stack 官方部署文档 docs/deployment.md 为骨架系统讲解如何将这一全栈应用模板部署到 Fly.io——从安装 flyctl、创建 staging/production 双环境、配置密钥与 Consul、挂载 SQLite 持久卷、接入 Tigris 对象存储到利用内置 GitHub Actions 实现 push-to-deploy并补充使用 Docker/Podman 本地部署的完整方案。读完本文你将掌握 Epic Stack 从本地开发到生产环境的完整部署链路并理解 LiteFS 单主复制、Prisma 迁移与零停机部署背后的实现原理。部署前的整体认知Epic Stack 是一个开箱即跑的全栈应用模板首次创建仓库时会引导你回答一系列问题来完成应用配置与部署。但官方在 docs/deployment.md 中把完整的部署步骤固化成了文档既方便排查问题也支持日后手动重建。整个部署流程围绕以下几个核心资产展开fly.tomlFly.io 应用声明文件定义了应用名、主区域、构建方式、服务端口与健康检查other/Dockerfile生产镜像构建脚本最终以litefs mount作为容器入口other/litefs.ymlLiteFS 配置负责 SQLite 的 FUSE 挂载、Consul 租约与启动时的 exec 命令链.github/workflows/deploy.yml内置 CI/CD推送main自动部署生产、推送dev自动部署 staging。部署模型是一台主实例primary可写、多台副本replica只读的 LiteFS 单主复制架构这与 Fly 托管的 Postgres 服务模式一致详情可参考 docs/database.md。因此 Epic Stack 的部署本质上是在搭建一个多实例、零停机、可迁移 SQLite 的生产运行环境。首次部署到 Fly.io9 步完整流程1. 安装并登录 Fly CLI首先安装 Fly CLI官方文档中若fly命令不可用可尝试flyctl然后注册并登录fly auth signup注意如果你有多个 Fly 账号务必确保终端里登录的账号与浏览器中登录的账号一致。可在终端执行fly auth whoami核对邮箱是否与浏览器中登录的 Fly 账号匹配。2. 创建 staging 与 production 两个应用Epic Stack 采用双环境策略为生产与预发布各建一个应用fly apps create [YOUR_APP_NAME] fly apps create [YOUR_APP_NAME]-staging注意应用名必须与 fly.toml 中的app字段保持一致否则无法部署。仓库默认值是app epic-stack-template你需要替换为自己的应用名。3. 初始化 Git 并关联远程仓库git init git remote add origin ORIGIN_URL此时不要推送代码因为后续还需要配置密钥与资源。4. 配置密钥SecretsEpic Stack 运行期依赖的敏感变量通过 Fly secrets 与 GitHub repo secrets 两级注入其在 app/utils/env.server.ts 中被 Zod schema 强制校验缺少任一必填项都会在启动时报Invalid environment variables并中止。GitHub 侧FLY_API_TOKEN进入 Fly 用户设置创建一个 Personal Access Token然后以FLY_API_TOKEN为名添加到 GitHub 仓库的 Encrypted Secrets。它是 .github/workflows/deploy.yml 中container与deploy两个 job 调用flyctl deploy的认证凭证env: FLY_API_TOKEN: ${{ secrets.FLY_API_TOKEN }}。Fly 侧SESSION_SECRET与HONEYPOT_SECRET这两个密钥分别用于会话加密与蜜罐表单防护需同时写入生产与 stagingfly secrets set SESSION_SECRET$(openssl rand -hex 32) HONEYPOT_SECRET$(openssl rand -hex 32) --app [YOUR_APP_NAME] fly secrets set SESSION_SECRET$(openssl rand -hex 32) HONEYPOT_SECRET$(openssl rand -hex 32) --app [YOUR_APP_NAME]-staging注意若未安装 openssl可用 1Password 等密码生成器生成随机串替换$(openssl rand -hex 32)即可。Fly 侧ALLOW_INDEXINGfalse仅 staging为防止搜索引擎索引到重复内容为 staging 设置ALLOW_INDEXINGfalsefly secrets set ALLOW_INDEXINGfalse --app [YOUR_APP_NAME]-staging这一变量的作用可以从源码得到印证在 app/root.tsx 中const allowIndexing ENV.ALLOW_INDEXING ! false当其为false时页面head会输出meta namerobots contentnoindex, nofollow /从而阻止爬虫收录 staging 站点。5. 创建 SQLite 持久化卷SQLite 数据库需要持久卷支撑staging 与 production 各建一个可按需调整大小与区域若更改区域须同步修改 fly.toml 中的primary_regionfly volumes create data --region sjc --size 1 --app [YOUR_APP_NAME] fly volumes create data --region sjc --size 1 --app [YOUR_APP_NAME]-staging该卷名data与 fly.toml 的[mounts]配置对应source data、destination /data。运行时数据库的真实落盘位置在/data/litefs/dbs/sqlite.db而应用通过 LiteFS 的 FUSE 挂载点/litefs/data/sqlite.db访问见 docs/database.md。6. 挂载 ConsulConsul 是 Fly 托管的服务负责在 LiteFS 集群中选举主实例primaryfly consul attach --app [YOUR_APP_NAME] fly consul attach --app [YOUR_APP_NAME]-staging租约机制在 other/litefs.yml 中配置lease.type consul且candidate: ${FLY_REGION PRIMARY_REGION}——这意味着只有处于主区域的实例才有资格成为主节点。PRIMARY_REGION即 fly.toml 的primary_region默认sjc。因此官方建议选择离大多数用户最近的区域作为主区域并在该区域部署至少两个实例以实现零停机部署。7. 创建 Tigris 对象存储fly storage create --app [YOUR_APP_NAME] fly storage create --app [YOUR_APP_NAME]-staging该命令会为两个环境各创建一个 Tigris 对象存储桶用于存放上传文件等对象并自动写入AWS_ACCESS_KEY_ID、AWS_SECRET_ACCESS_KEY、AWS_REGION、AWS_ENDPOINT_URL_S3、BUCKET_NAME等环境变量这些均被 app/utils/env.server.ts 列为必填项。本地开发时对象存储会被完全 mock 掉无需额外处理。8. 提交并推送触发自动部署Epic Stack 内置了完整的 GitHub Actions 工作流 .github/workflows/deploy.yml每次 push 到main分支 → 自动部署production每次 push 到dev分支 → 自动部署staging工作流由lint、typecheck、vitest、playwright、container五个前置 job 把关全部通过后才执行最终deployjobcontainerjob 使用flyctl deploy --build-only --push预构建镜像并打上 commit sha 标签--image-label ${{ github.sha }}deployjob 再以flyctl deploy --image registry.fly.io/app:sha拉取该镜像完成发布同时通过--build-arg COMMIT_SHA${{ github.sha }}把 commit sha 传入构建过程用于 Sentry release 命名等场景。提交命令git add . git commit -m initial deploy git push可选邮件、错误监控与数据库运维的对接部署主链路之外文档还给出三个可选的后续步骤入口均位于 docs 目录邮件服务为 Resend 设置RESEND_API_KEY并配置自定义发信域名见 docs/email.md错误监控为 Sentry 配置SENTRY_DSN、SENTRY_AUTH_TOKEN、SENTRY_ORG、SENTRY_PROJECT等见 docs/monitoring.md。其中SENTRY_AUTH_TOKEN通过构建阶段 secret 注入other/Dockerfile 中RUN --mounttypesecret,idSENTRY_AUTH_TOKEN即为其在 Vite 构建时可用而设计连接生产数据库 / 生产环境种子数据详见 docs/database.md包括fly ssh console直连、Prisma Studio 端口代理、litefs export/import备份恢复以及先加宽后收窄widen then narrow的零停机 schema 迁移策略。使用 fly 本地部署如果只是想在本机验证部署产物直接运行fly deploy该命令会在本机构建镜像并部署到当前 Fly 应用。Fly 平台本身也支持fly launch/fly deploy的本地预览模式可直接把应用跑在本地模拟环境中。使用 Docker / Podman 本地部署不依赖 Fly 的纯本地容器化运行也完全可行核心思路是用 Docker 卷替换 Fly 的 LiteFS 挂载用 Docker ENTRYPOINT 接管容器启动时的初始化命令。第一步裁剪 Dockerfile打开 other/Dockerfile从# prepare for litefs那一行开始即COPY --fromflyio/litefs:0.5.11 ...删到文件末尾替换为# prepare for litefs VOLUME /litefs ADD . . EXPOSE ${PORT} ENTRYPOINT [/myapp/other/docker-entry-point.sh]这一步做了两件事Docker volume用/litefs卷顶替 Fly 上的 LiteFS 挂载点原 Dockerfile 中ENV LITEFS_DIR/litefs/data、DATABASE_PATH$LITEFS_DIR/sqlite.db等路径依赖依然生效Docker ENTRYPOINT容器启动时执行自定义初始化脚本。第二步创建入口脚本在other/docker-entry-point.sh创建以下内容#!/bin/sh -ex npx prisma migrate deploy sqlite3 /litefs/data/sqlite.db PRAGMA journal_mode WAL; sqlite3 /litefs/data/cache.db PRAGMA journal_mode WAL; npm run start该脚本依次完成应用 Prisma 迁移 → 将主数据库与缓存数据库设为 WAL 日志模式降低并发死锁→ 启动 Node 应用监听 8081 端口。这与 other/litefs.yml 中exec段在 Fly 上执行的命令序列npx prisma migrate deploy→ 两段PRAGMA journal_mode WAL→npm start完全对应只是本地版不再依赖if-candidate主实例判定因为本地单容器即单实例。第三步构建与运行# 构建镜像--build-arg 传入短 commit sha docker build -t epic-stack . -f other/Dockerfile --build-arg COMMIT_SHAgit rev-parse --short HEAD # 创建本地 SQLite 数据库挂载点 mkdir ~/litefs # 运行容器注意 FLYfalse否则应用会尝试走 Fly 运行时逻辑 docker run -d -p 8081:8081 -e SESSION_SECRETsomesecret -e HONEYPOT_SECRETsomesecret -e FLYfalse -v ~/litefs:/litefs epic-stack运行后访问http://localhost:8081即可看到应用实例~/litefs目录下即是 SQLite 数据库文件可随时用sqlite3检查容器内INTERNAL_PORT8080、PORT8081见 other/Dockerfile因此-p 8081:8081将宿主机 8081 映射到容器 8081。若使用 Podman把上述命令中的docker替换为podman即可其余参数完全一致。部署相关的关键源码细节为了在真实项目中排查部署问题以下源码路径值得关注fly.tomlinternal_port 8080对应 LiteFS 代理端口[[services.http_checks]]中的/resources/healthcheck与/litefs/health是 Fly 的 HTTP 健康检查路径[build]指定了dockerfile /other/Dockerfile与ignorefile /other/Dockerfile.dockerignoreother/Dockerfile.dockerignore构建时排除/node_modules、.env、/build等避免把本地依赖与敏感文件打进镜像other/litefs.ymlproxy.addr :{INTERNAL_PORT}与proxy.target localhost:{PORT}实现 LiteFS 到应用端口的内网转发exec段是 Fly 上容器启动时的迁移与启动命令链app/utils/litefs.server.ts封装了litefs-js的服务端 APIensurePrimary、getInstanceInfo、getAllInstances等供路由层实现仅在主实例处理写请求等一致性逻辑app/utils/env.server.ts运行期环境变量的 Zod 校验 schema部署时缺失任何必填项都会导致应用拒绝启动是排查部署成功但容器反复崩溃的首选检查点。结语Epic Stack 的部署体系把 Fly.io 的托管能力卷、Consul、Tigris、Secrets与 LiteFS 的单主复制模型组合成一个可复制的生产就绪模板main/dev双分支触发双环境自动部署LiteFS 保证 SQLite 多实例读扩展与零停机迁移Docker 方案则让本地即可 1:1 复现生产运行方式。理解这套链路后无论你是跟随模板自动初始化还是日后手动重建部署都能在 Fly.io 上稳定运行自己的 Epic Stack 应用。【免费下载链接】epic-stackThis is a Full Stack app starter with the foundational things setup and configured for you to hit the ground running on your next EPIC idea.项目地址: https://gitcode.com/GitHub_Trending/ep/epic-stack创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考