Render.comでアプリをデプロイする完全ガイド - 無料枠から本番運用まで


Render.comでアプリをデプロイする完全ガイド

Render.comとは

Renderは、モダンなクラウドプラットフォームで、Webアプリケーション、API、データベース、静的サイトを簡単にデプロイできます。Herokuの後継として注目され、GitHubとのシームレスな統合、自動デプロイ、無料枠の提供が特徴です。

Renderの特徴

1. GitHubとの完全統合

# コミット → 自動デプロイ
git push origin main
# ↓
# Renderが自動的にビルド・デプロイ

2. 豊富なサービスタイプ

  • Web Service - Node.js、Python、Ruby、Go等のWebアプリ
  • Static Site - React、Vue、Next.js等の静的サイト
  • Background Worker - バックグラウンドジョブ
  • Cron Job - 定期実行タスク
  • PostgreSQL - マネージドデータベース
  • Redis - マネージドキャッシュ

3. 無料枠あり

  • 静的サイト: 完全無料
  • Web Service: 750時間/月(1インスタンス)
  • PostgreSQL: 90日間無料(その後$7/月)

Heroku/Vercelとの比較

項目RenderVercelHeroku
無料枠あり(制限付き)あり(Hobby)廃止
静的サイト無料無料非対応
データベースPostgreSQL内蔵外部連携アドオン
自動スリープ15分なし30分(廃止)
カスタムドメイン無料無料有料
料金$7〜/月$20〜/月$7〜/月

アカウント作成

1. サインアップ

# https://render.com にアクセス
# "Get Started for Free" をクリック
# GitHubアカウントで認証

2. GitHub連携

Settings → GitHub → Install Render
→ リポジトリアクセス許可

静的サイトのデプロイ

React/Viteアプリ

1. プロジェクト準備

# Viteプロジェクト作成
npm create vite@latest my-app -- --template react
cd my-app
npm install

# ビルドコマンド確認
npm run build
# → distディレクトリが生成される

2. Renderダッシュボードで設定

New → Static Site
→ GitHubリポジトリ選択
→ 設定:
  - Name: my-react-app
  - Branch: main
  - Build Command: npm run build
  - Publish Directory: dist
→ Create Static Site

3. 自動デプロイ

# コードを変更してpush
git add .
git commit -m "Update homepage"
git push origin main

# Renderが自動的にビルド・デプロイ

Next.jsアプリ(静的エクスポート)

// next.config.js
/** @type {import('next').NextConfig} */
const nextConfig = {
  output: 'export',  // 静的エクスポート
};

module.exports = nextConfig;

Render設定:

Build Command: npm run build
Publish Directory: out

カスタムドメイン設定

Settings → Custom Domains
→ Add Custom Domain
→ ドメイン入力: example.com
→ DNS設定(A/CNAMEレコード追加)

DNSレコード例:

Type: CNAME
Name: www
Value: my-app.onrender.com

Webサービスのデプロイ

Node.js + Expressアプリ

1. プロジェクト構成

// server.js
const express = require('express');
const app = express();
const PORT = process.env.PORT || 3000;

app.get('/', (req, res) => {
  res.json({ message: 'Hello from Render!' });
});

app.get('/health', (req, res) => {
  res.json({ status: 'ok' });
});

app.listen(PORT, '0.0.0.0', () => {
  console.log(`Server running on port ${PORT}`);
});
// package.json
{
  "name": "my-api",
  "version": "1.0.0",
  "scripts": {
    "start": "node server.js"
  },
  "dependencies": {
    "express": "^4.18.2"
  }
}

2. Render設定

New → Web Service
→ リポジトリ選択
→ 設定:
  - Name: my-express-api
  - Environment: Node
  - Region: Oregon (US West)
  - Branch: main
  - Build Command: npm install
  - Start Command: npm start
  - Instance Type: Free
→ Create Web Service

Python + Flaskアプリ

# app.py
from flask import Flask, jsonify
import os

app = Flask(__name__)

@app.route('/')
def hello():
    return jsonify(message='Hello from Render!')

@app.route('/health')
def health():
    return jsonify(status='ok')

if __name__ == '__main__':
    port = int(os.environ.get('PORT', 5000))
    app.run(host='0.0.0.0', port=port)
# requirements.txt
Flask==3.0.0
gunicorn==21.2.0

Render設定:

Build Command: pip install -r requirements.txt
Start Command: gunicorn app:app

環境変数の設定

Settings → Environment
→ Add Environment Variable

例:
DATABASE_URL: postgresql://...
API_KEY: your-secret-key
NODE_ENV: production

