Railway デプロイメント入門ガイド - モダンなアプリケーション展開を始める
Railwayは、モダンなアプリケーションを簡単にデプロイできるクラウドプラットフォームです。本記事では、Railwayの基本から実践的な使い方まで、包括的に解説します。
Railwayとは
Railwayは、Herokuの代替として注目を集めているPaaS(Platform as a Service)です。GitHubリポジトリと連携し、自動デプロイやデータベース統合、環境変数管理などを提供します。
主な特徴
- シンプルなデプロイ: GitHubプッシュで自動デプロイ
- 豊富なテンプレート: PostgreSQL, Redis, MongoDBなど即座に利用可能
- スケーラブル: 自動スケーリング対応
- 開発者フレンドリー: 優れたUI/UX
- 無料枠: $5/月の無料クレジット付与
はじめてのデプロイ
1. アカウント作成とプロジェクト作成
Railway CLI をインストールします。
# Homebrewでインストール(Mac)
brew install railway
# npmでインストール(全プラットフォーム)
npm i -g @railway/cli
# ログイン
railway login
2. プロジェクトの初期化
# 新規プロジェクト作成
railway init
# 既存のGitHubリポジトリから
railway init --repo your-username/your-repo
3. 環境変数の設定
# 環境変数を設定
railway variables set DATABASE_URL=postgresql://...
railway variables set NODE_ENV=production
# .envファイルから一括設定
railway variables set --from-env
4. デプロイ実行
# デプロイ
railway up
# ログ確認
railway logs
# ステータス確認
railway status
GitHubとの連携
自動デプロイの設定
Railwayダッシュボードから設定します。
# railway.json(オプション設定ファイル)
{
"$schema": "https://railway.app/railway.schema.json",
"build": {
"builder": "NIXPACKS",
"buildCommand": "npm run build"
},
"deploy": {
"startCommand": "npm start",
"healthcheckPath": "/health",
"restartPolicyType": "ON_FAILURE",
"restartPolicyMaxRetries": 10
}
}
ブランチデプロイ
# mainブランチは本番環境
# developブランチはステージング環境として別途デプロイ可能
ダッシュボードで各ブランチに対して異なる環境を設定できます。
データベースの追加
PostgreSQLの追加
# PostgreSQLプラグインを追加
railway add
# PostgreSQLを選択すると自動的に環境変数が設定される
# DATABASE_URL が自動的に利用可能に
アプリケーションコードでの使用例:
// Next.js + Prisma の例
// prisma/schema.prisma
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}
// データベース接続
import { PrismaClient } from '@prisma/client';
const prisma = new PrismaClient();
export default prisma;
Redisの追加
# Redisプラグインを追加
railway add
# REDIS_URL が自動的に設定される
使用例:
// Node.js + ioredis
import Redis from 'ioredis';
const redis = new Redis(process.env.REDIS_URL);
// キャッシュの設定
await redis.set('key', 'value', 'EX', 3600);
// キャッシュの取得
const value = await redis.get('key');
フレームワーク別デプロイ例
Next.js
// package.json
{
"scripts": {
"dev": "next dev",
"build": "next build",
"start": "next start"
}
}
// next.config.js
/** @type {import('next').NextConfig} */
const nextConfig = {
output: 'standalone', // Railway推奨
experimental: {
serverActions: true
}
};
module.exports = nextConfig;
環境変数の設定:
railway variables set NEXT_PUBLIC_API_URL=https://api.yourapp.com
railway variables set DATABASE_URL=postgresql://...
Express.js
// server.js
import express from 'express';
const app = express();
const PORT = process.env.PORT || 3000;
app.get('/health', (req, res) => {
res.json({ status: 'ok' });
});
app.listen(PORT, () => {
console.log(`Server running on port ${PORT}`);
});
// package.json
{
"scripts": {
"start": "node server.js",
"dev": "nodemon server.js"
}
}
Python (FastAPI)
# main.py
from fastapi import FastAPI
import os
app = FastAPI()
@app.get("/health")
def health_check():
return {"status": "ok"}
if __name__ == "__main__":
import uvicorn
port = int(os.environ.get("PORT", 8000))
uvicorn.run(app, host="0.0.0.0", port=port)
# pyproject.toml
[tool.poetry]
name = "myapp"
version = "0.1.0"
[tool.poetry.dependencies]
python = "^3.11"
fastapi = "^0.109.0"
uvicorn = "^0.27.0"
Astro
// astro.config.mjs
import { defineConfig } from 'astro/config';
import node from '@astrojs/node';
export default defineConfig({
output: 'server',
adapter: node({
mode: 'standalone'
})
});
// package.json
{
"scripts": {
"build": "astro build",
"start": "node ./dist/server/entry.mjs"
}
}
カスタムドメインの設定
ドメインの追加
# CLIから追加
railway domain
# カスタムドメインを指定
# ダッシュボードで設定することも可能
DNS設定
Railwayが提供するCNAMEレコードをDNSプロバイダーに設定します。
# 例: Cloudflare, Google Domains, Namecheapなど
Type: CNAME
Name: www (またはサブドメイン)
Value: your-app.up.railway.app
SSL証明書
Railwayは自動的にLet’s EncryptのSSL証明書を発行・更新します。
// 設定不要、自動的にHTTPSが有効化
// http:// へのアクセスは自動的にhttps:// へリダイレクト
環境変数の管理
環境ごとの変数管理
# production環境
railway variables set --environment production API_KEY=prod_key_123
# staging環境
railway variables set --environment staging API_KEY=staging_key_456
# 現在の環境の変数を確認
railway variables
シークレットの安全な管理
# 機密情報の設定
railway variables set DATABASE_PASSWORD=$(openssl rand -base64 32)
railway variables set JWT_SECRET=$(openssl rand -base64 64)
# GitHub Actionsとの連携
railway variables set GITHUB_TOKEN=${{ secrets.GITHUB_TOKEN }}
.envファイルとの同期
# ローカルの.envから同期
railway variables set --from-env
# Railwayから.envファイルを生成
railway variables > .env.railway
モニタリングとログ
リアルタイムログ
# ログをリアルタイム表示
railway logs --tail
# 特定のサービスのログ
railway logs --service web
# エラーログのみフィルタ
railway logs | grep ERROR
メトリクスの確認
ダッシュボードで以下が確認できます:
- CPU使用率
- メモリ使用量
- ネットワークトラフィック
- リクエスト数
- レスポンスタイム
アラート設定
// アプリケーションレベルでのヘルスチェック
app.get('/health', async (req, res) => {
try {
// データベース接続確認
await prisma.$queryRaw`SELECT 1`;
// Redis接続確認
await redis.ping();
res.json({
status: 'healthy',
timestamp: new Date().toISOString(),
uptime: process.uptime()
});
} catch (error) {
res.status(503).json({
status: 'unhealthy',
error: error.message
});
}
});
スケーリング戦略
垂直スケーリング
Railwayのプランをアップグレードすることで、より多くのリソースを確保できます。
# リソース使用状況の確認
railway status
# メトリクスの確認
railway metrics
水平スケーリング(複数インスタンス)
// railway.json
{
"deploy": {
"numReplicas": 3,
"healthcheckPath": "/health",
"healthcheckTimeout": 100
}
}
データベースのスケーリング
# PostgreSQLのリソースをアップグレード
# ダッシュボードから設定変更
CI/CDパイプライン
GitHub Actionsとの連携
# .github/workflows/deploy.yml
name: Deploy to Railway
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Install Railway
run: npm i -g @railway/cli
- name: Deploy to Railway
run: railway up
env:
RAILWAY_TOKEN: ${{ secrets.RAILWAY_TOKEN }}
テストとデプロイの自動化
# .github/workflows/ci-cd.yml
name: CI/CD Pipeline
on:
push:
branches: [main, develop]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: '20'
- name: Install dependencies
run: npm ci
- name: Run tests
run: npm test
- name: Run linter
run: npm run lint
deploy:
needs: test
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/main'
steps:
- uses: actions/checkout@v3
- name: Deploy to Railway
run: |
npm i -g @railway/cli
railway up
env:
RAILWAY_TOKEN: ${{ secrets.RAILWAY_TOKEN }}
コスト最適化
無料枠の活用
# 現在の使用状況を確認
railway usage
# 月額コストの見積もり
railway pricing
スリープ機能の活用
// railway.json
{
"deploy": {
"sleepAfterMinutesOfInactivity": 30
}
}
リソース最適化
// メモリリークの防止
process.on('SIGTERM', async () => {
console.log('SIGTERM received, closing server...');
await server.close();
await prisma.$disconnect();
await redis.quit();
process.exit(0);
});
// メモリ使用量のモニタリング
setInterval(() => {
const used = process.memoryUsage();
console.log('Memory usage:', {
rss: `${Math.round(used.rss / 1024 / 1024)}MB`,
heapTotal: `${Math.round(used.heapTotal / 1024 / 1024)}MB`,
heapUsed: `${Math.round(used.heapUsed / 1024 / 1024)}MB`
});
}, 60000);
トラブルシューティング
よくあるエラーと対処法
ビルドエラー
# ビルドログを確認
railway logs --deployment
# ローカルで再現
railway run npm run build
# Nixpacksの設定を確認
railway run nixpacks plan
接続エラー
// データベース接続のリトライ処理
import { PrismaClient } from '@prisma/client';
const prisma = new PrismaClient({
datasources: {
db: {
url: process.env.DATABASE_URL
}
},
log: ['error', 'warn'],
});
// 接続テスト
prisma.$connect()
.then(() => console.log('Database connected'))
.catch(err => console.error('Database connection error:', err));
メモリ不足
// package.json - Node.jsのメモリ上限を増やす
{
"scripts": {
"start": "node --max-old-space-size=2048 server.js"
}
}
デバッグテクニック
# リモート環境でコマンド実行
railway run bash
# 環境変数の確認
railway run env
# データベースに接続
railway connect postgres
ベストプラクティス
1. 環境変数の分離
// config/index.js
const config = {
nodeEnv: process.env.NODE_ENV || 'development',
port: parseInt(process.env.PORT || '3000'),
database: {
url: process.env.DATABASE_URL,
poolSize: parseInt(process.env.DB_POOL_SIZE || '10')
},
redis: {
url: process.env.REDIS_URL
},
api: {
baseUrl: process.env.API_BASE_URL
}
};
export default config;
2. ヘルスチェックの実装
app.get('/health', async (req, res) => {
const health = {
uptime: process.uptime(),
timestamp: Date.now(),
status: 'ok',
checks: {}
};
try {
await prisma.$queryRaw`SELECT 1`;
health.checks.database = 'ok';
} catch (error) {
health.checks.database = 'error';
health.status = 'degraded';
}
const statusCode = health.status === 'ok' ? 200 : 503;
res.status(statusCode).json(health);
});
3. グレースフルシャットダウン
let isShuttingDown = false;
process.on('SIGTERM', async () => {
if (isShuttingDown) return;
isShuttingDown = true;
console.log('Received SIGTERM, starting graceful shutdown...');
// 新規リクエストを拒否
server.close(async () => {
console.log('HTTP server closed');
// DB接続を閉じる
await prisma.$disconnect();
console.log('Database disconnected');
// Redis接続を閉じる
await redis.quit();
console.log('Redis disconnected');
process.exit(0);
});
// 30秒以内に終了しなければ強制終了
setTimeout(() => {
console.error('Forced shutdown after timeout');
process.exit(1);
}, 30000);
});
4. セキュリティ対策
import helmet from 'helmet';
import rateLimit from 'express-rate-limit';
app.use(helmet());
const limiter = rateLimit({
windowMs: 15 * 60 * 1000, // 15分
max: 100, // 最大100リクエスト
message: 'Too many requests from this IP'
});
app.use('/api/', limiter);
// CORSの設定
app.use(cors({
origin: process.env.ALLOWED_ORIGINS?.split(',') || '*',
credentials: true
}));
まとめ
Railwayは、モダンなアプリケーションを簡単にデプロイできる強力なプラットフォームです。GitHub連携による自動デプロイ、豊富なデータベーステンプレート、使いやすいCLI、そして優れた開発者体験により、個人開発から本格的なプロダクションまで幅広く対応できます。
本記事で紹介した設定やベストプラクティスを活用することで、信頼性が高く、スケーラブルなアプリケーションをRailway上で運用できます。まずは無料枠から始めて、Railwayの便利さを体験してみてください。