KeyError: REQUEST_METHOD с Django + uWSGI + nginx + docker
Я создал django REST-API и хочу развернуть его на своем сервере. Все отлично работает в локальной среде разработки. Но на моем сервере у меня возникает ошибка: nginx не передает uwsgi_params правильно (я думаю).
Ошибка
Мне кажется, что мои настройки работают нормально, так как когда я обращаюсь к своему доменному имени, журналы появляются на сервере. Однако мне кажется, что ошибка заключается в том, что nginx не передает reqeust_method для wsgi в django.
Я нашел другой пост здесь, в котором была та же ошибка, однако, я дважды проверил файл uwsgi_params и он не пустой. Так что у меня нет подсказки.
simuzones_server_web | Traceback (most recent call last):
simuzones_server_web | File "/home/tx7093/.local/lib/python3.8/site-packages/django/core/handlers/wsgi.py", line 130, in __call__
simuzones_server_web | request = self.request_class(environ)
simuzones_server_web | File "/home/tx7093/.local/lib/python3.8/site-packages/django/core/handlers/wsgi.py", line 78, in __init__
simuzones_server_web | self.method = environ["REQUEST_METHOD"].upper()
simuzones_server_web | KeyError: 'REQUEST_METHOD'
simuzones_server_web | [pid: 11|app: 0|req: 1/1] () {48 vars in 977 bytes} [Sun Jan 22 13:28:53 2023] => generated 0 bytes in 5 msecs ( 500) 0 headers in 0 bytes (0 switches on core 0)
simuzones_server_web | Traceback (most recent call last):
simuzones_server_web | File "/home/tx7093/.local/lib/python3.8/site-packages/django/core/handlers/wsgi.py", line 130, in __call__
simuzones_server_web | request = self.request_class(environ)
simuzones_server_web | File "/home/tx7093/.local/lib/python3.8/site-packages/django/core/handlers/wsgi.py", line 78, in __init__
simuzones_server_web | self.method = environ["REQUEST_METHOD"].upper()
simuzones_server_web | KeyError: 'REQUEST_METHOD'
simuzones_server_web | [pid: 11|app: 0|req: 2/2] () {44 vars in 855 bytes} [Sun Jan 22 13:28:53 2023] => generated 0 bytes in 4 msecs ( 500) 0 headers in 0 bytes (0 switches on core 0)
Django app docker
Я создал dockerfile для моего приложения django, который запускает и обслуживает приложение с помощью uwsgi. Докерфайл выглядит следующим образом
FROM python:3.8.15-slim-buster
ARG user
ARG DEBIAN_FRONTEND=noninteractive
ENV PATH="/docker_scripts:/home/${user}/.local/bin:${PATH}"
ENV PYTHONUNBUFFERED 1
...
RUN mkdir /simuzones_server
COPY ./simuzones_server /simuzones_server
WORKDIR /simuzones_server
COPY ./docker_scripts /docker_scripts
RUN chmod +x /docker_scripts/*
RUN mkdir -p /vol/web/media
RUN mkdir -p /vol/web/static
RUN adduser --disabled-login $user
RUN chown -R $user:$user /vol
RUN chmod -R 755 /vol/web
USER $user
COPY requirements.txt /simuzones_server/
RUN /usr/local/bin/python -m pip install --upgrade pip
RUN cd /simuzones_server/
RUN pip install -r requirements.txt
CMD ["entrypoint.sh"]
Файл entrypoint.sh
просто запускает сервер uwsgi.
#!/bin/sh
set -e
python manage.py collectstatic --noinput
uwsgi --socket :8000 --master --enable-threads --module simuzones_server.wsgi
Nginx docker
Dockerfile
FROM nginxinc/nginx-unprivileged:1-alpine
COPY ./default.conf /etc/nginx/conf.d/default.conf
COPY ./uwsgi_params /etc/nginx/uwsgi_params
USER root
RUN mkdir -p /vol/static
RUN chmod 755 /vol/static
USER nginx
И файл default.conf
server {
listen 8080;
listen [::]:8080;
server_name simuzones.tk www.simuzones.tk;
return 301 https://$server_name$request_uri;
}
server {
# SSL configuration
listen 443 ssl http2;
listen [::]:443 ssl http2;
ssl_certificate /etc/ssl/cert.pem;
ssl_certificate_key /etc/ssl/key.pem;
server_name simuzones.tk www.simuzones.tk;
return 200 $request_method;
location /static {
alias /vol/static;
}
location / {
include /etc/nginx/uwsgi_params;
uwsgi_pass web:8000;
}
}
И файл uwsgi_params
на хост-машине (сервере)
uwsgi_param QUERY_STRING $query_string;
uwsgi_param REQUEST_METHOD $request_method;
uwsgi_param CONTENT_TYPE $content_type;
uwsgi_param CONTENT_LENGTH $content_length;
uwsgi_param REQUEST_URI $request_uri;
uwsgi_param PATH_INFO $document_uri;
uwsgi_param DOCUMENT_ROOT $document_root;
uwsgi_param SERVER_PROTOCOL $server_protocol;
uwsgi_param REMOTE_ADDR $remote_addr;
uwsgi_param REMOTE_PORT $remote_port;
uwsgi_param SERVER_ADDR $server_addr;
uwsgi_param SERVER_PORT $server_port;
uwsgi_param SERVER_NAME $server_name;
Докер-композит (если необходимо)
version: '3.7'
services:
web:
build:
args:
user: tx7093
context: .
ports:
- "8000:8000"
volumes:
- ./simuzones_server:/simuzones_server
- static_data:/vol/web
container_name: simuzones_server_web
environment:
- POSTGRES_DB=${POSTGRES_DB}
- POSTGRES_USER=${POSTGRES_USER}
- POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
- PGDATA=/var/lib/postgresql/data/pgdata
- DATABASE_URL=${DATABASE_URL}
- DEBUG=1
- SECRET_KEY=${SECRET_KEY}
- ALLOWED_HOSTS=${ALLOWED_HOSTS}
depends_on:
- db
nginx:
build:
context: ./nginx
volumes:
- static_data:/vol/static
- /etc/ssl:/etc/ssl
ports:
- "8080:8080"
depends_on:
- web
db:
image: postgres:11.18-bullseye
environment:
- POSTGRES_DB=${POSTGRES_DB}
- POSTGRES_USER=${POSTGRES_USER}
- POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
- PGDATA=/var/lib/postgresql/data/pgdata
- DATABASE_URL=${DATABASE_URL}
ports:
- "5432:5432"
volumes:
- type: bind
source: ./tmp/postgres-data
target: /var/lib/postgresql/data
volumes:
static_data:
Я хотел бы сказать спасибо заранее, эта проблема занимает у меня несколько дней, и я до сих пор не смог ее решить.
Мне удалось заставить его работать! Основная причина в том, что я не пробросил порт для SSL (443)