コードで使用:

// Node.js
const apiKey = process.env.API_KEY;
const dbUrl = process.env.DATABASE_URL;
# Python
import os
api_key = os.environ.get('API_KEY')
db_url = os.environ.get('DATABASE_URL')

データベース連携

PostgreSQLの作成

New → PostgreSQL
→ 設定:
  - Name: my-database
  - Database: myapp
  - User: myuser
  - Region: Oregon (US West)
  - Instance Type: Free
→ Create Database

Web ServiceからDB接続

1. 環境変数の追加

Web Service → Environment
→ Add Environment Variable from Database
→ DATABASE_URL を選択

2. Node.js + pg

// db.js
const { Pool } = require('pg');

const pool = new Pool({
  connectionString: process.env.DATABASE_URL,
  ssl: {
    rejectUnauthorized: false
  }
});

module.exports = pool;
// server.js
const pool = require('./db');

app.get('/users', async (req, res) => {
  try {
    const result = await pool.query('SELECT * FROM users');
    res.json(result.rows);
  } catch (err) {
    res.status(500).json({ error: err.message });
  }
});

3. Prismaを使う場合

// schema.prisma
datasource db {
  provider = "postgresql"
  url      = env("DATABASE_URL")
}

generator client {
  provider = "prisma-client-js"
}

model User {
  id    Int     @id @default(autoincrement())
  email String  @unique
  name  String?
}
// package.json
{
  "scripts": {
    "build": "prisma generate && prisma migrate deploy",
    "start": "node server.js"
  }
}

Render設定:

Build Command: npm install && npm run build
Start Command: npm start

render.yamlでインフラをコード化

基本構成

# render.yaml
services:
  # Web Service
  - type: web
    name: my-app
    env: node
    region: oregon
    plan: free
    buildCommand: npm install
    startCommand: npm start
    envVars:
      - key: NODE_ENV
        value: production
      - key: DATABASE_URL
        fromDatabase:
          name: my-database
          property: connectionString

  # Background Worker
  - type: worker
    name: my-worker
    env: node
    region: oregon
    plan: free
    buildCommand: npm install
    startCommand: node worker.js
    envVars:
      - key: REDIS_URL
        fromService:
          name: my-redis
          type: redis
          property: connectionString

# データベース
databases:
  - name: my-database
    databaseName: myapp
    user: myuser
    region: oregon
    plan: free

# Redis
  - name: my-redis
    region: oregon
    plan: free

マイクロサービス構成

# render.yaml
services:
  # Frontend (Static Site)
  - type: web
    name: frontend
    env: static
    buildCommand: npm run build
    staticPublishPath: dist
    routes:
      - type: rewrite
        source: /*
        destination: /index.html

  # API Server
  - type: web
    name: api
    env: node
    buildCommand: npm install
    startCommand: npm start
    envVars:
      - key: DATABASE_URL
        fromDatabase:
          name: postgres-db
          property: connectionString

  # Background Worker
  - type: worker
    name: email-worker
    env: node
    buildCommand: npm install
    startCommand: node workers/email.js

  # Cron Job
  - type: cron
    name: daily-report
    env: node
    schedule: "0 9 * * *"  # 毎日9時
    buildCommand: npm install
    startCommand: node jobs/daily-report.js

databases:
  - name: postgres-db
    databaseName: myapp
    plan: starter

Cron Jobの設定

定期実行タスク

// jobs/cleanup.js
const pool = require('../db');

async function cleanup() {
  console.log('Running cleanup job...');

  try {
    // 古いデータを削除
    const result = await pool.query(
      'DELETE FROM logs WHERE created_at < NOW() - INTERVAL \'30 days\''
    );
    console.log(`Deleted ${result.rowCount} old records`);
  } catch (err) {
    console.error('Cleanup failed:', err);
    process.exit(1);
  }

  process.exit(0);
}

cleanup();

Render設定:

New → Cron Job
→ 設定:
  - Name: cleanup-job
  - Environment: Node
  - Schedule: 0 2 * * *  (毎日午前2時)
  - Build Command: npm install
  - Start Command: node jobs/cleanup.js

スケジュール例

# 毎時実行
0 * * * *

# 毎日午前9時
0 9 * * *

# 毎週月曜日午前0時
0 0 * * 1

# 毎月1日午前0時
0 0 1 * *

# 15分ごと
*/15 * * * *

ヘルスチェックとモニタリング

ヘルスチェックエンドポイント

// server.js
app.get('/health', (req, res) => {
  res.json({
    status: 'ok',
    timestamp: new Date().toISOString(),
    uptime: process.uptime()
  });
});

