Skip to content

Como configurar upload de arquivos PHP no Docker | php.ini · Nginx · docker-compose

Categoria:Docker・PHP
Este artigo está disponível atualmente apenas em japonês. As versões traduzidas serão publicadas sequencialmente.

Em ambientes construídos com Docker, problemas como 「as configurações definidas localmente não são refletidas no contêiner」 e 「as configurações do contêiner PHP-FPM permanecem mesmo após corrigir o contêiner Nginx」 ocorrem facilmente. Isso ocorre porque os contêineres Docker possuem ambientes independentes, portanto os arquivos de configuração são separados entre o host e o contêiner. Este artigo explica sistematicamente como configurar corretamente o upload de arquivos na combinação de contêineres Nginx e PHP-FPM.

Como configurar PHP customizado no Docker

Existem principalmente dois métodos para aplicar configurações personalizadas de php.ini em um contêiner PHP. Um é copiar o arquivo durante a construção da imagem no Dockerfile, e outro é usar montagem de volume no docker-compose.

Método 1: Copiar <code>php.ini</code> no <code>Dockerfile</code>

# Dockerfile(PHP-FPM コンテナ)
FROM php:8.3-fpm-alpine

# 必要な拡張をインストール
RUN docker-php-ext-install pdo_mysql opcache

# カスタム php.ini をコンテナにコピー
# php.ini-development または php.ini-production をベースにする
COPY ./docker/php/php.ini /usr/local/etc/php/php.ini

# または conf.d ディレクトリに追加設定ファイルとして置く(推奨)
# 既存設定を上書きせず、変更したい値だけ記述できる
COPY ./docker/php/custom.ini /usr/local/etc/php/conf.d/99-custom.ini

WORKDIR /var/www/html

Método 2: Montagem de volume com <code>docker-compose</code>

# docker-compose.yml
services:
  php:
    build:
      context: .
      dockerfile: ./docker/php/Dockerfile
    volumes:
      # アプリのソースコード
      - ./src:/var/www/html
      # php.ini をマウント(ファイル変更が即反映される)
      - ./docker/php/custom.ini:/usr/local/etc/php/conf.d/99-custom.ini:ro

A montagem de volume é adequada para o ambiente de desenvolvimento, pois as alterações no arquivo de configuração são refletidas apenas reiniciando o contêiner. Para o ambiente de produção, é recomendada a abordagem Dockerfile que copia para a imagem (para manter a reprodutibilidade da imagem).

Valores de configuração necessários e como escrever em php.ini

Existem 4 valores de configuração relacionados ao upload de arquivo. Prepare um arquivo <code>custom.ini</code> com todas essas configurações.

; docker/php/custom.ini
; ============================================
; ファイルアップロード関連の設定
; ============================================

; ファイルアップロードを有効化(デフォルトOnだが明示する)
file_uploads = On

; 1ファイルあたりのアップロード上限
; Nginx の client_max_body_size と合わせること
upload_max_filesize = 100M

; POSTリクエスト全体の上限
; upload_max_filesize より大きくすること(フォームフィールドのオーバーヘッド分)
post_max_size = 110M

; ============================================
; メモリ・実行時間の設定
; ============================================

; PHPスクリプトが使用できる最大メモリ
; post_max_size より大きくすること
memory_limit = 256M

; スクリプトの最大実行時間(秒)
; 大きなファイルのアップロードや処理に対応
max_execution_time = 300

; リクエストデータ(POSTやファイル)の読み込み最大時間(秒)
; -1 で max_execution_time に従う
max_input_time = 300

Como verificar o local do arquivo de configuração php.ini

Para verificar qual <code>php.ini</code> está sendo carregado dentro do container, use o seguinte comando.

# コンテナ内で実行(docker exec 経由)
docker exec -it <コンテナ名> php -i | grep "php.ini"

# 出力例:
# Configuration File (php.ini) Path => /usr/local/etc/php
# Loaded Configuration File         => /usr/local/etc/php/php.ini

# Additional .ini files parsed(conf.d の追加設定)
docker exec -it <コンテナ名> php -i | grep "additional"
# Additional .ini files parsed => /usr/local/etc/php/conf.d/docker-php-ext-opcache.ini,
#   /usr/local/etc/php/conf.d/99-custom.ini

# 特定の設定値を確認
docker exec -it <コンテナ名> php -i | grep -E "upload_max|post_max|memory_limit"
# upload_max_filesize => 100M
# post_max_size       => 110M
# memory_limit        => 256M

