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

  2. Then, create a Python virtual environment as seen here:

    python3 -m venv venv

    On Windows, it might look like:

    C:\Python311\python.exe -m venv venv

  3. Next, we have to activate the virtual environment:

    source venv/bin/activate

    On Windows:

    .\venv\Scripts\activate

  4. Now, it is time to install Django and Gunicorn. So, head to the project folder:

    cd django-nginx

  5. Then, create a source folder to hold the Django project:

    mkdir -p src

  6. Next, add Django and Gunicorn to requirements.txt:

    echo "django" >> src/requirements.txt
    echo "gunicorn" >> src/requirements.txt

    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.txt

    Alternatively:

    venv/bin/python -m pip install -r src/requirements.txt

  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 .

    Alternatively:

    cd src
    ../venv/bin/django-admin startproject cfehome

  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-nginx

  10. Then, create a folder for Nginx configuration:

    mkdir nginx

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

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

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

  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

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'

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 -D

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

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 *

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