// データベース接続確認
app.get('/health/db', async (req, res) => {
  try {
    await pool.query('SELECT 1');
    res.json({ status: 'ok', database: 'connected' });
  } catch (err) {
    res.status(500).json({ status: 'error', database: 'disconnected' });
  }
});

Render設定:

Settings → Health Check Path
→ /health

ログの確認

Dashboard → Logs → Live Logs

# ログ出力例
console.log('Server started');
console.error('Error:', error);

メトリクス

Dashboard → Metrics
- CPU使用率
- メモリ使用量
- リクエスト数
- レスポンスタイム

デプロイの自動化

GitHub Actions連携

# .github/workflows/deploy.yml
name: Deploy to Render

on:
  push:
    branches: [main]

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3

      - name: Setup Node.js
        uses: actions/setup-node@v3
        with:
          node-version: 18

      - name: Install dependencies
        run: npm install

      - name: Run tests
        run: npm test

      - name: Trigger Render Deploy
        env:
          RENDER_DEPLOY_HOOK: ${{ secrets.RENDER_DEPLOY_HOOK }}
        run: |
          curl -X POST $RENDER_DEPLOY_HOOK

Deploy Hook取得:

Settings → Deploy Hook
→ コピーして GitHub Secrets に保存

プレビュー環境

# render.yaml
services:
  - type: web
    name: my-app-preview
    env: node
    branch: develop  # developブランチで別環境
    buildCommand: npm install
    startCommand: npm start

パフォーマンス最適化

静的アセットのキャッシュ

// server.js
const express = require('express');
const path = require('path');

app.use(express.static('public', {
  maxAge: '1d',  // 1日キャッシュ
  etag: true
}));

// キャッシュヘッダー
app.use((req, res, next) => {
  res.setHeader('Cache-Control', 'public, max-age=86400');
  next();
});

圧縮

const compression = require('compression');

app.use(compression());

データベース接続プール

const { Pool } = require('pg');

const pool = new Pool({
  connectionString: process.env.DATABASE_URL,
  max: 20,  // 最大接続数
  idleTimeoutMillis: 30000,
  connectionTimeoutMillis: 2000,
});

トラブルシューティング

よくあるエラー

1. ビルド失敗

# ログ確認
Dashboard Logs Build Logs

# 原因:
- package.jsonの依存関係エラー
- Node.jsバージョン不一致
- 環境変数未設定

# 解決:
- ローカルでビルド成功を確認
- Node.jsバージョンを明示(package.json)
{
  "engines": {
    "node": "18.x"
  }
}

2. 起動失敗

// ポート番号を環境変数から取得
const PORT = process.env.PORT || 3000;

// 0.0.0.0でリッスン(重要)
app.listen(PORT, '0.0.0.0', () => {
  console.log(`Server on port ${PORT}`);
});

3. データベース接続エラー

// SSL設定を追加
const pool = new Pool({
  connectionString: process.env.DATABASE_URL,
  ssl: {
    rejectUnauthorized: false  // Renderで必要
  }
});

料金プラン

Free Tier(無料)

Static Site:
- 完全無料
- 無制限デプロイ
- 100GB/月転送量

Web Service:
- 750時間/月(1インスタンス)
- 15分非アクティブでスリープ
- 512MB RAM

PostgreSQL:
- 90日間無料
- その後$7/月
- 1GB ストレージ

Starter ($7/月)

- 常時起動
- スリープなし
- カスタムドメイン
- 自動SSL

Standard ($25/月)

- 2GB RAM
- 自動スケーリング
- 優先サポート

まとめ

Render.comは、モダンなアプリケーションデプロイに最適なプラットフォームです。

Renderの主要な利点

  1. 簡単なデプロイ - GitHubからワンクリック
  2. 無料枠 - 個人プロジェクト・検証に最適
  3. フルスタック対応 - フロントエンド、バックエンド、DB全て
  4. インフラコード化 - render.yamlで管理
  5. 自動スケーリング - トラフィックに応じて拡張

採用を検討すべきケース

最適:

  • フルスタックWebアプリ
  • API + データベース
  • バックグラウンドジョブ
  • スタートアップMVP
  • サイドプロジェクト

他の選択肢も検討:

  • 静的サイトのみ → Vercel/Netlify(より高速)
  • エンタープライズ → AWS/GCP(より柔軟)
  • Dockerベース → Railway/Fly.io(より自由度高)

Renderは、Herokuの代替として、シンプルさと柔軟性のバランスが取れた優れた選択肢です。