client_max_body_size не работает в Nginx proxy с Docker. Получаю ошибку 413 Payload too large
Я использую JWilder Nginx-proxy с Docker и сталкиваюсь с ошибкой “413 Payload too large” при попытке загрузки файлов. Несмотря на настройку client_max_body_size в моей конфигурации Nginx, эта настройка, кажется, не оказывает никакого эффекта.
Моя настройка:
- Nginx proxy (JWilder/nginx-proxy) с Docker
- Django & Gunicorn как приложение
- Cloudflare как CDN
Что я уже пробовал:
- Добавил
client_max_body_size 500m;в блок server в моей конфигурации Nginx - Добавил
client_max_body_size 500m;в блок location - Добавил
client_max_body_size 500m;в секцию http в основной конфигурации Nginx - Перезапустил контейнер, удалил его, удалил образ и пересобрал его
- Увеличил лимиты загрузки файлов в Django & Gunicorn
Моя конфигурация Nginx:
Основная конфигурация (секция http):
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
#tcp_nopush on;
keepalive_timeout 65;
#gzip on;
include /etc/nginx/conf.d/*.conf;
}
Конфигурация сервера:
server {
server_name mysite.io;
access_log /var/log/nginx/access.log vhost;
http2 on;
listen 443 ssl;
ssl_session_timeout 5m;
ssl_session_cache shared:SSL:50m;
ssl_session_tickets off;
ssl_certificate /etc/nginx/certs/swyve.io.crt;
ssl_certificate_key /etc/nginx/certs/swyve.io.key;
set $sts_header "";
if ($https) {
set $sts_header "max-age=31536000";
}
add_header Strict-Transport-Security $sts_header always;
include /etc/nginx/vhost.d/mysite.io;
location / {
proxy_pass http://swyve.io;
set $upstream_keepalive true;
include /etc/nginx/vhost.d/mysite.io_location;
}
}
Конфигурация виртуального хоста (/etc/nginx/vhost.d/mysite.io):
client_max_body_size 500m;
location /static/ {
alias /app/staticfiles/;
expires 1y;
add_header Cache-Control "public, immutable";
}
Конфигурация location (/etc/nginx/vhost.d/mysite.io_location):
client_max_body_size 500m;
proxy_request_buffering off;
proxy_buffering off;
proxy_connect_timeout 600s;
proxy_send_timeout 600s;
proxy_read_timeout 600s;
send_timeout 600s;
Дополнительная информация:
Я заметил в заголовках ответа идентификатор Cloudflare: “cf-ray: 999aa8574833c251-VIE”. Не ограничивает ли Cloudflare загрузку файлов до 100MB на своем бесплатном плане?
Найденное решение:
Я создал новый поддомен (upload.mysite.com) специально для загрузки файлов, который обходит Cloudflare. Это решило проблему, но мне пришлось обновить мою конфигурацию Nginx для поддержки нового поддомена.
Вопрос:
Почему client_max_body_size не работает в моей конфигурации Nginx proxy, и как правильно настроить его для разрешения загрузки больших файлов при использовании Cloudflare?
Проблема с неработающим параметром client_max_body_size в вашей конфигурации Nginx-прокси, скорее всего, вызвана несколькими факторами, при этом Cloudflare является основной причиной, исходя из вашей настройки. Ошибка 413 возникает, когда запросы на загрузку файлов превышают настроенные лимиты размера, но проблема обычно не в самом Nginx при использовании JWilder nginx-proxy.
Содержание
- Cloudflare как основная проблема
- Конфигурация JWilder nginx-proxy
- Правильные методы конфигурации Nginx
- Полное руководство по решению
- Альтернативные подходы
- Шаги проверки
Cloudflare как основная проблема
Наличие заголовка cf-ray в вашем ответе подтверждает, что Cloudflare перехватывает ваши запросы до того, как они достигнут вашего сервера Nginx. Бесплатный план Cloudflare имеет строгий лимит в 100 МБ для загрузки файлов, и это, скорее всего, является причиной ваших ошибок 413. Согласно документации Cloudflare, они проверяют и блокируют запросы, превышающие их лимиты размеров, прежде чем перенаправлять их на ваш исходный сервер.
Это объясняет, почему ваши изменения в конфигурации Nginx не подействовали — запросы никогда не достигают вашего прокси-сервера Nginx. Если лимит Cloudflare составляет 100 МБ, а вы пытаетесь загружать файлы большего размера, Cloudflare ответит ошибкой 413 независимо от ваших настроек Nginx.
Конфигурация JWilder nginx-proxy
Образ JWilder nginx-proxy имеет лимит загрузки по умолчанию 2 МБ, что значительно ниже ваших требований. Этот лимит по умолчанию имеет приоритет, если он не переопределен явно. Прокси использует динамическую генерацию конфигурации на основе переменных окружения и смонтированных файлов конфигурации.
Когда вы вручную добавляете client_max_body_size в свои файлы конфигурации, эти настройки могут быть перезаписаны динамической системой конфигурации nginx-proxy. Прокси генерирует файлы конфигурации во время выполнения на основе:
- Переменных окружения, установленных в контейнере
- Docker-меток на ваших контейнерах приложений
- Смонтированных файлов конфигурации
Правильные методы конфигурации Nginx
Метод 1: Переменные окружения (рекомендуется)
Самый надежный способ установить лимиты загрузки с помощью JWilder nginx-proxy — через переменные окружения. В вашем docker-compose.yml для сервиса прокси:
services:
proxy:
image: jwilder/nginx-proxy
container_name: nginx-proxy
ports:
- "80:80"
- "443:443"
volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro
- ./certs:/etc/nginx/certs:ro
environment:
CLIENT_MAX_BODY_SIZE: "500M"
GLOBAL_MAX_BODY_SIZE: "500M"
Метод 2: Монтирование файла конфигурации
Создайте пользовательский файл конфигурации и смонтируйте его в прокси:
# Создайте client_max_body_size.conf
echo "client_max_body_size 500M;" > client_max_body_size.conf
# Запустите контейнер со смонтированной конфигурацией
docker run -d \
--name nginx-proxy \
-v /var/run/docker.sock:/tmp/docker.sock \
-v /path/to/client_max_body_size.conf:/etc/nginx/conf.d/client_max_body_size.conf:ro \
-p 80:80 -p 443:443 \
jwilder/nginx-proxy
Метод 3: Docker-метки
Установите метки на ваш контейнер приложения для настройки лимитов для каждого хоста:
services:
myapp:
image: myapp
labels:
- "client_max_body_size=500M"
Полное руководство по решению
Шаг 1: Проверьте лимиты Cloudflare
Проверьте лимиты вашего плана Cloudflare:
- Бесплатный план: максимальный размер файла 100 МБ
- Pro план: максимальный размер файла 100 МБ
- Business план: максимальный размер файла 500 МБ
- Enterprise план: настраиваемые лимиты
Если вам нужно загружать файлы размером более 100 МБ, вам потребуется либо обновить ваш план Cloudflare, либо обойти его для конечных точек загрузки.
Шаг 2: Правильно настройте nginx-proxy
Измените конфигурацию nginx-proxy с помощью переменных окружения:
version: '3'
services:
nginx-proxy:
image: jwilder/nginx-proxy
container_name: nginx-proxy
ports:
- "80:80"
- "443:443"
volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro
- ./certs:/etc/nginx/certs:ro
environment:
CLIENT_MAX_BODY_SIZE: "500M"
GLOBAL_MAX_BODY_SIZE: "500M"
# Дополнительные рекомендуемые настройки
PROXY_BUFFERING: "off"
PROXY_REQUEST_BUFFERING: "off"
Шаг 3: Настройте лимиты для конкретных хостов
Если вам нужны разные лимиты для разных хостов, используйте Docker-метки:
services:
myapp:
image: myapp
labels:
- "VIRTUAL_HOST=mysite.io"
- "VIRTUAL_PORT=8000"
- "client_max_body_size=500M"
Шаг 4: Проверьте конфигурацию
После применения изменений:
- Перезапустите контейнер nginx-proxy:
docker restart nginx-proxy - Проверьте сгенерированную конфигурацию:
docker exec nginx-proxy cat /etc/nginx/conf.d/default.conf - Убедитесь, что настройка
client_max_body_sizeприсутствует
Альтернативные подходы
Обход Cloudflare для загрузок
Ваше решение по созданию поддомена, который обходит Cloudflare, является наиболее практичным для загрузки больших файлов. Настройте его следующим образом:
-
Конфигурация DNS:
- Создайте запись CNAME для
upload.mysite.io, указывающую напрямую на IP-адрес вашего сервера - Удалите прокси Cloudflare (оранжевое облако) для этого поддомена
- Создайте запись CNAME для
-
Конфигурация nginx-proxy:
yamlservices: nginx-proxy: # ... существующая конфигурация environment: CLIENT_MAX_BODY_SIZE: "500M" GLOBAL_MAX_BODY_SIZE: "500M" upload-app: image: myapp labels: - "VIRTUAL_HOST=upload.mysite.io" - "VIRTUAL_PORT=8000" - "client_max_body_size=1G" # Даже больший лимит для загрузок
Правила Cloudflare
Если вам нужно оставить Cloudflare для загрузок, но увеличить лимиты:
- Обновитесь до Business/Enterprise плана
- Пользовательские правила: настройте граничные правила для увеличения лимитов размера запросов
- Правила источника: настройте параметры размера запросов источника
Шаги проверки
Чтобы убедиться, что ваша конфигурация Nginx работает правильно:
-
Проверьте логи nginx-proxy:
bashdocker logs nginx-proxy | grep "client_max_body_size" -
Проверьте сгенерированную конфигурацию:
bashdocker exec nginx-proxy nginx -T -
Протестируйте загрузку файла без Cloudflare:
- Временно отключите прокси Cloudflare для вашего домена
- Попробуйте загрузить файл
- Если успешно, Cloudflare точно был проблемой
-
Проверьте заголовки запросов:
bashcurl -I -X POST --data-binary "@large_file.zip" http://mysite.io/upload
Ключевой вывод заключается в том, что лимиты Cloudflare по умолчанию, скорее всего, являются основной причиной ваших ошибок 413. Хотя правильная настройка client_max_body_size в nginx-proxy важна, вам придется решить проблему ограничения Cloudflare либо через обход, обновление или пользовательские правила, чтобы успешно обрабатывать загрузку больших файлов.
Источники
- Nginx: 413 - Request Entity Too Large Error and Solution - nixCraft
- nginx - client_max_body_size has no effect - Stack Overflow
- How can I change the docker jwilder/nginx-proxy upload limits? - Stack Overflow
- docker-compose.yml and client_max_body_size · Issue #690 · nginx-proxy/nginx-proxy
- docker push error “413 Request Entity Too Large” - Stack Overflow
- Error: 413 “Request Entity Too Large” in Nginx with “client_max_body_size” - Medium
Заключение
- Лимит Cloudflare в 100 МБ является основным барьером для ваших загрузок файлов, а не конфигурация Nginx
- Используйте переменные окружения (
CLIENT_MAX_BODY_SIZE,GLOBAL_MAX_BODY_SIZE) в вашей конфигурации nginx-proxy для надежных лимитов - Рассмотрите возможность обхода Cloudflare для специализированных поддоменов загрузки как наиболее практичное решение
- Проверьте участие Cloudflare, проверив наличие заголовков
cf-rayили временно отключив прокси Cloudflare - Регулярный мониторинг как логов Cloudflare, так и Nginx поможет диагностировать будущие проблемы с загрузкой
Наиболее эффективное долгосрочное решение, вероятно, представляет собой комбинацию правильной конфигурации nginx-proxy с переменными окружения и стратегического обхода Cloudflare для конечных точек загрузки, как вы уже обнаружили с вашим поддоменом upload.mysite.io.