Implementation of docker deployment of Django + MySQL + redis + gunicorn + nginx

Time:2021-1-19

1、 Preface

Docker technology is very popular now. It is very efficient to build a project environment through containers. So recently, I took the time to read some tutorials, and then changed the blog deployment mode to docker. I don’t feel that there is any particularly good blog on the InternetdockerdeploydjangoProject tutorial, specially wrote this article, is to record their own experience.

The test environment for this tutorial isDeepin, mainly focusing onArrangement of containersandDjangoThe related deployment knowledge and some details, such as environment dependent installation, will not be described in detail. Since it is tested locally, it can be configured locallynginxRelevant information will be configuredhttpActing instead of actinghttpsAgent.

2、 Environmental dependence

The deployment mode is docker plus docker compose, so you need to install docker and docker compose.

  • Docker can be accessed throughsudo apt install docker-ceCommand installation.
  • Docker compose can be installed with the following command.

sudo curl -L https://get.daocloud.io/docker/compose/releases/download/1.22.0/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose 
sudo chmod +x /usr/local/bin/docker-compose

After the installation, enterdocker version, the following screen indicates that the docker is installed successfully.

inputdocker-compose version, the following screen indicates that docker compose is installed successfully.

3、 Deployment Analysis

It is used in the blog projectDjango , Mysql , Redis , NginxTherefore, four containers are needed, and each container corresponds to an application. Of course, these containers have a sequence, that is to say, there is a dependency relationship. Then the four containers are arranged by docker compose to build the container running environment.

Four containers in total:

  • Redis container: caching service
  • MySQL container: data storage
  • Django (gunicorn) container: handling dynamic requests
  • Nginx container: reverse proxy, dealing with static resources

Here is the structure diagram of the container.

Container dependency: Django container depends on redis container and MySQL container, nginx container depends on gunicorn container.

4、 Project structure

See this tutorial, please try to keep the directory and tutorial directoryagreementOtherwise, errors are likely to occur in the subsequent deployment process.

my_ Blog isdjangoProject directory,deploymentFolder placed exceptDjangoThree container configuration information outside the container.

Dockerfile: docker environment file

docker- compose.yml : orchestrating container files

start.sh : shell command script executed after container initialization

requirements.txt : Django project environment dependency file

gunicorn.conf : gunicorn configuration file

The deployment directory containsmysqlContainer configuration information,nginxContainer configuration information andredisContainer data directory.

MySQL: put database configuration information, conf put database initialization configuration file my.cnf , data is used to mount database data, init places SQL script (import table structure and data, and mount them into container).

Nginx: place nginx configuration information, SSL place SSL certificate

Redis: Mount redis data

5、 Building Django container environment

1. Write dockerfile for Django project

Container environment and native environment arequarantineYes, you can use containers asAnother systemAt first, this system is the same as your local systemNo connectionBy writingDockerfilefileConfigure and buildContainer environment (like configuring a python environment on a clean system).

#Building a python 3.6 environment
FROM daocloud.io/python:3.6

#Mirror author
MAINTAINER zyk [email protected]

#Setting Python environment variables
ENV PYTHONUNBUFFERED 1

#Create my_ Blog folder
RUN mkdir /my_blog

#Will my_ Blog folder is the working directory
WORKDIR /my_blog

#Add the current directory to the working directory (. Indicates the current directory)
ADD . /my_blog

#Use pip to install dependency (- I means the specified source, the default source download is too slow)
RUN pip3 install -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple/

#Setting environment variables
ENV SPIDER=/my_blog

2. Write the gunicorn configuration file

to write gunicorn.conf File, used to start gunicorn

Workers = 3 # number of parallel work processes 
Threads = 2 # specifies the number of threads per worker 
Bind = ['0.0.0:8000 '] # monitoring intranet port 8000 
proc_ name='my_ Blog '# process name 
pidfile='/tmp/ blog.pid '# set the process file directory 
worker_ Class ='gevent 'ා working mode coroutine 
Timeout = 30 # timeout 
max_ Requests = 6000 # maximum number of requests

3. Preparation start.sh Command script

start.sh The script is used to start the Django container

#!/bin/bash
#From the first line to the last line:
#1. The daemons execute the celery, and the partners without this requirement can delete the first command
#2. Collect static files to the root directory,
#3. Generate database executable file,
#4. Modify the database according to the database executable file
#5. Start Django service with gunicorn
celery multi start w1 -A celery_tasks.tasks worker -l info&&
python manage.py collectstatic --noinput&&
python manage.py makemigrations&&
python manage.py migrate&&
gunicorn my_blog.wsgi:application -c gunicorn.conf

6、 Building nginx container environment

1. Write dockefile of nginx container

Create and write dockerfile in nginx folder

#Nginx image
FROM daocloud.io/nginx

#Delete the original configuration file, create static resource folder and SSL certificate save folder
RUN rm /etc/nginx/conf.d/default.conf \
&& mkdir -p /usr/share/nginx/html/static \
&& mkdir -p /usr/share/nginx/html/media \
&& mkdir -p /usr/share/nginx/ssl

#Add profile
ADD ./nginx.conf /etc/nginx/conf.d/

2. Configuration nginx.conf

nginx.conf It is used to reverse proxy domain name or IP, distribute dynamic requests to port 8000 of Django container, and configure static resource path.

When configuring the reverse proxy, note that the host must be changed to web, which is the name of the Django container (in docker)- compose.yml Medium configuration)

