Wasp 应用部署到 Railway 完整指南:手动部署服务端、客户端与 PostgreSQL 数据库
2026/9/13 20:12:25 网站建设 项目流程

Wasp 应用部署到 Railway 完整指南:手动部署服务端、客户端与 PostgreSQL 数据库

【免费下载链接】waspThe batteries-included full-stack framework for the AI era. Develop JS/TS web apps (React, Node.js, and Prisma) using declarative code that abstracts away complex full-stack features like auth, background jobs, RPC, email sending, end-to-end type safety, single-command deployment, and more.项目地址: https://gitcode.com/GitHub_Trending/wa/wasp

本篇指南以 Wasp 官方文档 web/docs/guides/deployment/cloud-providers/railway.md 为核心,讲解如何把 Wasp 全栈应用部署到 Railway 云平台:从创建 PostgreSQL 数据库、配置server/client两个服务、设置环境变量,到推送构建产物并完成更新重部署的完整闭环。读完本文,你将掌握基于 Railway CLI 的手动部署全流程,也能理解 Wasp 官方wasp deploy railway自动部署命令在底层替你做了什么,以及.wasp/out构建产物中Dockerfilerailway.jsonCaddyfile各自的作用。

一、自动部署:优先使用 Wasp Deploy

Wasp 官方建议优先使用wasp deploy railway一行命令完成 Railway 上的部署:Wasp CLI 会自动完成客户端、服务端和数据库三个部分的部署,无需手动在控制台创建服务、配置变量。

完整的自动部署教程见 Wasp Deploy 部署到 Railway,本指南聚焦其背后的手动部署流程,帮助你理解自动部署在底层做了什么,也便于在自动部署不满足需求(例如需要自定义域名、自建 PostgreSQL 或精细控制构建方式)时手动完成部署。

二、手动部署前置条件

开始之前,请依次完成以下准备工作:

  1. 在项目根目录运行wasp build,确保应用已构建成功。该命令会在项目内生成.wasp/out目录,其中包含服务端部署所需的Dockerfile与客户端静态构建产物(.wasp/out/web-app/build)。
  2. 注册一个 Railway 账号。
  3. 安装 Railway CLI 命令行工具。
  4. 在终端运行railway login,浏览器会自动打开授权页面完成登录认证。

注意:wasp build每次都会重新生成.wasp/out目录。如果里面保存了上一次部署遗留的自定义文件(如 Caddyfile 手改版本),重新构建前需要先备份。

三、创建 Railway 项目

登录后在 Railway 控制台按以下步骤创建项目:

  1. 打开 Railway 控制台,点击New Project,从下拉菜单中选择Deploy PostgreSQL,为应用创建一个托管的 PostgreSQL 数据库服务。
  2. 项目创建完成后,点击右上角的Create按钮,选择Empty Service创建一个空服务。
  3. 点击新建的服务,将服务名改为server
  4. 再创建一个空服务,命名为client
  5. 点击顶部的Deploy按钮应用这些变更。

此时项目中应有三个服务:PostgreSQLserverclient,分别对应数据库、Wasp 服务端和 Wasp 客户端。

四、部署应用

4.1 配置域名

serverclient两个服务都需要公网域名,以便后续配置环境变量和访问应用:

  1. 进入server实例的Settings标签页,点击Generate Domain
  2. 端口填写8080,然后点击Generate Domain生成域名。
  3. clientSettings下执行同样的操作(端口同样填写8080)。
  4. 复制两个服务的域名,后续配置环境变量时会用到。

端口8080并非随意选择——查看 Wasp 部署包的 ports.ts 可以看到,serverAppPortclientAppPort均定义为8080

// Ports we decided to use for the server and client apps. // These are arbitrary values that are used internally by // Railway containers to run the apps. export const serverAppPort = 8080 as Port; export const clientAppPort = 8080 as Port;

也就是说,Railway 容器内部以8080端口运行 Wasp 服务端与客户端静态服务,因此生成域名时必须指定8080才能让 Railway 的健康检查与流量转发命中正确的端口。

4.2 部署服务端

