In the previous chapter, we added MySQL database to Docker, but the development server adopted is convenient to use, but poor performance and low reliability, which cannot be applied in the production environment.

Therefore, this chapter will implement Docker + Django + MySQL + Nginx + Gunicorn container project to complete the final server deployment.

For starters, go back to chapter 1 of the tutorial and start reading. Otherwise, some of the content will be hard to understand. For those of you who have no idea how to deploy a Django project, you can start by reading my post on Deploying a Django project to a server.

Docker-compose

Try local deployment before deploying to the server.

Continue to modify the docker-comemage.yml configuration based on the previous chapter:

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:Copy the code

It’s a little complicated. Here’s the general idea:

  • Three of them are definedThe container, respectively,appdbnginx. Containers communicate with each other through defined ports.
  • Two of them are definednetwork, respectively,web_networkdb_network. Only containers on the same network can communicate with each other. Different networks are isolated and cannot communicate with each other even if they use the same port.
  • One is definedData volume.static-volume. Data volumes are great for multiple containers sharing the same data, as you can seeappnginxIt’s used.
  • exposeportsExpose only exposes ports to other containers, while ports expose ports to other containers and the host.

This might be hard to understand, but let’s keep breaking it down.

Internet network

Docker allows users to define the network in which each container works, and only communicate within the same network. You can see that the nginx container is on the Web_network and the DB container is on the DB_network, so the two can’t communicate and don’t really need to. The app container is in both web_network and DB_network, which is like a bridge between the three containers.

Defining a network can isolate the network environment of containers and facilitate O&M personnel to see the logical relationship of the network at a glance.

Data volume

The volume used to map the host and container directories we saw earlier is actually called mount; Now the new static-volume is called a volume. It is used like this: static-volume:/code/collected_static, where the colon is the directory inside the container, but before the colon is not the host directory, just the volume name. Data volumes are essentially a directory mapping between host and container, but the data volumes are managed by Docker, and you don’t even need to know where the data volumes are stored on the host.

Compared with mounting, the advantage of the data volume is that because it is uniformly managed by Docker, there is no mounting problem caused by insufficient permissions, and there is no need to specify different paths on different servers. The disadvantage is that it is not very suitable for single-profile mapping.

Just like mounting, the life cycle of a data volume is separated from the container, and the volume still exists after the container is deleted. The name of the specified volume can be used the next time the image is built.

Since Docker can manage volumes, it is very easy to delete them. Instructions, I will not tell you, the production environment must not be cheap. Backing up your data regularly is a good habit.

Data volumes have an important feature: if the volume is empty at startup, all contents of the container-mapped directory will be copied to the volume. In other words, once the volume is initialized, the container’s original collected_static directory is no longer used, and the new files only exist in the volume, not in the container.

Static persistent storage of static files (and media files) by mounting or data volume. Which one to use is a matter of opinion. It’s your choice.

The media media file is not covered in the tutorial because of limited space, but it is set up exactly the same as static.

Other configuration

Nginx container config/ 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/; }}Copy the code

In this configuration, Nginx listens on port 8000 of the container and sends requests to the APP container (except for static file requests).

Add the Gunicorn library to requirements.txt:

django==2.2
mysqlclient==1.314.
gunicorn==19.9. 0
Copy the code

Django_app /settings.py domain and directory for storing static files

. ALLOWED_HOSTS = [The '*']... STATIC_ROOT = os.path.join(BASE_DIR,'collected_static')
STATIC_URL = '/static/'
Copy the code

All configuration is complete.

The tutorial uses an empty Django project. For demonstration purposes, DEBUG=False has not been changed. Set it to False if you are testing with your own project.

test

The test instructions are as follows:

$ docker-compose up
Copy the code

Browser 127.0.0.1:8000 and you’ll see your familiar Django rocket again.

As in the previous chapter, you may fail to connect to MySQL when you start the container for the first time. This is because the db container has been started, but initialization is not complete. After you restart the container, it works. If multiple starts do not work properly, that is another reason, a good check.

If the local deployment is successful, deploy the server.

Server Deployment

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

Similarly, Docker, docker-compose, Python3 and other tools should be installed on the server before deployment. Clone the project locally to the server with Git.

Settings. Py, config/nginx/django_app.conf, requirements. TXT Copy docker-comemage. yml and Dockerfile to the server.

Docker-comemage.yml: docker-comemage.yml: docker-comemage.yml: docker-comemage.yml: docker-comemage.yml: docker-comemage.yml

version: "3" services: app: ... command: bash -c "... Your_project_name.wsgi: Application "# change your project name... db: ... nginx: ... Ports: - "80:8000" # listen on port 80... networks: ... volumes: ...Copy the code

Change the project name of the Gunicorn binding and let the host listen on the public HTTP default port 80.

Config /nginx/django_app.conf

upstream your_domain_name { ip_hash; server app:8000; } server { ... location / { proxy_pass http://your_domain_name/; }}Copy the code

This change is mainly to take care of the callback address of various third-party login (GitHub and Weibo login will fail if you do not change this one). If you don’t have a similar need, don’t change. For example, the blogger’s personal website is www.dusaiphoto.com, so change your_domain_name to www.dusaiphoto.com.

Finally, remember to modify the DEBUG configuration in settings.py:

# DEBUG=True
DEBUG=False
Copy the code

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

 docker-compose up
Copy the code

Your site should be accessible from your browser.

conclusion

You are now ready to deploy an online containerized Django project. Congratulations!

If you found this tutorial helpful, please give it a Star on GitHub and read my Django Build blog tutorials.

See you guys in the next tutorial!


  • If you have any questions please leave a message on Doucet’s personal website and I will reply as soon as possible.
  • Django-docker-tutorial
  • Or Email me a private message: [email protected]