#Only for local docker environment test (80 port proxy HTTP request)
server {
 Listen 80; # listen to port 80
 server_ Name 127.0.0.1; # please change the production environment to domain name
 location / {
  proxy_ pass  http://web : 8000; # reverse proxy Django container 8000 port, web is Django container name, remember not to write domain name or IP
  proxy_set_header Host $host;
  proxy_redirect off;
  proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
 }
 location /static/ {
  Alias / usr / share / nginx / HTML / static /; # static resource path
 }
 location /media/ {
  Alias / usr / share / nginx / HTML / media /; # upload file path
 }
}

7、 Configure MySQL

1. Preparation my.cnf file

my.cnf File is used to initialize MySQL configuration, and this file will be mounted to the container.


[mysqld]
user=mysql
default-storage-engine=INNODB
character-set-server=utf8
sql_mode=STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION
[client]
default-character-set=utf8
[mysql]
default-character-set=utf8

2. Import the initialization SQL file (you can ignore this step if you don’t need to import the initial database)

Put the SQL file to be imported into the init directory and change its name to init.sql

8、 Using docker compose to arrange container

Write docker- compose.yml

version: "3"
services:
 redis:
 image: daocloud.io/redis:3
 command: redis-server
 volumes:
  - ./deployment/redis:/data
 ports:
  - "6379:6379"
 Restart: always restart when the always # always table container runs in error

 db:
 image: daocloud.io/mysql:5.7
 environment:
  - MYSQL_ DATABASE=my_ Blog # database name
  - MYSQL_ ROOT_ Password = 19960331 ᦇ database password
 volumes:
  -. / deployment / MySQL / data / var / lib / MySQL? Mount database data
  - ./deployment/mysql/conf/ my.cnf :/etc/mysql/ my.cnf  #Mount profile
  -. / deployment / MySQL / init / docker entrypoint initdb. D / # mount data to initialize SQL script
 ports:
  - "3306:3306"
 restart: always

 web:
 build: .
 expose:
  - "8000"
 volumes:
  - .:/my_blog
  - /tmp/logs:/tmp
 command: bash start.sh
 links:
  - db
  - redis
 depends_on:
  - db
  - redis
 restart: always

 nginx:
 build: deployment/nginx
 ports:
  - "80:80"
  - "443:443"
 expose:
  - "8000"
 volumes:
  - ./collect_ Static / usr / share / nginx / HTML / static # mount static files
  -. / media / usr / share / nginx / HTML / media ᦇ mount upload file
  -. / deployment / nginx / SSL / usr / share / nginx / SSL
 links:
  - web
 depends_on:
  - web
 restart: always

Redis, DB, web and nginx are container names.

Image represents the name of the pull image,buildThe dockerfile will be found in the given directory and the container environment will be built.

Expose means to expose the port to other containers, butnoExposed to the host (different containers are isolated from each other by default).

Ports means to map the container port to the host port (read from right to left, for example, “3307:3306” means to map the 3306 port of the container to the 3307 port of the host), and the container port will also be open to other containers.

Volumes means mount, which is to map the files in the local machine and the files in the container. The container and the local environment are originally isolated. Mount is equivalent to digging a small hole so that the data between the two can be exchanged.

Links means to interconnect containers.

depends_ On: indicates dependency, because the containers are started in sequence. Django container depends on MySQL container and redis container (Django needs to read and write data from database and cache), while nginx depends on Django container (nginx container needs to reverse proxy port 8000 of Django container)

9、 Build and run container

Before building the run container, you need to modify the configuration of the Django projectsettings.pyDocuments.

Change the database connection host to MySQL container namedb

DATABASES = {
 'default': {
  'ENGINE': ' django.db.backends . MySQL ', # MySQL driver
  'NAME': 'my_ Blog ', # database name
  'user':'root '; login account
  'password':'19960331 ', ා login password
  'host':'db '; host address (container deployment)
  #'host':'127.0.0.1 ', # host address
  'port':'3306 ', ා port
  'OPTIONS': {'charset': 'utf8mb4'},
 }
}

Change host in cache configuration to redis container nameredis(if you have configured redis as cache, please ignore it if not.)

CACHES = {
 'default': {
  'BACKEND': 'django_redis.cache.RedisCache',
  'LOCATION': ' redis://redis : 6379 ', redis (container)
  # 'LOCATION': '127.0.0.1:6379',
  'OPTIONS': {
   "CLIENT_CLASS": "django_redis.client.DefaultClient",
   "CONNECTION_POOL_KWARGS": {"max_connections": 100},
   'SOCKET_TIMEOUT': 10,
  },
 },
}

For production environment deployment, pleasesettings.pyInDEBUG = TrueChange toDEBUG = FalseTo turn off debug mode.

Finally, execute the command at the root of the projectdocker-compose up --build

After execution, you can see the following screen to show that the construction is successful.

Access 127.0.0.1 or your public IP on the browser port. If you can access it successfully, it indicates that the construction is successful.

10、 Finally

It’s also the first time that I have used docker compose to deploy Django project. Please help me to point out if there is any improper or incorrect writing.

The above is the whole content of this article, I hope to help you learn, and I hope you can support developer more.

Recommended Today

DK7 switch’s support for string

Before JDK7, switch can only support byte, short, char, int or their corresponding encapsulation classes and enum types. After JDK7, switch supports string type. In the switch statement, the value of the expression cannot be null, otherwise NullPointerException will be thrown at runtime. Null cannot be used in the case clause, otherwise compilation errors will […]