先部署服务端,操作步骤如下:

  1. 进入.wasp/out构建产物目录:

    cd .wasp/out
  2. 将当前目录链接到刚创建的 Railway 项目:

    railway link

    当 CLI 提示选择服务时,选择server

  3. 回到 Railway 控制台,为server服务配置环境变量。点击server服务,进入Variables标签页,依次添加:

    变量名说明
    DATABASE_URL点击Variable reference并选择DATABASE_URL自动填充PostgreSQL 数据库连接串,由 Railway 自动注入正确值
    WASP_WEB_CLIENT_URLclient域名,例如https://client-production-XXXX.up.railway.app客户端地址,必须带https://前缀
    WASP_SERVER_URLserver域名,例如https://server-production-XXXX.up.railway.app服务端地址,必须带https://前缀
    JWT_SECRET至少 32 字符的随机字符串用于签名认证 JWT 令牌的密钥

    如果你的应用使用了 Wasp 支持的外部认证方式(如 Google、GitHub 登录),还需要额外设置这些认证方式要求的对应环境变量(如 OAuth Client ID / Client Secret 等),详见 外部认证环境变量提醒。

    这四个变量正是自动部署命令wasp deploy railwaysetup阶段自动配置的内容。查看 setup.ts 可以看到,Wasp CLI 会读取 Railway 数据库中DATABASE_URL的变量引用,并自动写入JWT_SECRETWASP_SERVER_URLWASP_WEB_CLIENT_URLDATABASE_URL四项:

    ["--variables", `JWT_SECRET=${jwtSecret}`], ["--variables", `WASP_SERVER_URL=${serverUrl}`], ["--variables", `WASP_WEB_CLIENT_URL=${clientUrl}`], ["--variables", `DATABASE_URL=${databaseUrl}`],
  4. 推送并部署服务端:

    railway up --ci

    使用--ci标志可以将日志输出限制为仅显示构建过程,避免终端被大量日志刷屏。Railway 会自动定位.wasp/out目录中的Dockerfile并据此构建、部署你的服务端。

    从源码层面看,server.ts 中的deployServer通过getServerBuildArtefactsDir定位.wasp/out构建目录,然后调用deployServiceWithStreamingLogs完成部署;而 common.ts 中最终执行的 Railway CLI 命令等价于:

    railway up <部署目录> --service <服务名> --no-gitignore --path-as-root --ci

    其中--no-gitignore确保构建产物(包括.env*之外的敏感文件)被完整打包,--path-as-root则解决 Railway CLI 的一个已知问题,将服务目录作为部署的根路径。

4.3 部署客户端

