Django docker containerized deployment: Django docker MySQL nginx gunicorn cloud deployment

Time:2020-7-7

In the previous chapter, we added MySQL database to docker, but the development server adopted is easy to use, but it has poor performance and low reliability, so it can not be applied in production environment.

Therefore, this chapter will implement the docker + Django + MySQL + nginx + gunicorn container project to complete the final server deployment.

For those who directly enter this chapter, it is recommended to go back to Chapter 1 of the tutorial to start reading, otherwise some contents are difficult to understand. Readers who have no concept of Django project deployment can also read my blog post: deploying the Django project to the server.

Docker-compose

Try local deployment before deploying to the server.

On the basis of the previous chapter, continue to revisedocker-compose.ymlto configure:

version: "3"

services:
  app:
    restart: always
    build: .
    command: bash -c "python3 manage.py collectstatic --no-input && python3 manage.py migrate && gunicorn --timeout=30 --workers=4 --bind :8000 django_app.wsgi:application"
    volumes:
      - .:/code
      - static-volume:/code/collected_static
    expose:
      - "8000"
    depends_on:
      - db
    networks:
      - web_network
      - db_network
  db:
    image: mysql:5.7
    volumes:
      - "./mysql:/var/lib/mysql"
    ports:
      - "3306:3306"
    restart: always
    environment:
      - MYSQL_ROOT_PASSWORD=mypassword
      - MYSQL_DATABASE=django_app
    networks:
      - db_network
  nginx:
    restart: always
    image: nginx:latest
    ports:
      - "8000:8000"
    volumes:
      - static-volume:/code/collected_static
      - ./config/nginx:/etc/nginx/conf.d
    depends_on:
      - app
    networks:
      - web_network
      
networks:
  web_network:
    driver: bridge
  db_network:
    driver: bridge
    
volumes:
  static-volume:

It’s a little complicated. Take a look at the general idea:

  • Three are definedcontainer, respectivelyappdbandnginx。 Containers communicate through defined ports.
  • Two are definednetwork, respectivelyweb_networkanddb_network。 Only containers in the same network can communicate with each other. Different networks are isolated and cannot communicate even with the same port.
  • 1 is definedData volumestatic-volume。 Data volumes are great for multiple containers to share and use the same data, as you can seeappandnginxIt’s all used.
  • exposeandportsThe difference is that expose is only exposed to other containers, while ports is exposed to other containers and hosts.

It’s still hard to understand. Let’s continue to decompose.

Network

Docker allows users to define the network in which each container works. Communication can only be carried out in the same network. You can see thatnginxContainer inweb_networkNetwork, anddbContainer indb_networkThe network, therefore, is unable to communicate with each other. In fact, it does not need to communicate. andappThe container is in theweb_networkanddb_networkThe network, equivalent to a bridge, connects three containers.

Defining the network can isolate the network environment of the container, and also facilitate the operation and maintenance personnel to see the logical relationship of the network at a glance.

Data volume

The volumes we’ve seen previously for mapping host and container directories are actually calledmount ; now newstatic-volumeJust callvolume。 It’s used like this:static-volume:/code/collected_staticAfter the colon is the directory in the container, but before the colon is not the host directory, just the name of the volume. In essence, the data volume also realizes the directory mapping between the host and the container, but the data volume is managed by docker, and you don’t even need to know the specific location of the data volume stored in the host.

Compared with mount, the advantage of data volume is that it is uniformly managed by docker, there is no mount problem caused by insufficient permissions, and there is no need to specify different paths in different servers. The disadvantage is that it is not suitable for mapping single configuration files.

Like Mount, the lifecycle of a data volume is detached from the container, and the volume still exists after the container is deleted. The next time you build the mirror, the name of the specified volume is ready for use.

Since docker can manage volumes, it is also very easy to delete volumes. Instructions, I will not tell you, production environment must not be cheap. It’s a good habit to back up your data regularly.

Data volumes have an important feature: if the volume isEmpty, all contents of the container mapping directory will be copied to the volume. In other words, as long as the volume initialization is complete, the container’s originalcollected_staticThe directory is no longer used, and the newly added files only exist in the volume, not in the container.

