Deploying Django project with Nginx, uWSGI and docker

I am trying to deploy and run a django application by using uWSGI, Nginx and docker on DigitalOcean. The Nginx and uWSGI works fine (I think) but I do not know why the uWSGI do not recieve any requests from Nginx.

Here is my nginx configuration

# upstream for uWSGI
upstream uwsgi_app {
    server unix:/tmp/uwsgi/my_project.sock;
}

# upstream for Daphne
upstream daphne {
    server unix:/tmp/uwsgi/my_project_daphne.sock;
}

server {
    listen 80;
    server_name www.domaine.com domaine.com;
    return 301 https://$host$request_uri;
}

server {
    listen               443 ssl;
    ssl_certificate      /code/django_project/ssl/certs/cert.pem;
    ssl_certificate_key  /code/django_project/ssl/certs/key.pem
    server_name  www.domaine.com domaine.com;
    error_log    stderr warn;
    access_log   /dev/stdout main;

    location / {
        include      /etc/nginx/uwsgi_params;
        uwsgi_pass   uwsgi_app;
    }

    location /ws/ {
        proxy_http_version  1.1;
        proxy_set_header    Upgrade $http_upgrade;
        proxy_set_header    Connection "upgrade";
        proxy_redirect      off;
        proxy_pass          http://daphne;
    }

    location /static/ {
        alias /code/django_project/staticfiles/;
    }
    location /media/ {
        alias /code/django_project/mediafiles/;
    }
}

my uWSGI file

[uwsgi]

socket       = /tmp/uwsgi/my_project.sock
chdir        = /code/django_project/

module       = django_project.wsgi:application
master       = true
processes    = 2

chmod-socket = 666
uid          = www-data
gid          = www-data

harakiri     = 60
vacuum       = true
buffer-size  = 32768

logger       = file:/tmp/uwsgi.log
log-maxsize  = 200000

**My Dockerfile **

FROM python:3.11.5


### 3. Set environment variables
ENV PYTHONUNBUFFERED 1
ENV PYTHONDONTWRITEBYTECODE 1


RUN mkdir /code
COPY . /code/
WORKDIR /code

RUN chmod +x /code/wait-for-it.sh


# uwsgi setup
RUN apk add python3-dev build-base linux-headers pcre-dev

RUN set -e;\
    /usr/local/bin/python -m pip install --upgrade pip ;\
    python -m pip install --default-timeout=100 -r /code/requirements/deploy.txt ;


CMD ["uwsgi", "--ini", "/code/config/uwsgi/uwsgi.ini"]

My docker-compose.yml file :

services:

app:
    image: "${APP_IMAGE}"
    restart: unless-stopped
    command: >
      bash -c "./wait-for-it.sh db:5432 --
      && uwsgi --ini /code/config/uwsgi/uwsgi.ini
      && python /code/django_project/manage.py makemigrations
      && python /code/django_project/manage.py migrate"
    volumes:
      - .:/code
      - /var/log/django_project:/code/logs
      - uwsgi_data:/tmp/uwsgi/
    environment:
      - DJANGO_SETTINGS_MODULE=django_project.settings.test
      - POSTGRES_USER=${USER_DB}
      - POSTGRES_PASSWORD=${PASSWORD_DB}
      - POSTGRES_DB=${DB_NAME}
      - POSTGRES_PORT= ${PORT_DB}
    env_file:
      - .env
    networks:
      - django_project_network
    container_name: app


nginx:
    container_name: nginx
    restart: unless-stopped
    image: "${NGINX_IMAGE}"
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - uwsgi_data:/tmp/uwsgi/
    command: "/bin/sh -c 'while :; do sleep 6h & wait ${!}; nginx -s reload; done & nginx -g \"daemon off;\"'"
    networks:
      - django_project_network
    depends_on:
      - app

volumes:
  uwsgi_data:

networks:
    django_project_network:
        driver: bridge

In the logs, of docker, that is what I get for app :

