Skip to content

Como configurar upload de arquivo PHP/Node.js no Render | Disk, variáveis de ambiente e integração S3

Categoria:Render • Configuração de implantação
Este artigo está disponível atualmente apenas em japonês. As versões traduzidas serão publicadas sequencialmente.

Render é uma plataforma em nuvem popular como alternativa ao Heroku. Como usa um modelo de processo residente (Web Service) em vez de Serverless, a arquitetura de upload de arquivo difere da Vercel e Netlify. Este artigo explora a configuração de armazenamento persistente (Disk) no Render, como alterar <code>upload_max_filesize</code> em ambientes PHP, configuração S3 usando variáveis de ambiente, e exemplos de configuração em Infrastructure as Code (IaC) com <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
Figura: Web Service do Render e destino de armazenamento de upload (Disk vs S3)

O que é Render Disk (Armazenamento Persistente)

O Web Service do Render é efêmero por padrão (o sistema de arquivos é redefinido ao reimplantar). Para persistir arquivos enviados, você precisa adicionar um Disk.

Tipo de armazenamento Persistência Compartilhamento entre múltiplas instâncias Custo
Disco efêmero (padrão) Redefinir na reimplantação Não permitido Gratuito
Render Disk (Persistente) Persistente (retido até exclusão manual) Não permitido (apenas 1 instância) $0.25/GB/mês
AWS S3 (externo) Persistente Possível Em conformidade com a precificação do S3

Como Render Disk não oferece suporte a scale-out (múltiplas instâncias), é recomendada a integração com S3 para uploads de arquivos em produção. O Disk é adequado para ambientes de desenvolvimento e staging ou operações com instância única.

Configuração de Disco no Render Dashboard

O Disk pode ser adicionado nas configurações do Web Service do 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('許可されていないファイル形式です。'));
    }
  },
});

Configuração de upload_max_filesize no ambiente PHP

Para aplicativos PHP no Render (baseado em Docker), você pode ajustar o tamanho de upload alterando as configurações em <code>php.ini</code>. Como Render permite configurações arbitrárias no Docker, é mais flexível do que outros serviços de hospedagem.

# 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"

Configuração S3 usando variáveis de ambiente

Configure as variáveis de ambiente no Render Dashboard ou em <code>render.yaml</code> para que seu aplicativo acesse o AWS S3. Use o recurso de gerenciamento de segredos do Render para informações sensíveis, incluindo apenas as chaves em <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);
}

Exemplo de configuração completa em render.yaml (Blueprint)

Com Blueprint, você pode gerenciar a infraestrutura do Render através de código. Você pode definir Web Service, banco de dados, Redis, disco e variáveis de ambiente em 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

Arquivo de teste disponível para usar neste artigo (gratuito)

  • → <a href="/ja/files/images/png/1mb/" class="text-primary-600 dark:text-primary-400 hover:underline">Imagem PNG de teste (1MB)</a> — Para verificação de operação de upload para <code>Render Disk</code> e <code>S3</code>
  • → <a href="/ja/files/pdf/1mb/" class="text-primary-600 dark:text-primary-400 hover:underline">Arquivo de teste PDF (1MB)</a> — Para confirmação do funcionamento da configuração <code>upload_max_filesize</code> do PHP
  • → <a href="/ja/files/zip/1mb/" class="text-primary-600 dark:text-primary-400 hover:underline">Arquivo de teste ZIP (1MB)</a> — Para teste de valor limite e validação de upload direto em S3

Artigos relacionados

  • → <a href="/ja/blog/vercel-upload-config/" class="text-primary-600 dark:text-primary-400 hover:underline">Configuração e limites de upload de arquivos do Vercel | Vercel Blob, limitações de API e soluções alternativas</a>
  • → <a href="/ja/blog/netlify-upload-config/" class="text-primary-600 dark:text-primary-400 hover:underline">Como fazer upload de arquivos com Netlify Functions | Limites, Large Media e soluções alternativas</a>
  • → <a href="/ja/blog/laravel-file-upload/" class="text-primary-600 dark:text-primary-400 hover:underline">Guia de implementação de upload de arquivos no Laravel | Validação, Storage e suporte S3</a>