Skip to content

How to Configure PHP File Upload Settings in Docker | php.ini, Nginx, docker-compose

Category: Docker / PHP
This article is currently available in Japanese only. We are working on translations.

In Docker environments, issues like "configuration applied locally but not reflected in the container" or "fixed Nginx container but PHP-FPM container settings remain" are common. This is because Docker containers have isolated environments where configuration files are separated between host and container. This article systematically explains how to properly configure file uploads with Nginx and PHP-FPM containers.

PHP Custom Configuration Methods in Docker

There are mainly two ways to apply custom php.ini settings to a PHP container: copying the file during image build in Dockerfile, or using volume mount in docker-compose.

Method 1: Copy <code>php.ini</code> in 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

Method 2: Volume mount with 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

Volume mounting is suitable for development environments and can be applied by simply modifying the configuration file and restarting the container. For production environments, the Dockerfile method of copying to the image is recommended (to maintain image reproducibility).

Required configuration values and how to write <code>php.ini</code>

There are 4 configuration values related to file uploads. We will prepare a <code>custom.ini</code> file with these settings consolidated.

; 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

How to find the location of the php.ini configuration file

To check which <code>php.ini</code> is being loaded inside the container, use the following command.

# コンテナ内で実行(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

To check via the web, use <code>phpinfo()</code>.

<?php
// /var/www/html/public/info.php (一時的なデバッグ用)
phpinfo();
// ※ 本番環境では削除すること(サーバー情報が丸見えになる)
Docker 2-container (Nginx + PHP-FPM) upload flow Client Browser Nginx container Nginx client_max_body_size PHP-FPM container PHP-FPM upload_max_filesize post_max_size App /var/www HTTP POST FastCGI :9000 Both limits must match or upload fails Upload path in Docker 2-container setup
Fig 1: Upload flow in Nginx + PHP-FPM 2-container setup

Configuration relationship between Nginx and PHP-FPM containers

A typical Docker PHP setup is a 2-container architecture separating Nginx and PHP-FPM containers. Since each has independent limits, <strong>uploads will fail if both are not properly configured</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;
    }
}

Complete Configuration Example of docker-compose.yml

Here is a complete example of a docker-compose.yml that includes 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

How to verify if settings are applied

After changing settings, always restart the container and verify that the configuration is being loaded correctly.

# コンテナの再起動(設定ファイル変更を反映)
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

Common problems and solutions

Symptoms Cause Solution
413 Request Entity Too Large Nginx <code>client_max_body_size</code> Exceeded Increase Nginx configuration and run <code>nginx -s reload</code>
UPLOAD_ERR_INI_SIZE at PHP level <code>upload_max_filesize</code> exceeded Modify custom.ini and Restart Container
Settings do not apply even after changing them Container restart required / Incorrect mount path for configuration file <code>docker compose restart php</code> / Check the path
Write to temporary directory failed Mismatch between PHP container user permissions and <code>/tmp</code> permissions Check volume permission settings and <code>upload_tmp_dir</code>
Timeout with large files <code>fastcgi_read_timeout</code> or <code>max_execution_time</code> is too short Increase both values

Production environment notes

Also consider the following points in the production environment.

  • Embed php.ini with <code>COPY</code> during image build and do not mount as a volume (for reproducibility)
  • Always set <code>display_errors = Off</code> and <code>log_errors = On</code>
  • When the upload destination is cloud storage like S3, keep temporary storage in the container local to the duration of request processing only.
  • In a multi-replica (horizontal scale) configuration, you cannot use local upload destinations. Use S3 or shared storage (EFS, NFS) instead.
  • The number of PHP-FPM processes (<code>pm.max_children</code>) can also strain memory when many large uploads occur simultaneously

Test files for this article (free)

  • → <a href="/ja/files/threshold/" class="text-primary-600 dark:text-primary-400 hover:underline">Boundary Value Test Files</a> — Reproduce and verify errors around the upload_max_filesize setting
  • → <a href="/ja/files/images/" class="text-primary-600 dark:text-primary-400 hover:underline">Test Images List</a> — Verify upload behavior in Docker environment across various sizes

Related articles

  • → <a href="/ja/blog/nginx-upload-config/" class="text-primary-600 dark:text-primary-400 hover:underline">How to Properly Configure Nginx client_max_body_size | Troubleshooting Upload Limits</a>
  • → <a href="/ja/blog/php-file-upload/" class="text-primary-600 dark:text-primary-400 hover:underline">How to Implement File Upload in PHP | Complete Guide to Validation, Storage, and Security</a>
  • → <a href="/ja/blog/laravel-file-upload/" class="text-primary-600 dark:text-primary-400 hover:underline">Laravel File Upload Implementation Guide | Validation, Storage, and S3 Support</a>

Frequently Asked Questions

How to Change PHP's upload_max_filesize in Docker?

Create a custom <code>php.ini</code> file and copy it to <code>/usr/local/etc/php/conf.d/</code> inside the container via the Dockerfile.

How to Configure Upload Settings for Nginx and PHP-FPM in docker-compose.yml?

Configure client_max_body_size in nginx.conf for Nginx and upload_max_filesize in php.ini for PHP, then mount each with volumes.

Why Aren't Upload Settings Reflected in Docker Environments?

The location of php.ini might be incorrect. Check the current configuration value with <code>php -i | grep upload_max_filesize</code> and verify which ini file is being loaded via Loaded Configuration File.