[uWSGI] getting INI configuration from /code/config/uwsgi/uwsgi.ini
wait-for-it.sh: waiting 15 seconds for db:5432
wait-for-it.sh: db:5432 is available after 0 seconds
[uWSGI] getting INI configuration from /code/config/uwsgi/uwsgi.ini
wait-for-it.sh: waiting 15 seconds for db:5432
wait-for-it.sh: db:5432 is available after 0 seconds
[uWSGI] getting INI configuration from /code/config/uwsgi/uwsgi.ini
wait-for-it.sh: waiting 15 seconds for db:5432
wait-for-it.sh: db:5432 is available after 0 seconds
[uWSGI] getting INI configuration from /code/config/uwsgi/uwsgi.ini
wait-for-it.sh: waiting 15 seconds for db:5432
wait-for-it.sh: db:5432 is available after 0 seconds
[uWSGI] getting INI configuration from /code/config/uwsgi/uwsgi.ini
2024/06/15 17:32:58 [notice] 9#9: using the "epoll" event method
2024/06/15 17:32:58 [notice] 9#9: nginx/1.23.1
2024/06/15 17:32:58 [notice] 9#9: built by gcc 10.2.1 20210110 (Debian 10.2.1-6)
2024/06/15 17:32:58 [notice] 9#9: OS: Linux 5.15.0-112-generic
2024/06/15 17:32:58 [notice] 9#9: getrlimit(RLIMIT_NOFILE): 1048576:1048576
2024/06/15 17:32:58 [notice] 9#9: start worker processes
2024/06/15 17:32:58 [notice] 9#9: start worker process 10
# 2024/06/15 17:34:28 [error] 10#10: *1 open() "/usr/share/nginx/html/index.php" failed (2: No such file or directory), client: 94.73.145.234, server: localhost, request: "GET /index.php?route=extension/module/update/cevap HTTP/1.0", host: "domaine.com"
94.73.145.234 - - [15/Jun/2024:17:34:28 +0000] "GET /index.php?route=extension/module/update/cevap HTTP/1.0" 404 153 "-" "-" "-"
2024/06/15 17:40:08 [error] 10#10: *7 open() "/usr/share/nginx/html/wp-content/plugins/hellopress/wp_filemanager.php" failed (2: No such file or directory), client: 52.169.254.120, server: localhost, request: "GET /wp-content/plugins/hellopress/wp_filemanager.php HTTP/1.1", host: "domaine.com"
52.169.254.120 - - [15/Jun/2024:17:40:08 +0000] "GET /wp-content/plugins/hellopress/wp_filemanager.php HTTP/1.1" 404 153 "-" "-" "-"
2024/06/15 17:40:08 [error] 10#10: *7 open() "/usr/share/nginx/html/lv.php" failed (2: No such file or directory), client: 52.169.254.120, server: localhost, request: "GET /lv.php HTTP/1.1", host: "domaine.com"
52.169.254.120 - - [15/Jun/2024:17:40:08 +0000] "GET /lv.php HTTP/1.1" 404 153 "-" "-" "-"
2024/06/15 17:40:09 [error] 10#10: *7 open() "/usr/share/nginx/html/wp-22.php" failed (2: No such file or directory), client: 52.169.254.120, server: localhost, request: "GET /wp-22.php?sfilename=bdkr28tools.php&sfilecontent=&supfiles= HTTP/1.1", host: "domaine.com"
52.169.254.120 - - [15/Jun/2024:17:40:09 +0000] "GET /wp-22.php?sfilename=bdkr28tools.php&sfilecontent=&supfiles= HTTP/1.1" 404 153 "-" "-" "-"
2024/06/15 17:40:09 [error] 10#10: *7 open() "/usr/share/nginx/html/wp-content/plugins/pwnd/pwnd.php" failed (2: No such file or directory), client: 52.169.254.120, server: localhost, request: "GET /wp-content/plugins/pwnd/pwnd.php HTTP/1.1", host: "domaine.com"
52.169.254.120 - - [15/Jun/2024:17:40:09 +0000] "GET /wp-content/plugins/pwnd/pwnd.php HTTP/1.1" 404 153 "-" "-" "-"

Please can you help me to figure out how to make it work together ? I think that is the main problem. I really need your help. Any answer is welcome. Thanks for advance :slight_smile:

I try to read the uwsgi docs and some youtube vidoes but nothing works for me.

Welcome @samdjose !

Those are attacks. Someone is scanning your ip address looking for vulnerabilities.

I see no requests here even being made for your Django app.

You’ll want your makemigrations and migrate to run before you launch uwsgi.

