RenderでPHP/Node.jsのファイルアップロード設定する方法|Disk・環境変数・S3連携
Render は Heroku の代替として人気のクラウドプラットフォームです。Serverless ではなく常駐プロセス(Web Service)モデルのため、Vercel や Netlify とは異なりファイルアップロードのアーキテクチャが変わります。本記事では Render の永続ストレージ(Disk)設定、PHP 環境での upload_max_filesize の変更方法、環境変数を使った S3 設定、そして Infrastructure as Code(IaC)の render.yaml(Blueprint)での設定例まで解説します。
Render の Disk(永続ストレージ)とは
Render の Web Service はデフォルトでエフェメラル(再デプロイ時にファイルシステムがリセット)です。アップロードされたファイルを永続化するには Disk を追加します。
| ストレージの種類 | 永続性 | 複数インスタンス間共有 | 費用 |
|---|---|---|---|
| エフェメラルディスク(デフォルト) | 再デプロイでリセット | 不可 | 無料 |
| Render Disk(永続) | 永続(手動削除まで保持) | 不可(1インスタンスのみ) | $0.25/GB/月 |
| AWS S3(外部) | 永続 | 可 | S3 の料金に準拠 |
Render Disk はスケールアウト(複数インスタンス)に対応していないため、本格的なファイルアップロードには S3 連携が推奨されます。Disk は開発・ステージング環境や単一インスタンスでの運用に向いています。
Render Dashboard での Disk 設定
Disk は Render Dashboard の Web Service 設定から追加できます。
# render.yaml(Blueprint)での Disk 設定
services:
- type: web
name: my-app
runtime: node
buildCommand: npm install && npm run build
startCommand: npm start
disk:
name: uploads-disk
mountPath: /app/uploads # アプリ内でのマウントパス
sizeGB: 10 # 10GB のディスク
envVars:
- key: UPLOAD_DIR
value: /app/uploads
// Node.js での Disk へのファイル保存
const path = require('path');
const fs = require('fs');
const UPLOAD_DIR = process.env.UPLOAD_DIR || path.join(__dirname, 'uploads');
// アップロードディレクトリが存在しない場合は作成
if (!fs.existsSync(UPLOAD_DIR)) {
fs.mkdirSync(UPLOAD_DIR, { recursive: true });
}
// multer の設定例(Disk ストレージ)
const multer = require('multer');
const storage = multer.diskStorage({
destination: (req, file, cb) => {
cb(null, UPLOAD_DIR);
},
filename: (req, file, cb) => {
const uniqueSuffix = `${Date.now()}-${Math.round(Math.random() * 1e9)}`;
const ext = path.extname(file.originalname);
cb(null, `upload-${uniqueSuffix}${ext}`);
},
});
const upload = multer({
storage,
limits: { fileSize: 50 * 1024 * 1024 }, // 50MB
fileFilter: (req, file, cb) => {
const allowedTypes = ['image/jpeg', 'image/png', 'image/webp', 'application/pdf'];
if (allowedTypes.includes(file.mimetype)) {
cb(null, true);
} else {
cb(new Error('許可されていないファイル形式です。'));
}
},
});
PHP 環境での upload_max_filesize 設定
Render での PHP アプリ(Docker ベース)の場合、php.ini の設定を変更することでアップロードサイズを調整できます。Render は Docker での任意の設定が可能なため、他のホスティングサービスより柔軟です。
# Dockerfile(PHP アプリ)
FROM php:8.2-fpm
# 必要な拡張をインストール
RUN docker-php-ext-install pdo pdo_mysql
# php.ini の設定をオーバーライド
RUN echo "upload_max_filesize = 100M" > /usr/local/etc/php/conf.d/uploads.ini \
&& echo "post_max_size = 110M" >> /usr/local/etc/php/conf.d/uploads.ini \
&& echo "memory_limit = 256M" >> /usr/local/etc/php/conf.d/uploads.ini \
&& echo "max_execution_time = 120" >> /usr/local/etc/php/conf.d/uploads.ini \
&& echo "max_input_time = 120" >> /usr/local/etc/php/conf.d/uploads.ini
WORKDIR /var/www/html
COPY . .
EXPOSE 9000
CMD ["php-fpm"]
# php.ini(直接配置する場合)
; ファイルアップロードの有効化
file_uploads = On
; 1ファイルあたりの上限
upload_max_filesize = 100M
; POST データ全体の上限(upload_max_filesize より大きくする)
post_max_size = 110M
; PHP スクリプトのメモリ上限
memory_limit = 256M
; スクリプトの最大実行時間(秒)
max_execution_time = 120
; ファイル入力待ちの最大時間(秒)
max_input_time = 120
; 一時ファイルのディレクトリ(Render の場合は /tmp を使用)
upload_tmp_dir = /tmp
<?php
// .htaccess が使えない場合は ini_set() で実行時に変更(共有ホスティングでは制限あり)
// Render(Docker)では Dockerfile での設定が確実
// ini_set() による実行時オーバーライド(一部の設定のみ有効)
ini_set('memory_limit', '256M');
// upload_max_filesize と post_max_size は実行時変更不可(php.ini での設定が必要)
// 設定値の確認
echo ini_get('upload_max_filesize'); // "100M"
echo ini_get('post_max_size'); // "110M"
echo ini_get('memory_limit'); // "256M"
環境変数を使った S3 設定
Render Dashboard または render.yaml で環境変数を設定し、アプリから AWS S3 にアクセスします。シークレット情報は Render のシークレット管理機能を使い、render.yaml にはキーのみ記載します。
# render.yaml(Blueprint)— シークレットはキーのみ定義
services:
- type: web
name: my-php-app
runtime: docker
dockerfilePath: ./Dockerfile
envVars:
# 非シークレット(値を直接記載)
- key: AWS_REGION
value: ap-northeast-1
- key: AWS_S3_BUCKET
value: my-app-uploads
# シークレット(Render Dashboard で値を設定)
- key: AWS_ACCESS_KEY_ID
sync: false # sync: false でダッシュボードで手動入力
- key: AWS_SECRET_ACCESS_KEY
sync: false
# または Render の Environment Group を参照
- fromGroup: aws-credentials
disk:
name: tmp-uploads
mountPath: /tmp/uploads
sizeGB: 5
<?php
// PHP での AWS SDK を使った S3 アップロード
require 'vendor/autoload.php';
use Aws\S3\S3Client;
use Aws\Exception\AwsException;
$s3 = new S3Client([
'version' => 'latest',
'region' => getenv('AWS_REGION'),
'credentials' => [
'key' => getenv('AWS_ACCESS_KEY_ID'),
'secret' => getenv('AWS_SECRET_ACCESS_KEY'),
],
]);
function uploadToS3(array $file, string $bucket): array
{
global $s3;
$key = 'uploads/' . uniqid('file_', true) . '_' . basename($file['name']);
try {
$result = $s3->putObject([
'Bucket' => $bucket,
'Key' => $key,
'SourceFile' => $file['tmp_name'],
'ContentType' => mime_content_type($file['tmp_name']),
'ACL' => 'private',
]);
return [
'success' => true,
'key' => $key,
'url' => $result['ObjectURL'],
];
} catch (AwsException $e) {
return ['success' => false, 'error' => $e->getMessage()];
}
}
// アップロード処理
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_FILES['file'])) {
$file = $_FILES['file'];
// バリデーション
$maxSize = 50 * 1024 * 1024; // 50MB
if ($file['size'] > $maxSize) {
http_response_code(413);
echo json_encode(['error' => 'ファイルが大きすぎます(上限50MB)。']);
exit;
}
$allowedMimes = ['image/jpeg', 'image/png', 'image/webp', 'application/pdf'];
$detectedMime = mime_content_type($file['tmp_name']); // サーバー側でMIMEを検出
if (!in_array($detectedMime, $allowedMimes)) {
http_response_code(415);
echo json_encode(['error' => '許可されていないファイル形式です。']);
exit;
}
$result = uploadToS3($file, getenv('AWS_S3_BUCKET'));
echo json_encode($result);
}
render.yaml(Blueprint)での完全な設定例
Blueprint を使うと Render のインフラをコードで管理できます。Web Service・データベース・Redis・Disk・環境変数をまとめて定義できます。
# render.yaml
version: "1"
services:
# Web アプリケーション
- type: web
name: file-upload-app
runtime: node
plan: starter # free / starter / standard / pro
region: singapore # oregon / frankfurt / singapore / ohio
buildCommand: npm ci && npm run build
startCommand: node server.js
healthCheckPath: /health
autoDeploy: true # Git push で自動デプロイ
# 永続ストレージ(スケールアウト不可)
disk:
name: user-uploads
mountPath: /app/data/uploads
sizeGB: 20
# 環境変数
envVars:
- key: NODE_ENV
value: production
- key: PORT
value: 3000
- key: UPLOAD_DIR
value: /app/data/uploads
- key: AWS_REGION
value: ap-northeast-1
- key: AWS_S3_BUCKET
value: my-production-bucket
# シークレット(ダッシュボードで値を設定)
- key: AWS_ACCESS_KEY_ID
sync: false
- key: AWS_SECRET_ACCESS_KEY
sync: false
- key: DATABASE_URL
fromDatabase:
name: app-db
property: connectionString
# PostgreSQL データベース
- type: pserv
name: app-db
runtime: postgres
plan: starter
region: singapore
databaseName: app_production
この記事で使えるテストファイル(無料)
- → PNG テスト画像(1MB) — Render Disk・S3 へのアップロード動作確認に
- → PDF テストファイル(1MB) — PHP の upload_max_filesize 設定の動作確認に
- → ZIP テストファイル(1MB) — 境界値テスト・S3 直接アップロードの検証に