跳到内容

如何在 Docker 中配置 PHP 文件上传设置 | php.ini · Nginx · docker-compose

分类:Docker·PHP
本文目前仅提供日文版本。我们正在进行翻译工作。

在 Docker 环境中,"在本地配置但未在容器中反映"或 "修复了 Nginx 容器但 PHP-FPM 容器设置仍然存在"等问题很常见。这是因为 Docker 容器具有隔离的环境,配置文件在主机和容器之间分离。本文系统地解释了如何使用 Nginx 和 PHP-FPM 容器正确配置文件上传。

Docker 中 PHP 自定义配置方法

将自定义php.ini设置应用到PHP容器主要有两种方法:在Dockerfile中构建镜像时复制文件,或在docker-compose中使用卷挂载。

方法 1:在 Dockerfile 中复制 <code>php.ini</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

方法 2:使用 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

卷挂载方式适合开发环境,只需修改配置文件并重启容器即可应用。生产环境建议使用将文件复制到镜像的 Dockerfile 方式(以保持镜像的可复现性)。

所需的配置值和 <code>php.ini</code> 的写法

有 4 个与文件上传相关的配置值。我们将准备一个 <code>custom.ini</code> 文件,其中包含这些设置。

; 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

如何查找 php.ini 配置文件的位置

要检查容器内正在加载哪个 php.ini,请使用以下命令。

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

通过 Web 确认时,使用 <code>phpinfo()</code>。

<?php
// /var/www/html/public/info.php (一時的なデバッグ用)
phpinfo();
// ※ 本番環境では削除すること(サーバー情報が丸見えになる)
Docker 双容器 (Nginx + PHP-FPM) 上传流程 Client Browser Nginx 容器 Nginx client_max_body_size PHP-FPM 容器 PHP-FPM upload_max_filesize post_max_size App /var/www HTTP POST FastCGI :9000 两个限制值必须一致否则上传失败 Docker 双容器配置上传路径
图1: Nginx + PHP-FPM 双容器上传流程

Nginx容器和PHP-FPM容器之间的配置关系

Docker 中典型的 PHP 设置是分离 Nginx 和 PHP-FPM 容器的 2 容器架构。由于每个容器都有独立的限制,<strong>如果两者配置不当,上传将失败</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;
    }
}

docker-compose.yml的完整配置示例

下面是包含 Nginx + PHP-FPM + 卷挂载的完整 docker-compose.yml 示例。

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

如何验证设置是否已应用

更改设置后,必须重新启动容器,并确认设置已正确加载。

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

常见问题和解决方案

症状 原因 解决方案
413 Request Entity Too Large Nginx <code>client_max_body_size</code> 超限 提高 Nginx 配置,运行 <code>nginx -s reload</code>
PHP 级别的 UPLOAD_ERR_INI_SIZE <code>upload_max_filesize</code> 超限 修改custom.ini并重启容器
即使更改设置也不会应用 需要重启容器 / 配置文件的挂载路径错误 <code>docker compose restart php</code> / 检查路径
写入临时目录失败 PHP容器的用户权限与<code>/tmp</code>权限不匹配 检查卷权限设置和 <code>upload_tmp_dir</code>
大文件超时 <code>fastcgi_read_timeout</code> 或 <code>max_execution_time</code> 太短 提高两个值

生产环境补充说明

在生产环境中也请考虑以下几点。

  • 在镜像构建时使用 <code>COPY</code> 嵌入 php.ini,不要作为卷挂载(为了可再现性)
  • 务必设置 <code>display_errors = Off</code> 和 <code>log_errors = On</code>
  • 当上传目标是 S3 等云存储时,容器本地的临时存储应仅在请求处理期间保留。
  • 在多副本(水平扩展)配置中,无法使用本地上传目标。请改用 S3 或共享存储(EFS、NFS)。
  • PHP-FPM的进程数(<code>pm.max_children</code>)在大量上传同时发生时也会给内存造成压力

本文中可用的测试文件(免费)

  • → <a href="/ja/files/threshold/" class="text-primary-600 dark:text-primary-400 hover:underline">边界值测试文件列表</a> — 在 upload_max_filesize 设置值前后重现和验证错误
  • → <a href="/ja/files/images/" class="text-primary-600 dark:text-primary-400 hover:underline">测试图像列表</a> — 在 Docker 环境中验证各种大小的上传行为

相关文章

  • → <a href="/ja/blog/nginx-upload-config/" class="text-primary-600 dark:text-primary-400 hover:underline">如何正确配置 Nginx client_max_body_size | 上传限制问题排查</a>
  • → <a href="/ja/blog/php-file-upload/" class="text-primary-600 dark:text-primary-400 hover:underline">PHP 文件上传实现方法 | 验证・存储・安全性完整指南</a>
  • → <a href="/ja/blog/laravel-file-upload/" class="text-primary-600 dark:text-primary-400 hover:underline">Laravel 文件上传实现指南|验证、Storage 和 S3 支持</a>

常见问题

如何在 Docker 中更改 PHP 的 upload_max_filesize?

创建自定义的 <code>php.ini</code> 文件,并通过 Dockerfile 将其复制到容器内的 <code>/usr/local/etc/php/conf.d/</code> 中。

如何在docker-compose.yml中配置Nginx和PHP-FPM的上传设置?

在nginx.conf中为Nginx配置client_max_body_size,在php.ini中为PHP配置upload_max_filesize,然后分别用volumes挂载。

为什么 Docker 环境中未反映上传设置?

php.ini 的位置可能不正确。使用 <code>php -i | grep upload_max_filesize</code> 检查当前配置值,并通过 Loaded Configuration File 确认正在加载哪个 ini 文件。