In fact, the persistent storage of static static files (as well as media files) is realized throughmount perhapsData volumeYou can do it; you can choose which one to use.

Due to the limited space, the tutorial does not mention media files, but its settings are exactly the same as static.

Other configurations

First, modify the configuration file of nginx, which is mapped tonginxContainerizedconfig/nginx/django_app.conf

upstream app {
  ip_hash;
  server app:8000;
}

server {
  listen 8000;
  server_name localhost;
  
  location /static/ {
    autoindex on;
    alias /code/collected_static/;
  }
  
  location / {
    proxy_pass http://app/;
  }
}

In this configuration, nginx will listen to the 8000 port of the container and send the received request to theappContainer (except for static file requests).

stayrequirements.txtAdd in filegunicornLibrary:

django==2.2
mysqlclient==1.3.14
gunicorn==19.9.0

Last revisiondjango_app/settings.pyOffieldAnd static filesStorage directoryConfiguration of:

...

ALLOWED_HOSTS = ['*']

...

STATIC_ROOT = os.path.join(BASE_DIR, 'collected_static')
STATIC_URL = '/static/'

All the configuration is complete.

The tutorial uses an empty Django project. To demonstrate the effect, debug = false is not modified. If you test with your own project, remember to call it false.

test

There is only one test instruction:

$ docker-compose up

Browser access127.0.0.1:8000I see the familiar Django rocket again.

Similar to the previous chapter, the first time you start a container, you may encounter an error that you cannot connect to MySQL. This is because although the DB container has been started, the initialization is not completed. After the container is restarted, it can work normally. If it doesn’t work after many starts, it’s another reason. Check it.

The local deployment is successful. The next step is server deployment.

Server deployment

With the experience of local deployment, server deployment is very, very simple.

Similarly, install docker, docker compose, Python and other tools on the server before deployment; clone the project to the local server with GIT.

Next, put thesettings.pyconfig/nginx/django_app.confrequirements.txtThe relevant positions were changed according to the tutorial processdocker-compose.ymlandDockerfileCopy to the server.

Since the default HTTP request is port 80, a little modification is needed to receive public network requestsdocker-compose.ymlWork:

version: "3"

services:
  app:
    ...
    command: bash -c "... your_ project_ name.wsgi Change to your project name
    ...
  db:
    ...
  nginx:
    ...
    ports:
      -"80:8000" ා monitor port 80
    ...
      
networks:
  ...
    
volumes:
  ...

Modify the project name bound by gunicorn and let the host listen to the default port 80 of public network http.

In addition, it has to be modifiedconfig/nginx/django_app.conf

upstream your_domain_name {
  ip_hash;
  server app:8000;
}

server {
  ...
  
  location / {
    proxy_pass http://your_domain_name/;
  }
}

This change is mainly to take care of the callback addresses of various third-party logins (GitHub and Weibo will fail if you do not change here). If you don’t have similar needs, it’s OK not to change. For example, a blogger’s personal website iswww.dusaiphoto.comSo here it isyour_domain_nameIt is amended aswww.dusaiphoto.com

Finally, remember tosettings.pyModify debug configuration in

#Debug = true comment out
DEBUG=False

That’s it! Build the image and start the container:

 docker-compose up

In the browser, you can visit your website normally.

summary

Now you can deploy an online containerized Django project. Congratulations!

If this tutorial is helpful to you, please send a star to GitHub, and welcome to my Django blog tutorial.

Old friends, see you next tutorial!


  • If you have any questions, please leave a message on dusai’s personal website, I will reply as soon as possible.
  • Tutorial example code: Django docker tutorial
  • Or email me: [email protected]

Recommended Today

ASP.NET Example of core MVC getting the parameters of the request

preface An HTTP request is a standard IO operation. The request is I, which is the input; the responsive o is the output. Any web development framework is actually doing these two things Accept the request and parse to get the parameters Render according to the parameters and output the response content So let’s learn […]