Cómo configurar la carga de archivos para PHP/Node.js en Render | Disk, variables de entorno e integración S3
Render es una plataforma en la nube popular como alternativa a Heroku. A diferencia de Vercel o Netlify, utiliza un modelo de proceso persistente (Web Service) en lugar de serverless, lo que cambia la arquitectura de carga de archivos. Este artículo cubre la configuración de almacenamiento persistente (Disk) de Render, cómo modificar <code>upload_max_filesize</code> en entornos PHP, configuración de S3 usando variables de entorno, y ejemplos de Infrastructure as Code (IaC) con <code>render.yaml</code> (Blueprint).
¿Qué es Render Disk (almacenamiento persistente)?
El Web Service de Render es efímero por defecto (el sistema de archivos se reinicia al redeploy). Para persistir archivos cargados, agregue un Disk.
| Tipo de almacenamiento | Persistencia | Compartido entre múltiples instancias | Costo |
|---|---|---|---|
| Disco efímero (predeterminado) | Restablecer en re-implementación | No es posible | Gratuito |
| Render Disk (Persistente) | Persistente (se mantiene hasta eliminación manual) | No es posible (solo una instancia) | $0.25/GB/mes |
| AWS S3 (Externo) | Persistente | Compatible | Se aplican precios de S3 |
Render Disk no admite escalado horizontal (múltiples instancias), por lo que se recomienda la integración con S3 para cargas de archivos en producción. Disk es adecuado para desarrollo, entornos de staging o despliegues de instancia única.
Configuración de Disk en Render Dashboard
Los discos se pueden agregar desde la configuración de Web Service en el Render Dashboard.
# 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('許可されていないファイル形式です。'));
}
},
});
Configuración de upload_max_filesize en entorno PHP
Para aplicaciones PHP en Render (basadas en Docker), puede ajustar el tamaño de carga modificando la configuración de <code>php.ini</code>. Render ofrece flexibilidad con configuración arbitraria de Docker, superando a otros servicios de hosting.
# 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"
Configuración de S3 mediante variables de entorno
Configure variables de entorno en Render Dashboard o <code>render.yaml</code> y acceda a AWS S3 desde su aplicación. Use la función de gestión de secretos de Render para información confidencial e incluya solo las claves en <code>render.yaml</code>.
# 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);
}
Ejemplo de configuración completa en render.yaml (Blueprint)
Con Blueprint, puedes administrar la infraestructura de Render como código. Puedes definir Web Service, base de datos, Redis, Disk y variables de entorno en conjunto.
# 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
Archivos de prueba para este artículo (gratis)
- → <a href="/ja/files/images/png/1mb/" class="text-primary-600 dark:text-primary-400 hover:underline">Imagen PNG de Prueba (1MB)</a> — Para verificar el comportamiento de carga a Render Disk y S3
- → <a href="/ja/files/pdf/1mb/" class="text-primary-600 dark:text-primary-400 hover:underline">Archivo de prueba PDF (1MB)</a> — para verificar la configuración <code>upload_max_filesize</code> en PHP
- → <a href="/ja/files/zip/1mb/" class="text-primary-600 dark:text-primary-400 hover:underline">Archivo de prueba ZIP (1MB)</a> — para pruebas de límites y validación de carga directa a S3
Artículos relacionados
- → <a href="/ja/blog/vercel-upload-config/" class="text-primary-600 dark:text-primary-400 hover:underline">Configuración y Límites de Carga de Archivos en Vercel | Vercel Blob, Restricciones API, Soluciones Alternativas</a>
- → <a href="/ja/blog/netlify-upload-config/" class="text-primary-600 dark:text-primary-400 hover:underline">Cómo Cargar Archivos con Netlify Functions | Límites, Large Media y Soluciones Alternas</a>
- → <a href="/ja/blog/laravel-file-upload/" class="text-primary-600 dark:text-primary-400 hover:underline">Guía de Implementación de Carga de Archivos en Laravel | Validación, Storage y S3</a>