You’ll also want to verify that the socket file is created and that the appropriate permissions are granted on it.

If this is the first time you’ve done a production deployment, I would strongly suggest you do an initial deployment that is not within docker containers. There are enough little things that can go wrong that you at least want to see what a working deployment looks like before adding docker into the mix. (This means seeing what the logs should look like when the deployment is functional. It makes it easier to see when something has gone wrong.)

Note: In my nginx configurations, I have the socket address specified as unix:///run/... that is three slashes instead of one for domain sockets within the file system.

Thank you for taking time to find a solution to my problem.
So you mean the messages I am getting form nginx are attacks. So what can I do to avoid that or I do not want to worry about that ? Because as you metion, this is my first time to deploy a django application using Nginx, uWSGI and docker so not too familliar with that. Is there any kind of securities things I have to do for that ?

So as you mention, I review my nginx configuration as it is mention in the documentaion tutorial and change it like that :

 # upstream for uWSGI
upstream uwsgi_app {
    server unix:///tmp/uwsgi/my_project.sock;
}

# upstream for Daphne
upstream daphne {
    server unix:///tmp/uwsgi/my_project_daphne.sock;
}

server {
    listen 80;
    server_name www.domain.com domain.com;
    return 301 https://$host$request_uri;
}

server {
    listen               443 ssl;
    ssl_certificate      /code/django_project/ssl/certs/cert.pem;
    ssl_certificate_key  /code/django_project/ssl/certs/key.pem
    server_name  www.domain.com domain.com;
    error_log    stderr warn;
    access_log   /dev/stdout main;

    location / {
        include      /etc/nginx/uwsgi_params;
        uwsgi_pass   uwsgi_app;
    }

    location /ws/ {
        proxy_http_version  1.1;
        proxy_set_header    Upgrade $http_upgrade;
        proxy_set_header    Connection "upgrade";
        proxy_redirect      off;
        proxy_pass          http://daphne;
    }

    location /static/ {
        alias /code/django_project/staticfiles/;
    }
    location /media/ {
        alias /code/django_project/mediafiles/;
    }
}

But still get the same result.

Okay so I have to try to deploy my application without docker containers first before trying to add it right ! Fine, no probleme with that I thing I can do it on my own with digitalOcean droplet.

Thanks for your help I appriciate :blush:

You can’t “avoid” them, they’re a sad fact of life of servers on the internet. There are some steps you can take to mitigate them, but they all requre various degrees of effort to install and maintain.

That’s a whole career in itself. Keeping a server secure isn’t trivial.

Is it a good pratice to run the Django in docker and nginx in host os ?

Wow thats a grt ans
Hello Sit can u help me ?

I want to know if we can create microservices in django and how to do it, can we find any refrence what are the technologies involved in it?

Welcome @Aastha22j02 !

Please don’t write posts tagging people requesting assistance. We are all volunteers here, answering questions as time, knowledge, and energy allows.

Also, please don’t jump into other threads referencing questions or issues that you have already posted.

I don’t see any problem with doing that. But then I don’t see any particular benefit to it either.

I guess I would say I’m probably neutral on the idea. Like a lot of other options for deployment, I’d probably say that the decision to do (or not do) this would depend upon other, non-technical, factors.

Okay I see. the thing is that, I try to find solution and in my research I found that some people try to run the django application using docker and expose a port then setup reverse proxy using nginx.

I am very confuse. I did not know that deploying django application using uwsgi, docker and ngnix can be a nightmare :hot_face:

See the threads and my comments at:

Short version, yes, deploying Django properly is confusing, precisely because there are so many different ways of deploying it and the software used to do so.

(Just off the top of my head, I’d say I’ve deployed Django in at least 5 different ways, all different depending upon the target environment involved. That’s with and without docker; uwsgi, gunicorn, and even Werkzeug in a couple of very limited-target environments; both Apache and nginx; and that’s not even beginning to count the different configurations I’ve played with in a test lab environment.)

A big problem occurs when you go searching through the internet trying to find answers, and you start finding conflicting information. It’s not even necessarily the case that one person is wrong where the other is right - they both can be correct. But this doesn’t help when you’re trying to work through issues in areas you’re not yet familiar with.

In general, my advice is always “go with what you know” at first. Try to minimize the number of unknowns that you will need to deal with, unless you’re working from a functional starting point.