客户端是静态站点,需要在本地构建后用 Railpack 构建器上传,步骤如下:

  1. 在项目根目录,使用server域名作为 API 地址构建生产版本:

    REACT_APP_API_URL=<url_to_wasp_backend> npx vite build

    构建产物输出到.wasp/out/web-app/build。这个环境变量会被打进前端代码,作为所有 API 请求的基地址,因此必须填写可公网访问的server域名。

  2. .wasp/out/web-app/build目录下创建railway.json,显式指定构建器为 Railpack,避免 Railway 未来变更默认构建器时导致部署行为不一致:

    { "$schema": "https://railway.com/railway.schema.json", "build": { "builder": "RAILPACK" } }
  3. .wasp/out/web-app/build目录下创建Caddyfile,覆盖 Railpack 的默认 Caddyfile,配置静态文件托管与 SPA 回退:

    { admin off persist_config off auto_https off log { format json } servers { trusted_proxies static private_ranges } } :{$PORT:80} { log { format json } respond /health 200 # Security headers header { # Enable cross-site filter (XSS) and tell browsers to block detected attacks X-XSS-Protection "1; mode=block" # Prevent some browsers from MIME-sniffing a response away from the declared Content-Type X-Content-Type-Options "nosniff" # Keep referrer data off of HTTP connections Referrer-Policy "strict-origin-when-cross-origin" # Enable strict Content Security Policy Content-Security-Policy "default-src 'self'; img-src 'self' data: https: *; style-src 'self' 'unsafe-inline' https: *; script-src 'self' 'unsafe-inline' https: *; font-src 'self' data: https: *; connect-src 'self' https: *; media-src 'self' https: *; object-src 'none'; frame-src 'self' https: *;" # Remove Server header -Server } root * . # Handle static files file_server { hide .git hide .env* } # Compression with more formats encode { gzip zstd } # Try files with HTML extension and handle SPA routing # This is where we diverge from the Railpacks's original Caddyfile try_files {path} {path}/index.html /200.html handle_errors { rewrite * /{err.status_code}.html file_server } }

    这份 Caddyfile 在 Railpack 默认模板(面向纯静态站点)的基础上做了关键改动:try_files {path} {path}/index.html /200.html这一行让预渲染(prerender)页面能够被正确返回,同时让未预渲染的路由回退到 SPA 外壳(200.html)。这正是 Wasp 的prerender特性(见 示例应用 main.wasp.ts 中route("RootRoute", "/", page(Main), { prerender: true }))在部署阶段得以生效的原因。此外该 Caddyfile 还开启了 gzip/zstd 压缩、JSON 格式访问日志、/health健康检查响应,以及一组安全响应头(XSS 过滤、MIME 嗅探防护、Referrer Policy、Content Security Policy 等),并隐藏.git.env*文件。

    Wasp 的部署包会在自动部署时自动生成这两份文件。查看 client.ts 中的addRailwayBuildConfig函数可以印证:

    function addRailwayBuildConfig(buildDir: string): void { fs.writeFileSync(path.join(buildDir, "railway.json"), railwayJsonContents); fs.writeFileSync(path.join(buildDir, "Caddyfile"), caddyfileContents); }

    Wasp 明确要求保持文档中的这两份配置与部署包源码同步——源码中注释标注了「更新这份 railway.json 时,务必同步更新部署包与部署文档」,因此你在文档中看到的配置与 client.ts 内嵌的模板完全一致。

  4. 将客户端构建目录链接到client服务:

    cd .wasp/out/web-app/build railway link

    当 CLI 提示选择服务时,选择client

  5. 部署客户端构建产物:

    railway up --ci

完成以上步骤后,你的 Wasp 应用就部署完成了。回到 Railway 控制台,可以看到项目中包含三个服务:PostgreSQL、Server、Client。通过client服务的域名即可访问应用。

五、更新与重新部署

当代码更新后需要重新部署时,按以下顺序操作:

  1. 在项目根目录运行wasp build重新构建应用。注意这会重建整个.wasp/out目录,之前手动放入该目录的文件(如果有)会被清空。

  2. 进入.wasp/out目录,重新部署服务端:

    cd .wasp/out railway up --ci

    Railway 会重新基于.wasp/out中的 Dockerfile 构建镜像并滚动更新server服务。

  3. 在项目根目录重新构建客户端:

    REACT_APP_API_URL=<url_to_wasp_backend> npx vite build

    然后进入客户端构建目录部署:

    cd .wasp/out/web-app/build railway up --ci

    由于wasp build会重建构建目录,railway.jsonCaddyfile需要重新创建(自动部署时由 Wasp CLI 代劳,手动部署则需要再次写入这两份文件)。

六、手动部署与自动部署的对应关系

将手动部署流程与 部署包源码 对比,可以清晰看到wasp deploy railway在底层执行的正是本指南中的手动步骤:

手动步骤自动部署对应实现
railway loginCLI 调用 Railway CLI 完成认证
创建项目与 PostgreSQLsetup.ts 创建项目、数据库与server/client服务
配置DATABASE_URLJWT_SECRETWASP_SERVER_URLWASP_WEB_CLIENT_URLsetup 阶段自动写入四个环境变量
wasp build+ 推送.wasp/outserver.ts 的deployServer定位.wasp/out并执行railway up --ci
写入railway.json+Caddyfileclient.ts 的addRailwayBuildConfig自动生成
构建客户端并推送buildClientserver域名为REACT_APP_API_URL执行 Vite 构建后部署

理解这条对应关系后,无论你是想快速上线(使用wasp deploy railway),还是需要精细控制部署过程的每一步(参考本指南手动操作),都能在 Railway 上稳定运行你的 Wasp 全栈应用。

【免费下载链接】waspThe batteries-included full-stack framework for the AI era. Develop JS/TS web apps (React, Node.js, and Prisma) using declarative code that abstracts away complex full-stack features like auth, background jobs, RPC, email sending, end-to-end type safety, single-command deployment, and more.项目地址: https://gitcode.com/GitHub_Trending/wa/wasp

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询