Bobcares

Nginx and Gunicorn in Same Container | Setup Guide

by | Feb 29, 2024

Learn how to set up Nginx and Gunicorn in same container. Our Nginx Support team is here to help you with your questions and concerns.

Nginx and Gunicorn in the same container | Setup Guide

Today, we are going to take a look at integrating Gunicorn and Nginx within a Docker container.

An Introduction to Gunicorn

Gunicorn is a WSGI compliant web server for Python Applications. It receives requests sent by a Client to the Web Server and then forwards them to Web Frameworks or Python applications to run the application code for the request.

Nginx and Gunicorn in the same container | Setup Guide

 

Furthermore, the Gunicorn server is compatible with different web frameworks. Also, implementation is simple and light on server resource usage.

An Introduction to Gunicorn & Nginx

Gunicorn can handle requests very fast. Also, it only allows those requests through, that need to arrive at our web application.

When a request comes from Nginx, Gunicorn converts it into a format that our web application can understand and ensures that your code is run when necessary.

In other words, Gunicorn handles requests quickly, and Nginx acts as a reverse proxy, translating requests for optimal execution.

If we are running Django & Gunicorn within a Docker container, we can limit access to a specific domain.

This involves running NGINX alongside Gunicorn and Django. Although this is not recommended, it comes in handy in certain situations.

To do this, Django will be running via Gunicorn as a daemon process and NGINX as a non-daemon process.

Simplifying Django and Nginx Deployment in a Docker Container

Let’s break down the steps to deploy a Django application with Nginx using Docker. We’ll keep it simple and easy to follow.

  1. To begin with, we have to set up the local environment. So, go to the and create a project folder:
      cd path/to/your/dev/folder
    mkdir -p django-nginx
    Copy Code
  2. Then, create a Python virtual environment as seen here:
    python3 -m venv venvCopy Code

    On Windows, it might look like:

    C:\Python311\python.exe -m venv venvCopy Code
  3. Next, we have to activate the virtual environment:
    source venv/bin/activateCopy Code

    On Windows:

    .\venv\Scripts\activateCopy Code
  4. Now, it is time to install Django and Gunicorn. So, head to the project folder:
    cd django-nginxCopy Code
  5. Then, create a source folder to hold the Django project:
    mkdir -p srcCopy Code
  6. Next, add Django and Gunicorn to requirements.txt:
    echo "django" >> src/requirements.txt
    echo "gunicorn" >> src/requirements.txt
    Copy Code

    We can add any other project requirements we may have.

  7. We can install the requirements as seen here:
    $(venv) python -m pip install -r src/requirements.txtCopy Code

    Alternatively:

    venv/bin/python -m pip install -r src/requirements.txtCopy Code
  8. Now, it is time to create Django Project. So, move to the source directory and create a Django project named ‘cfehome’:
    cd src
    $(venv) django-admin startproject cfehome .
    Copy Code

    Alternatively:

    cd src
    ../venv/bin/django-admin startproject cfehome Copy Code
  9. At this point, we have to add Nginx Configuration. So, go back to the main project folder:
    cd path/to/your/dev/folder/django-nginxCopy Code
  10. Then, create a folder for Nginx configuration:
    mkdir nginxCopy Code
  11. Now, create `nginx/default.conf`with this content:
    upstream django_project {
    server localhost:8000;
    }
    error_log /var/log/nginx/error.log;
    server {
    listen       80;
    server_name  codingforentrepreneurs.com *.codingforentrepreneurs.com;
    root   /www/data/;
    access_log /var/log/nginx/access.log;
    location / {
    proxy_pass http://django_project;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header Host $host;
    proxy_redirect off;
    }
    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
    root   /usr/share/nginx/html;
    }
    }
    Copy Code
  12. Now, create `config/entrypoint.sh` in the source directory:
      #!/bin/bash
    RUN_PORT="8000"
    /opt/venv/bin/python manage.py migrate --no-input
    /opt/venv/bin/gunicorn cfehome.wsgi:application --bind "0.0.0.0:${RUN_PORT}" --daemon
    nginx -g 'daemon off;'
    Copy Code
  13. Then, create `Dockerfile`in the main project folder:
    FROM python:3.11-slim
    RUN apt-get update && apt-get install nginx -y
    COPY ./nginx/default.conf /etc/nginx/conf.d/default.conf
    RUN ln -sf /dev/stdout /var/log/nginx/access.log && ln -sf /dev/stderr /var/log/nginx/error.log
    COPY ./src ./app
    WORKDIR /app
    RUN python -m venv /opt/venv && \
    /opt/venv/bin/python -m pip install pip --upgrade && \
    /opt/venv/bin/python -m pip install -r requirements.txt
    RUN chmod +x config/entrypoint.sh
    CMD ["./config/entrypoint.sh"]
    Copy Code
  14. Finally, it is time to build and run the Docker image:
    docker build -t django-nginx -f Dockerfile .
    docker run -p 8000:80 --name django-nginx --rm django-nginx
    Copy Code

Now you have a simplified guide to deploy your Django application with Nginx using Docker!

Troubleshooting Tips

While deploying a Python Flask application with both Gunicorn and Nginx within a single container, users may run into issues. Usually, the Nginx component fails to initiate. This guide provides solutions and considerations for a seamless deployment.

1: Kubernetes Deployment

To fix the issue, we can try Kubernetes-based deployment. This involves separating Gunicorn and Nginx into different pods:

  1. First, create a Deployment and Service (ClusterIP) for Gunicorn.
  2. Then, create another Deployment and Service (NodePort or LoadBalancer) for Nginx.
  3. Now, configure Nginx to reference the Gunicorn Service as the backend host in its configuration using the `proxy_pass` directive.

This solution offers independent scalability and customization of each pod. Additionally, the automatic recreation of Pods is managed by the Deployment during application updates.

Also, we do not need to restart Nginx if the Python service (Gunicorn) crashes.

2: Docker Compose

Alternatively, we can use Docker Compose and simplify the YAML file structure:


version: '3.8'
services:
backend:
build: .
proxy:
image: nginx
volumes:
- ./nginx-conf:/etc/nginx/conf.d
ports:
- '8888:80'
Copy Code

This method helps avoid challenges associated with running multiple processes in one container. Also, it simplifies the Dockerfile structure for Gunicorn.

3: Daemon Mode for Gunicorn

If maintaining a single container is preferred, we can modify the Gunicorn startup in daemon mode to resolve issues. Update the Dockerfile CMD to:

CMD gunicorn --bind :8000 --workers 3 wsgi:app -DCopy Code

This will help Gunicorn and Nginx function within a single container.

4: Kubernetes Pod with Two Containers

In case the containers work independently but communicate, we can consider a single pod with two containers:

apiVersion: v1
kind: Pod
spec:
containers:
- name: gunicorn-container
image:
- name: nginx-container
image: nginx
ports:
- containerPort: 80
Copy Code

At the end of the day, choosing the right solution depends on our deployment goals and preferences.

[Need assistance with a different issue? Our team is available 24/7.]

Conclusion

In brief, our Support Experts demonstrated how to integrate Nginx and Gunicorn in the same container.

PREVENT YOUR SERVER FROM CRASHING!

Never again lose customers to poor server speed! Let us help you.

Our server experts will monitor & maintain your server 24/7 so that it remains lightning fast and secure.

GET STARTED

0 Comments

Submit a Comment

Your email address will not be published. Required fields are marked *

Speed issues driving customers away?
We’ve got your back!