Para verificar via web, use <code>phpinfo()</code>.

<?php
// /var/www/html/public/info.php (一時的なデバッグ用)
phpinfo();
// ※ 本番環境では削除すること(サーバー情報が丸見えになる)
Fluxo de upload de configuração Docker de 2 contêineres (Nginx + PHP-FPM) Client Browser Contêiner Nginx Nginx client_max_body_size Contêiner PHP-FPM PHP-FPM upload_max_filesize post_max_size App /var/www HTTP POST FastCGI :9000 o upload falha se os dois valores limite não corresponderem Caminho de upload da configuração Docker de 2 contêineres
Figura 1: Fluxo de upload com configuração de 2 contêineres Nginx + PHP-FPM

Relacionamento de configuração entre contêiner Nginx e contêiner PHP-FPM

A configuração típica de PHP no Docker é uma configuração de 2 contêineres que separa o contêiner Nginx e o contêiner PHP-FPM. Como cada um possui limitações independentes, <strong>o upload falhará se as configurações de ambos não forem apropriadas</strong>.

クライアント
    │
    ▼(HTTP リクエスト)
┌──────────────────────────────┐
│  Nginx コンテナ              │  ← client_max_body_size で制限
│  client_max_body_size 100m;  │     ここを超えると 413 エラー
└──────────────────────────────┘
    │
    ▼(FastCGI プロトコル)
┌──────────────────────────────┐
│  PHP-FPM コンテナ            │  ← upload_max_filesize / post_max_size で制限
│  upload_max_filesize = 100M  │     ここを超えると UPLOAD_ERR_INI_SIZE
│  post_max_size = 110M        │
└──────────────────────────────┘
# docker/nginx/conf.d/default.conf
server {
    listen 80;
    server_name localhost;
    root /var/www/html/public;
    index index.php;

    # Nginx レベルのアップロード上限
    # PHP の upload_max_filesize / post_max_size 以上にする
    client_max_body_size 110m;

    # タイムアウト設定(大容量ファイル処理用)
    proxy_read_timeout 300s;
    proxy_send_timeout 300s;

    location / {
        try_files $uri $uri/ /index.php?$query_string;
    }

    location ~ \.php$ {
        fastcgi_pass php:9000;   # PHP-FPMコンテナのサービス名:ポート
        fastcgi_index index.php;
        fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
        include fastcgi_params;

        # FastCGI のタイムアウト設定
        fastcgi_read_timeout 300s;
        fastcgi_send_timeout 300s;
    }
}

Exemplo de configuração completa do docker-compose.yml

Apresentamos um exemplo completo de <code>docker-compose.yml</code> incluindo Nginx + PHP-FPM + volume mount.

version: '3.8'

services:
  # Nginx コンテナ
  nginx:
    image: nginx:1.27-alpine
    ports:
      - "8080:80"
    volumes:
      # アプリのソースコード(Nginx から静的ファイルを配信)
      - ./src:/var/www/html/public:ro
      # Nginx 設定ファイル
      - ./docker/nginx/conf.d:/etc/nginx/conf.d:ro
    depends_on:
      - php
    networks:
      - app-network

  # PHP-FPM コンテナ
  php:
    build:
      context: .
      dockerfile: ./docker/php/Dockerfile
    volumes:
      # アプリのソースコード
      - ./src:/var/www/html
      # PHP カスタム設定(開発時はマウントで即反映)
      - ./docker/php/custom.ini:/usr/local/etc/php/conf.d/99-custom.ini:ro
      # アップロードファイルの一時保存先(権限に注意)
      - upload_tmp:/tmp/php-uploads
    environment:
      PHP_UPLOAD_TMP_DIR: /tmp/php-uploads
    networks:
      - app-network

networks:
  app-network:
    driver: bridge

volumes:
  upload_tmp:
    driver: local
# docker/php/Dockerfile
FROM php:8.3-fpm-alpine

# 必要なシステムパッケージ
RUN apk add --no-cache \
    libpng-dev \
    libjpeg-turbo-dev \
    libwebp-dev \
    freetype-dev

# PHP 拡張のインストール
RUN docker-php-ext-configure gd \
        --with-freetype \
        --with-jpeg \
        --with-webp && \
    docker-php-ext-install \
        gd \
        pdo_mysql \
        opcache \
        exif

# アプリユーザーを作成(www-data と権限を合わせる)
RUN addgroup -g 1000 appuser && \
    adduser -u 1000 -G appuser -s /bin/sh -D appuser

