KeyError: REQUEST_METHOD with Django + uWSGI + nginx + docker

I've built a django REST-API and I want to deploy it on my server. Everything works fine in local dev environment. But on my server I have an error with nginx doesn't pass uwsgi_params correctly (I think).

The error

It seems to me that my configs work fine, since when I access my domain name, the logs appear on the server. However, the error seems to me that nginx doesn't pass the reqeust_method to wsgi in django.

I did found another post here which had the same error, however, I double checked the uwsgi_params file and it's not empty. So I have no clue.

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

I've created a dockerfile for my django app which runs and serves the application using uwsgi. The dockerfile is as follow

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"]

The entrypoint.sh file simply launches the uwsgi server.

#!/bin/sh

set -e

python manage.py collectstatic --noinput

uwsgi --socket :8000 --master --enable-threads --module simuzones_server.wsgi

Nginx docker

The 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

And the default.conf file

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;
    }
}

And the uwsgi_params file on host machine (server)

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;

The docker-compose (if needed)

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:

I would like to say thanks in advance, this problem takes me days and I couldn't figure it out yet.

Back to Top