Cómo configurar opciones de carga de archivos de PHP en Docker | php.ini, Nginx, docker-compose
En entornos Docker, problemas como "configuración aplicada localmente pero no reflejada en el contenedor" o "corregido el contenedor Nginx pero la configuración del contenedor PHP-FPM permanece" son comunes. Esto se debe a que los contenedores Docker tienen entornos aislados donde los archivos de configuración se separan entre el host y el contenedor. Este artículo explica sistemáticamente cómo configurar correctamente las cargas de archivos con contenedores Nginx y PHP-FPM.
Métodos de configuración personalizada de PHP en Docker
Hay principalmente dos formas de aplicar configuración personalizada de php.ini a un contenedor PHP: copiar el archivo durante la compilación de imagen en Dockerfile, o usar montaje de volumen en docker-compose.
Método 1: Copiar <code>php.ini</code> en Dockerfile
# 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: Montar volumen con docker-compose
# 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
El montaje de volumen es adecuado para entornos de desarrollo y se puede aplicar simplemente modificando el archivo de configuración e reiniciando el contenedor. Para entornos de producción, se recomienda el método Dockerfile de copiar a la imagen (para mantener la reproducibilidad de la imagen).
Valores de configuración requeridos y cómo escribir <code>php.ini</code>
Hay 4 valores de configuración relacionados con cargas de archivos. Prepararemos un archivo <code>custom.ini</code> con estas configuraciones consolidadas.
; 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
Cómo encontrar la ubicación del archivo de configuración php.ini
Para verificar cuál <code>php.ini</code> se está cargando dentro del contenedor, utilice el siguiente 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 a través de la web, use <code>phpinfo()</code>.
<?php
// /var/www/html/public/info.php (一時的なデバッグ用)
phpinfo();
// ※ 本番環境では削除すること(サーバー情報が丸見えになる)
Relación de configuración entre contenedores Nginx y PHP-FPM
Una configuración típica de PHP en Docker es una arquitectura de 2 contenedores que separa los contenedores de Nginx y PHP-FPM. Como cada uno tiene límites independientes, <strong>las cargas fallarán si ambos no están configurados correctamente</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;
}
}
Ejemplo completo de configuración de docker-compose.yml
Aquí se muestra un ejemplo completo de docker-compose.yml que incluye Nginx + PHP-FPM + montaje de volumen.
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
Cómo verificar si los ajustes se han aplicado
Después de cambiar la configuración, siempre reinicie el contenedor y verifique que la configuración se esté cargando correctamente.
# コンテナの再起動(設定ファイル変更を反映)
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 comunes y soluciones
| Síntomas | Causa | Solución |
|---|---|---|
| 413 Request Entity Too Large | Límite de <code>client_max_body_size</code> de Nginx superado | Aumenta la configuración de Nginx y ejecuta <code>nginx -s reload</code> |
| UPLOAD_ERR_INI_SIZE a nivel de PHP | <code>upload_max_filesize</code> superado | Modificar custom.ini y reiniciar el contenedor |
| Los ajustes no se aplican aunque se cambien | Se requiere reiniciar el contenedor / Ruta de montaje incorrecta para el archivo de configuración | <code>docker compose restart php</code> / Verificar la ruta |
| Error al escribir en el directorio temporal | Desajuste entre los permisos de usuario del contenedor PHP y los permisos de <code>/tmp</code> | Verifique la configuración de permisos de volumen y <code>upload_tmp_dir</code> |
| Tiempo de espera agotado con archivos grandes | <code>fastcgi_read_timeout</code> o <code>max_execution_time</code> es demasiado corto | Aumentar ambos valores |
Notas para el entorno de producción
También considere los siguientes puntos en el entorno de producción.
- Incorporar php.ini con <code>COPY</code> durante la compilación de la imagen y no montarlo como volumen (para reproducibilidad)
- Siempre configure <code>display_errors = Off</code> y <code>log_errors = On</code>
- Cuando el destino de carga es almacenamiento en la nube como S3, mantenga el almacenamiento temporal en el local del contenedor solo durante el procesamiento de la solicitud.
- En una configuración de múltiples réplicas (escala horizontal), no puede usar destinos de carga locales. Use S3 o almacenamiento compartido (EFS, NFS) en su lugar.
- El número de procesos PHP-FPM (<code>pm.max_children</code>) también puede sobrecargar la memoria cuando ocurren muchas cargas grandes simultáneamente
Archivos de prueba para este artículo (gratis)
- → <a href="/ja/files/threshold/" class="text-primary-600 dark:text-primary-400 hover:underline">Lista de archivos de prueba de valores límite</a> — Reproducir y verificar errores alrededor del límite upload_max_filesize
- → <a href="/ja/files/images/" class="text-primary-600 dark:text-primary-400 hover:underline">Lista de imágenes de prueba</a> — Verificar el comportamiento de carga en el entorno Docker con varios tamaños
Artículos relacionados
- → <a href="/ja/blog/nginx-upload-config/" class="text-primary-600 dark:text-primary-400 hover:underline">Cómo Configurar Correctamente client_max_body_size en Nginx | Solución de Problemas de Límites de Carga</a>
- → <a href="/ja/blog/php-file-upload/" class="text-primary-600 dark:text-primary-400 hover:underline">Cómo Implementar la Carga de Archivos en PHP | Guía Completa de Validación, Almacenamiento y Seguridad</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>