USER appuser
WORKDIR /var/www/html

Como verificar se a configuração foi aplicada

Após alterar a configuração, sempre reinicie o contêiner e confirme se a configuração foi carregada corretamente.

# コンテナの再起動(設定ファイル変更を反映)
docker compose restart php

# または特定の設定値だけ確認
docker compose exec php php -r "echo ini_get('upload_max_filesize'), PHP_EOL;"
docker compose exec php php -r "echo ini_get('post_max_size'), PHP_EOL;"
docker compose exec php php -r "echo ini_get('memory_limit'), PHP_EOL;"

# 複数の値をまとめて確認
docker compose exec php php -r "
foreach (['upload_max_filesize', 'post_max_size', 'memory_limit', 'max_execution_time'] as \$key) {
    echo \$key . ' = ' . ini_get(\$key) . PHP_EOL;
}"

# Nginx の設定確認
docker compose exec nginx nginx -T | grep -E "client_max_body|server_name"

# Nginx の設定をリロード(コンテナ再起動なし)
docker compose exec nginx nginx -s reload

Problemas comuns e soluções

Sintoma Causa Solução
413 Request Entity Too Large Limite de <code>client_max_body_size</code> do Nginx excedido Elevar a configuração do Nginx e executar <code>nginx -s reload</code>
UPLOAD_ERR_INI_SIZE no nível do PHP <code>upload_max_filesize</code> excedido Modificar custom.ini e reiniciar o container
A configuração não é aplicada mesmo após alterar Reinicialização do container necessária / Caminho de montagem do arquivo de configuração está incorreto <code>docker compose restart php</code> / Verificar o caminho
Falha na escrita no diretório temporário Incompatibilidade entre a permissão de usuário do contêiner PHP e a permissão de <code>/tmp</code> Verifique as permissões do volume e <code>upload_tmp_dir</code>
Timeout em arquivos grandes <code>fastcgi_read_timeout</code> ou <code>max_execution_time</code> curtos aumentar ambos os valores

Notas adicionais para ambiente de produção

Considere também os seguintes pontos no ambiente de produção.

  • php.ini é incorporado com <code>COPY</code> durante o build da imagem e não é montado como volume (para reprodutibilidade)
  • Certifique-se de definir <code>display_errors = Off</code> e <code>log_errors = On</code>
  • Ao usar armazenamento em nuvem como S3 como destino de upload, mantenha o armazenamento temporário local do contêiner apenas durante o processamento da solicitação
  • Em uma configuração com múltiplas réplicas (escala horizontal), você não pode usar destinos de upload locais. Use S3 ou armazenamento compartilhado (EFS/NFS).
  • O número de processos do PHP-FPM (<code>pm.max_children</code>) também pressiona a memória quando ocorrem muitos uploads grandes simultaneamente

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

  • → <a href="/ja/files/threshold/" class="text-primary-600 dark:text-primary-400 hover:underline">Lista de arquivos de teste de valores limite</a> — Reproduzir e verificar erros próximos aos valores de configuração de upload_max_filesize
  • → <a href="/ja/files/images/" class="text-primary-600 dark:text-primary-400 hover:underline">Lista de imagens de teste</a> — Verificar o comportamento de upload em ambiente Docker com vários tamanhos

Artigos relacionados

  • → <a href="/ja/blog/nginx-upload-config/" class="text-primary-600 dark:text-primary-400 hover:underline">Como configurar corretamente o client_max_body_size do Nginx | Resolução de problemas de limite de upload</a>
  • → <a href="/ja/blog/php-file-upload/" class="text-primary-600 dark:text-primary-400 hover:underline">Como implementar upload de arquivos em PHP | Guia completo de validação, armazenamento e segurança</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>

Perguntas frequentes

Como alterar upload_max_filesize do PHP no Docker?

Crie um arquivo <code>php.ini</code> personalizado e copie-o para <code>/usr/local/etc/php/conf.d/</code> dentro do contêiner no Dockerfile.

Como configurar uploads no Nginx e PHP-FPM usando docker-compose.yml?

Configure <code>client_max_body_size</code> em <code>nginx.conf</code> para Nginx e <code>upload_max_filesize</code> em <code>php.ini</code> para PHP, montando-os respectivamente com volumes.

Por que as configurações de upload não são refletidas no ambiente Docker?

O local do php.ini pode estar incorreto. Verifique o valor de configuração atual com <code>php -i | grep upload_max_filesize</code> e confirme qual arquivo ini está sendo lido em Loaded Configuration File.