John Wick

Deploy a railway python bot that never sleeps — port binding, health checks, self-ping, and crash recovery using StayPresent.

在 Railway 上使用 StayPresent 執行 Python Bot 而不休眠

Railway 可自動偵測 Python 專案,並在幾分鐘內完成部署,但 railway python bot — 例如 Discord bot、Telegram bot 或爬蟲 — 仍會遇到每個 PaaS 都會出現的核心問題:平台期望有一個面向 HTTP 的程序,而你的 bot 事件迴圈或閘道連線並不會自然提供這樣的程序。本指南將介紹如何部署一個在 Railway 上保持線上的 bot,並使用 StayPresent 來填補這項空缺。

目錄

  1. Railway 如何偵測並執行 Python 應用程式
  2. $PORT 要求
  3. 設定 StayPresent
  4. Railway 儀表板中的健康檢查
  5. 針對對閒置敏感方案的自我 ping
  6. 當機恢復
  7. 完整可運作範例
  8. 最佳實踐
  9. 常見錯誤
  10. 常見問題
  11. 結論

Railway 如何偵測並執行 Python 應用程式

Railway 可從 requirements.txt(或 pyproject.toml)自動偵測 Python 專案,並透過 Nixpacks 自動為其建置容器,無需 Dockerfile。接著會啟動你的應用程式,並期望它綁定 Railway 透過 PORT 環境變數指定的連接埠,以便其自身的路由和健康檢查可以存取。

$PORT 要求

這是幾乎所有現代 PaaS 都採用的相同模式:從環境讀取 PORT,而非硬式編碼。

import os
import staypresent

staypresent.run(
    "bot.py",
    port=int(os.getenv("PORT", 8080)),
)

Enter fullscreen mode Exit fullscreen mode

如果你的 bot 完全沒有綁定此連接埠 — 這對於 Discord 或 Telegram bot 來說是正常且預期的行為 — 即使你的 bot 本身可能運作正常,Railway 的健康檢查(如果已啟用)仍會將部署標記為不健康。

設定 StayPresent

安裝 production 額外套件,讓 Waitress 處理服務,而非 Flask 的開發伺服器:

pip install staypresent[prod]

Enter fullscreen mode Exit fullscreen mode

你的 main.py

import os
import staypresent

staypresent.web.json({
    "status": "running",
    "service": "my-telegram-bot",
})

staypresent.run(
    "bot.py",
    port=int(os.getenv("PORT", 8080)),
)

Enter fullscreen mode Exit fullscreen mode

Railway 的啟動指令僅為:

python main.py

Enter fullscreen mode Exit fullscreen mode

Railway 儀表板中的健康檢查

如果你已為服務啟用 Railway 的健康檢查功能,可以將其指向 StayPresent 內建的 /health 端點,該端點一律會回傳 {"status": "ok"} — 無論你在根路由設定了什麼:

staypresent.web.json({"status": "running"})
# /health still returns {"status": "ok"} regardless

Enter fullscreen mode Exit fullscreen mode

這將平台層級的健康監控與你在 / 提供給人類或自身工具的自訂狀態酬載分開。

針對對閒置敏感方案的自我 ping

是否適用基於閒置的休眠,取決於你特定的 Railway 方案和設定 — 在假設任何行為之前,請務必先查看 Railway 目前的定價和使用文件。如果你的部署確實適用,staypresent.cron() 會針對你自己的公開 URL 產生對外流量,以避免被視為閒置:

import staypresent

staypresent.cron(
    "https://my-app.up.railway.app",
    interval=240,
)

Enter fullscreen mode Exit fullscreen mode

與任何平台一樣,這必須指向實際的公開 URL — ping 0.0.0.0127.0.0.1 永遠不會離開機器,因此對閒置偵測沒有任何影響。

當機恢復

Bot 可能因各種原因當機,而 Railway 不會自動重新啟動在容器 內部 死亡的子程序,除非容器本身退出。StayPresent 直接處理此內部層級:

staypresent.run(
    "bot.py",
    port=int(os.getenv("PORT", 8080)),
    restart_on_crash=True,
    max_restarts=5,
    restart_delay=2.0,
    restart_reset_after=60.0,
)

Enter fullscreen mode Exit fullscreen mode

如果最終耗盡了重新啟動次數,StayPresent 會以 bot 原本的退出代碼退出整個程序 — 讓 Railway 自己的部署重新啟動政策作為最後的後盾。

完整可運作範例

import os
import staypresent

staypresent.web.json({"status": "running"})

staypresent.cron("https://my-app.up.railway.app", interval=240)

staypresent.run(
    "bot.py",
    port=int(os.getenv("PORT", 8080)),
    threads=8,
    restart_on_crash=True,
    max_restarts=5,
)

Enter fullscreen mode Exit fullscreen mode

最佳實踐

  • 一律動態讀取 PORT — Railway 會為每次部署指定連接埠,且在不同環境中可能有所不同。
  • 如果你的根路由提供自訂內容,請將任何設定的健康檢查指向 /health 而非 /
  • 對於任何接收真實流量的部署,請務必安裝 prod 額外套件,而不僅是保持連線的 ping。

常見錯誤

  • 硬式編碼 port=8080 而非讀取 os.getenv("PORT", 8080) — 這在某些設定中可能有效,但在其他情況下可能靜默失敗,視 Railway 的設定方式而定。
  • 假設 Railway 的休眠行為與 Render 相同。 各平台的政策不同,且會隨時間改變 — 請查閱 Railway 自己的文件以確認目前行為,而非自行假設。
  • 因為「Railway 反正會重新啟動當機的部署」而跳過當機恢復。 Railway 自己的重新啟動政策是在容器層級運作;bot 子程序在仍在執行的容器內部當機,是另一種失敗模式,StayPresent 會直接處理。

常見問題

Railway 是否需要 Dockerfile?
不需要 — Railway 可透過 Nixpacks 自動偵測並建置 Python 專案,無需 Dockerfile,但如果你偏好明確控制,也支援 Dockerfile。

我可以重複使用 Render 部署的同一個 main.py 嗎?
可以 — 由於兩個平台都遵循相同的 $PORT 慣例,相同的進入點通常可以在兩者之間無需修改即可運作。

我在 Railway 上需要 staypresent.cron() 嗎?
只有在你的特定方案/設定會受到基於閒置的休眠影響時才需要 — 在決定之前,請先查閱 Railway 目前關於你方案的文件。

結論

一個 railway python bot 保持線上的方式與任何現代 PaaS 上的 bot 相同:綁定指定的連接埠、公開專用的健康端點,並讓 StayPresent 監督 bot 程序本身。這個設定與 Railway、Render、Koyeb 和 Heroku 幾乎相同,這正是讓 StayPresent 成為一次性投資,而非每個平台都要重複撰寫樣板的關鍵。

pip install staypresent[prod]

Enter fullscreen mode Exit fullscreen mode