--Web server - nginx --WSGI server (AP server) - Gunicorn --Web application framework - Django --Since WSGI is used here, other frameworks may be used as long as they are WSGI compliant. --No Django-specific settings occur in this article --Web server and WSGI server run in Docker container --Use UNIX domain sockets for communication between the web server and WSGI server
--WSGI stands for Web Server Gateway Interface, a protocol for communication between a web server and Python's AP server. --Frameworks such as Django, Flask, and Bottle also comply with this protocol. --The AP server that conforms to the above WSGI is called a WSGI server, and Gunicorn is one of them. --WSGI servers other than gunicorn have uWSGI
--Communication method to search for a communication partner through the path of the file system --A file is created in that path and each process accesses the file ――It seems that you are just sharing a file, but the created file is a special file called a socket file and there is no actual situation. --Communication interface
Gunicorn
--First, try running the WSGI server alone
--Install Django
$ pip install Django==3.0.2
--Create a project in your work environment
$ django-admin.py startproject django_project .
--Here, create a project with the name django_project --If you check with the tree command, it will be as follows
$ tree
.
├── django_project
│ ├── __init__.py
│ ├── asgi.py
│ ├── settings.py
│ ├── urls.py
│ └── wsgi.py
├── manage.py
--Create a Dockerfile
FROM python:3.8.0-alpine
WORKDIR /usr/src/app
ENV PYTHONDONTWRITEBYTECODE 1
ENV PYTHONUNBUFFERED 1
RUN pip install --upgrade pip
COPY ./requirements.txt /usr/src/app/requirements.txt
RUN pip install -r requirements.txt
--requirements.txt is as follows
requirements.txt
Django==3.0.2
gunicorn==20.0.4
--Build
$ docker build -t gunicorn:tmp .
--The description of docker-compose.yaml is as follows --I will add nginx information later
version: '3.7'
services:
gunicorn:
image: gunicorn:tmp
container_name: gunicorn
command: python manage.py runserver 0.0.0.0:8000
volumes:
- .:/usr/src/app/
ports:
- 8000:8000
-- python manage.py runserver 0.0.0.0:8000
command starts a simple test server
--Here, port 8000 is forwarded to check the operation.
--Start with $ docker-compose up -d
, access localhost: 8000, and if the Django screen is displayed, it's OK.
--Use the official Docker image, but create a conf file that describes the UNIX domain socket settings and mount it at startup --Description the following contents with the name gunicorn.conf
gunicorn.conf
upstream gunicorn-django {
server unix:///var/run/gunicorn/gunicorn.sock;
}
server {
listen 80;
server_name localhost;
location / {
try_files $uri @gunicorn;
}
location @gunicorn {
proxy_pass http://gunicorn-django;
}
}
--```upstream gunicorn-django {…}` `` contents are UNIX domain socket settings --Communicate with gunicorn via the socket file in the path described --In other words, it is necessary to set to call this socket file from the gunicorn side as well. --After that, you can specify gunicorn-django specified by upstream in proxy_pass of location. --The description of docker-compose.yaml of Nginx is as follows
version: '3.7'
services:
nginx:
image: nginx:1.17.7
container_name: nginx
ports:
- "80:80"
volumes:
- ./gunicorn.conf:/etc/nginx/conf.d/default.conf
--Mount in Nginx with the name /etc/nginx/conf.d/default.conf
--Nginx reads /etc/nginx/nginx.conf at startup and says include /etc/nginx/conf.d/*.conf;
in that file, so `` If you mount the conf file you created under `/etc/nginx/conf.d```, it will be read together at startup.
--Make some changes from the state where it was started locally earlier
--You need to hit the following gunicorn command so that Gunicorn can communicate with Nginx
gunicorn django_project.wsgi
--This loads wsgi.py under django_project, which is built when you create a project called django_project this time. --Manage.py was started when starting locally, but this command is required when communicating with WSGI.
--Specify the startup socket file path with `` `--bind``` to communicate with UNIX domain sockets.
gunicorn django_project.wsgi --bind=unix:/var/run/gunicorn/gunicorn.sock
--This enables UNIX domain socket communication to gunicorn
--Changed CMD of Dockerfile based on the above contents
Dockerfile
FROM python:3.8.0-alpine
WORKDIR /usr/src/app
ENV PYTHONDONTWRITEBYTECODE 1
ENV PYTHONUNBUFFERED 1
RUN pip install --upgrade pip
COPY ./requirements.txt /usr/src/app/requirements.txt
RUN pip install -r requirements.txt
RUN mkdir -p /var/run/gunicorn
CMD ["gunicorn", "django_project.wsgi", "--bind=unix:/var/run/gunicorn/gunicorn.sock"]
--Build again
$ docker build -t gunicorn:latest .
--Specify in ʻALLOWED_HOSTS = [] in setting.py created under django_project --It should be restricted normally, but here it is set to ʻALLOWED_HOSTS = [*]
to allow access from all hosts.
--This file is called from wsgi.py
--Since the socket file path was specified in Nginx and Gunicorn, it is necessary to create a socket file volume. --This time, we will start with Docker, so create a Docker Volume at startup and mount it from two containers to that Volume. --The final docker-compose.yaml is as follows
docker-compose.yaml
version: '3.7'
services:
gunicorn:
image: gunicorn:latest
container_name: gunicorn
volumes:
- .:/usr/src/app/
- gunicorn:/var/run/gunicorn
nginx:
image: nginx:1.17.7
container_name: nginx
depends_on:
- gunicorn
ports:
- "80:80"
volumes:
- ./gunicorn.conf:/etc/nginx/conf.d/default.conf
- gunicorn:/var/run/gunicorn
volumes:
gunicorn:
driver: local
--Create a Volume called gunicorn and mount it in each container (this time, / var / run / gunicorn
is specified in both containers)
--Start with the following command
$ docker-compose up -d
Starting gunicorn ... done
Starting nginx ... done
--Try accessing localhost
after startup
--OK if the screen is displayed --The screen displayed is the same as when Gunicorn was first run alone, but this time it is displayed via nginx.
--The set of files created this time is here
-Quick Start Guide: Docker Compose and Django -Introduction to uWSGI -Unix domain socket -Who runs django? (Overview for deployment) -Django ALLOWED_HOSTS settings -Run a Python web application on gunicorn (Django and Flask)
Recommended Posts