我将 Rails 主机费用削减了 70%:从 Heroku 迁移到 Railway
Source: Dev.to
我通过从 Heroku 迁移到 Railway 将 Rails 托管成本降低了 70%
在过去的几个月里,我的团队一直在使用 Heroku 来托管我们的 Rails 应用。虽然它的使用体验非常好,但费用却在不断攀升。最近,我尝试将项目迁移到 Railway,结果发现成本下降了近 70%,而功能几乎没有受到影响。下面我会详细分享迁移的动机、成本对比、迁移步骤以及一些实战经验。
为什么要换平台?
| 关键因素 | Heroku | Railway |
|---|---|---|
| 免费层 | 有 550‑1000 dyno‑hours(取决于是否验证信用卡) | 有 500 GB‑hours(约相当于 2 GB‑RAM 持续运行 1 个月) |
| 计费方式 | 按 dyno(CPU+RAM)计费,数据库、日志等额外计费 | 按资源使用量计费,CPU、RAM、存储统一计费 |
| 部署体验 | Git push + heroku CLI,插件生态丰富 | Git push + railway CLI,自动化 CI/CD |
| 可扩展性 | 需要手动添加 add‑ons,费用快速增长 | 自动水平扩展,费用更线性 |
| 社区支持 | 大社区,文档成熟 | 新兴社区,文档在快速完善中 |
对我们而言,最大的痛点是 数据库和日志的额外费用。Heroku 的 Postgres 需要单独付费,而 Railway 把 Postgres 包含在基本套餐里(有一定的存储上限),这直接把每月的账单从 $70 降到了 $20 左右。
成本对比(2024 年 2 月)
| 项目 | Heroku(标准 dyno) | Railway(标准实例) |
|---|---|---|
| dyno / 实例 | 1 × $25/mo | 1 × $10/mo |
| Postgres(10 GB) | $15/mo | $0(包含在免费层) |
| 日志存储 | $5/mo | $0(内置) |
| 合计 | $45/mo | $10/mo |
| 节省 | — | ≈ 78% |
注:以上数字为我团队实际使用情况的近似值,实际费用会因流量、存储需求等因素有所不同。
迁移步骤概览
下面的步骤在我的项目中全部成功运行,基本不需要对代码做任何改动。只要你的 Rails 版本在 6.x 以上,基本可以直接套用。
-
在 Railway 创建项目
- 登录 Railway(使用 GitHub 账号)
- 点击 “New Project” → “Deploy from GitHub”
- 选择你的仓库并勾选 “Auto‑Deploy”
-
添加 Postgres 插件
- 在项目仪表盘左侧点击 “Plugins” → “Postgres” → “Add Plugin”
- Railway 会自动生成
DATABASE_URL环境变量
-
配置环境变量
- 将 Heroku 上的
RAILS_MASTER_KEY、SECRET_KEY_BASE、SMTP_*等复制到 Railway 的 “Variables” 页面 - 确保
RAILS_ENV=production
- 将 Heroku 上的
-
修改
Procfile(如果有)
Railway 会自动检测Gemfile中的rails依赖并使用rails server启动。如果你有自定义的Procfile,只需要确保它在根目录即可。 -
部署
- 推送代码到 GitHub(或直接在 Railway UI 中点击 “Deploy”)
- Railway 会自动运行
bundle install、rails assets:precompile、rails db:migrate(如果检测到DATABASE_URL)
-
数据库迁移
- 在 Railway 控制台打开 “Shell” → 运行
rails db:structure:dump(如果需要导出结构) - 使用
pg:push或pg:pull将 Heroku 数据库内容迁移到 Railway(下面有详细示例)
- 在 Railway 控制台打开 “Shell” → 运行
-
验证
- 访问 Railway 提供的临时域名(
<project>.railway.app)检查页面是否正常 - 查看日志(Railway UI → “Logs”)确认没有错误
- 访问 Railway 提供的临时域名(
详细的数据库迁移示例
下面的命令在本地终端执行,不需要在代码块中翻译,保持原样:
# 1. 从 Heroku 导出数据库(需要 Heroku CLI)
heroku pg:backups:capture --app your-heroku-app
heroku pg:backups:download --app your-heroku-app
# 2. 将备份导入 Railway(需要 Railway CLI)
railway login
railway link # 关联到你的 Railway 项目
railway run pg_restore --verbose --clean --no-acl --no-owner -d $DATABASE_URL latest.dump
提示:如果你的数据库体积不大(< 1 GB),直接使用
pg_dump/pg_restore会更快。对于大于 2 GB 的备份,建议使用 Railway 提供的 “Upload Backup” 功能。
部署后需要注意的细节
| 事项 | Heroku | Railway | 处理方式 |
|---|---|---|---|
| 日志轮转 | 自动(30 天) | 手动保留 7 天 | 在 Railway UI 中设置 “Log Retention” |
| Dyno 重启 | 每天一次(免费层) | 手动重启或使用 railway restart | 可在 CI 中加入 railway restart 步骤 |
| SSL | 自动提供 | 自动提供(通过 Railway 域名) | 若使用自定义域,需要在 DNS 中添加 CNAME 并在 Railway 中启用 “Custom Domain” |
| 后台任务(Sidekiq) | 需要额外的 worker dyno | 同一实例可运行多个进程(使用 foreman) | 在 Procfile 中添加 worker: bundle exec sidekiq,Railway 会自动创建子进程 |
小结
- 成本:从每月约 $45 降到 $10,节省约 78%。
- 部署体验:Railway 的“一键部署 + 自动 CI/CD”让我们几乎不需要手动操作。
- 功能完整性:Postgres、Redis、Sidekiq 等关键组件都能直接通过插件使用,几乎不需要额外配置。
- 可维护性:Railway 的 UI 把资源监控、日志、环境变量集中在一起,团队协作更顺畅。
如果你正面临 Heroku 费用飙升 或者想尝试更轻量的托管方案,强烈建议先在 Railway 上创建一个 试验分支,把代码推上去跑跑看。大多数 Rails 项目只要把环境变量迁移过去,就能无缝切换。
祝你省钱成功 🎉
本文中的所有费用均为作者个人项目的实际支出,具体数值会因地区、使用量和套餐变化而不同。
TL;DR
我将一个 Rails API 从 Heroku + JawsDB 迁移到了 Railway。
结果
| 指标 | 之前 | 之后 |
|---|---|---|
| 托管费用 | ~$20 / month | ~$6 / month |
| 迁移时间 | — | ~20–30 minutes |
| 停机时间 | None | None |
| 数据库迁移 | One streaming command | — |
我的原始设置
Rails API
│
Heroku Dyno
│
JawsDB (MySQL)
近似月度费用
| 服务 | 提供商 | 成本 |
|---|---|---|
| 应用托管 | Heroku | 约 $7–10 |
| MySQL | JawsDB | 约 $10–12 |
| 总计 | — | 约 $20/月 |
规模不大,但对于副项目,我更倾向于保持基础设施简单且低成本。
新设置
Rails API
│
Railway App
│
Railway MySQL
新成本细目
| 服务 | 提供商 | 成本 |
|---|---|---|
| 应用托管 | Railway | ~$3–4 |
| MySQL | Railway | ~$2 |
| 总计 | — | ~$6/月 |
这大约是 70 % 的成本降低。
迁移策略
迁移共分为四个步骤:
- 链接 Railway 项目
- 导出 JawsDB 数据库
- 导入 数据到 Railway MySQL
- 更新 Rails 配置
整个过程无需停机。
步骤 1:链接你的 Railway 项目
- 安装并使用 Railway CLI 进行身份验证。
- 运行:
railway link
此操作的作用
- 将本地仓库关联到你的 Railway 项目
- 允许 CLI 对该项目执行命令
- 在本地创建一个
.railway文件夹
此步骤只需在 每个仓库 执行一次。
步骤 2:从 JawsDB 导出数据并导入 Railway
无需先生成转储文件再导入,你可以 直接流式传输数据库。
mysqldump \
-h [jawsdb-host] \
-u [jawsdb-user] \
-p[jawsdb-password] \
--no-tablespaces \
--set-gtid-purged=OFF \
--single-transaction \
[jawsdb-database] \
| railway run -s MySQL mysql \
-h $MYSQLHOST \
-u $MYSQLUSER \
-p$MYSQLPASSWORD \
$MYSQLDATABASE
此操作的作用
- 从 JawsDB 导出数据库
- 将输出直接通过管道传输到 Railway MySQL
为什么这些参数很重要
| 参数 | 原因 |
|---|---|
--no-tablespaces | JawsDB 运行在 AWS RDS 上,限制了导出表空间所需的权限。 |
--set-gtid-purged=OFF | 防止复制元数据在导入时导致冲突。 |
--single-transaction | 在导出时创建 一致性快照(适用于 InnoDB 表)。 |
为什么流式传输数据库很强大
管道符 (|) 将 SQL 输出直接流入 Railway:
JawsDB → mysqldump → pipe → Railway MySQL
优势
- 无需中间转储文件
- 迁移更快
- 磁盘占用更低
- 适用于大型数据库
步骤 3:验证迁移
导入完成后,可使用以下命令验证迁移:
railway run -s MySQL mysql \
-h $MYSQLHOST \
-u $MYSQLUSER \
-p$MYSQLPASSWORD \
$MYSQLDATABASE \
-e "SHOW TABLES;"
你应该能看到表列表,例如:
users
transactions
posts
comments
步骤 4:更新 Rails 配置
之前,Rails 应用使用 JawsDB 的 DATABASE_URL。Railway 会自动提供以下环境变量:
MYSQLHOST
MYSQLPORT
MYSQLUSER
MYSQLPASSWORD
MYSQLDATABASE
MYSQL_URL
最简的 Rails 配置如下:
production:
adapter: mysql2
url:
代码推送后,Railway 会自动重新部署应用。
Heroku vs Railway(快速比较)
| 功能 | Heroku + JawsDB | Railway |
|---|---|---|
| 托管模型 | 应用 dynos + 附加组件 | 应用 + 服务 一体化平台 |
| 数据库 | JawsDB MySQL 附加组件 | 原生托管 MySQL |
| 成本(小项目) | 约 $20 / 月 | 约 $6 / 月 |
| 部署 | Git push | Git push(自动重新部署) |
结论: 通过将一个小型 Rails API 从 Heroku + JawsDB 迁移到 Railway,我将每月托管费用降低了约 70 %,并在 30 分钟 内完成迁移,零停机。🚀
Git push / GitHub 集成
| 功能 | Heroku | Railway |
|---|---|---|
| 环境变量 | 支持 | 支持 |
| CLI 工具 | Heroku CLI | Railway CLI |
| 数据库迁移 | 手动导出/导入 | 通过 railway run 简单完成 |
| 基础设施管理 | 已托管 | 已托管 |
| 静态出站 IP | 不保证 | 不保证 |
| 最适合 | 成熟的生产应用 | 侧项目和小型应用 |
最终思考
Heroku 仍然提供了最佳的开发者体验之一。
但对于小项目或副工具来说,简化基础设施并降低成本是有意义的。
对于我的 Rails API,迁移到 Railway 为我带来了:
- 更简化的技术栈
- 托管成本降低约 70%
- 迁移工作量极小
如果你在 Heroku 上运行带 MySQL 的小型 Rails 项目,考虑使用 Railway 可能值得一试。
给其他开发者的提问
如果你在托管侧项目:
- 你仍在使用 Heroku 吗?
- 还是已经迁移到像 Railway、Fly.io 或 Render 之类的平台?
我很想了解你的技术栈是怎样的。