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との比較
| 項目 | Render | Vercel | Heroku |
|---|---|---|---|
| 無料枠 | あり(制限付き) | あり(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の主要な利点
- 簡単なデプロイ - GitHubからワンクリック
- 無料枠 - 個人プロジェクト・検証に最適
- フルスタック対応 - フロントエンド、バックエンド、DB全て
- インフラコード化 - render.yamlで管理
- 自動スケーリング - トラフィックに応じて拡張
採用を検討すべきケース
最適:
- フルスタックWebアプリ
- API + データベース
- バックグラウンドジョブ
- スタートアップMVP
- サイドプロジェクト
他の選択肢も検討:
- 静的サイトのみ → Vercel/Netlify(より高速)
- エンタープライズ → AWS/GCP(より柔軟)
- Dockerベース → Railway/Fly.io(より自由度高)
Renderは、Herokuの代替として、シンプルさと柔軟性のバランスが取れた優れた選択肢です。