Saltar al contenido

Cómo configurar la carga de archivos para PHP/Node.js en Render | Disk, variables de entorno e integración S3

Categoría: Render / Configuración de despliegue
Este artículo está disponible actualmente solo en japonés. Estamos trabajando en las traducciones.

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).

Client Render Web Service App (always-on) Disk (persistent) /var/data — single instance No body size limit (set in app/proxy) S3 / R2 (recommended) scale-out friendly
Diagrama: Render Web Service y destinos de subida (Disk vs S3)

¿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>