Django-Docker容器化部署:Django-Docker-MySQL-Nginx-Gunicorn云端部署

上一章咱们实现了在 Docker 中添加了 MySQL 数据库,但采用的开发服务器虽然使用便捷,但性能差、可靠性低,没法应用在生产环境中。python

所以本章将实现 Docker + Django + MySQL + Nginx + Gunicorn 容器项目,完成最终的服务器部署。mysql

直接进入本章的 Docker 入门读者,建议回到教程第一章开始阅读,不然某些内容很差理解。对 Django 项目部署都没有概念的读者,还能够先阅读个人博文:将 Django 项目部署到服务器nginx

Docker-compose

在部署到服务器以前,先来尝试本地部署。git

在上一章的基础上,继续修改 docker-compose.yml 配置:github

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:
复制代码

有点复杂。来看看大致思路:web

  • 定义了 3 个容器,分别是 appdbnginx 。容器之间经过定义的端口进行通信。
  • 定义了 2 个网络,分别是 web_networkdb_network 。只有处在相同网络的容器才能互相通信。不一样网络之间是隔离的,即使采用一样的端口,也没法通信。
  • 定义了 1 个数据卷static-volume 。数据卷很是适合多个容器共享使用同一数据,你能够看到 appnginx 都用到了它。
  • exposeports 均可以暴露容器的端口,区别是 expose 仅暴露给其余容器,而 ports 会暴露给其余容器和宿主机。

这么讲可能仍是很难理解,让咱们继续分解。sql

网络 network

Docker 容许用户给每一个容器定义其工做的网络,只有在相同的网络之中才能进行通信。你能够看到 nginx 容器处于 web_network 网络,而 db 容器处于 db_network 网络,所以它两是没法通信的,实际上确实也不须要通信。而 app 容器同时处于 web_networkdb_network 网络,至关因而桥梁,连通了3个容器。docker

定义网络能够隔离容器的网络环境,也方便运维人员一眼看出网络的逻辑关系。shell

数据卷

以前咱们见识过的用于映射宿主机和容器目录的卷了,实际上称为挂载;如今新出现的 static-volume 才叫。它的使用方式像这样:static-volume:/code/collected_static ,冒号后面仍是容器内的目录,但冒号前的却不是宿主机目录、仅仅是卷的名称而已。从本质上讲,数据卷也是实现了宿主机和容器的目录映射,可是数据卷是由 Docker 进行管理的,你甚至都不须要知道数据卷保存在宿主机的具体位置。数据库

相比挂载,数据卷的优势是因为是 Docker 统一管理的,不存在因为权限不够引起的挂载问题,也不须要在不一样服务器指定不一样的路径;缺点是它不太适合单配置文件的映射。

和挂载同样,数据卷的生命周期脱离了容器,删除容器以后卷仍是存在的。下次构建镜像时,指定卷的名称就能够继续使用了。

既然 Docker 可以管理卷,因此要想删除卷也是很是容易的。指令嘛,我不告诉你,生产环境千万不要手贱。按期备份数据是个好习惯。

数据卷有个很重要的特性:启动时若是卷是空的,则会将容器映射目录的全部内容复制到卷里去。换句话说就是,只要卷初始化完成后,容器原始的 collected_static 目录就不会再使用了,新增的文件也只存在于卷中,容器中是没有的。

实际上 static 静态文件(以及 media 媒体文件)的持久存储,经过挂载或者数据卷均可以实现;具体用哪一种,这个就见仁见智了,你本身选择。

篇幅有限,教程没有讲到 media 媒体文件,但它的设置和 static 是彻底相同的。

其余配置

首先修改 Nginx 的配置文件,即映射到 nginx 容器的 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/;
  }
}
复制代码

此配置下 Nginx 会监听容器的 8000 端口,并将受到的请求发送到 app 容器(静态文件请求除外)。

requirements.txt 文件中增长 gunicorn 库:

django==2.2
mysqlclient==1.3.14
gunicorn==19.9.0
复制代码

最后修改 django_app/settings.py和静态文件存放目录的配置:

...

ALLOWED_HOSTS = ['*']

...

STATIC_ROOT = os.path.join(BASE_DIR, 'collected_static')
STATIC_URL = '/static/'
复制代码

全部配置就完成了。

教程使用空的 Django 项目,为演示效果,就没有修改 DEBUG=False 了。若你用的本身的项目测试,记得把它为 False。

测试

测试指令就一条:

$ docker-compose up
复制代码

浏览器访问 127.0.0.1:8000 又看到熟悉的 Django 小火箭了。

和上一章相似,第一次启动容器时可能会出现没法链接 MySQL 的错误,这是因为虽然 db 容器已经启动,但初始化并未完成;从新启动容器以后就能够正常工做了。若屡次启动都没法正常工做,那就是别的缘由了,好好检查吧。

本地部署成功,下一步服务器部署。

服务器部署

有了本地部署的经验,服务器部署就很是很是简单了。

仍是相似的,部署前将 Docker 、 Docker-compose 、 Python3 等工具在服务器上安装好;将项目用 Git 克隆到服务器本地。

接下来把 settings.pyconfig/nginx/django_app.confrequirements.txt 相关位置都按教程流程改好;将 docker-compose.ymlDockerfile 复制到服务器。

因为 http 请求默认为 80 端口,因此为了接收公网请求,还须要作一点点修改 docker-compose.yml 的工做:

version: "3"

services:
  app:
    ...
    command: bash -c "... your_project_name.wsgi:application"  # 改成你的项目名称
    ...
  db:
    ...
  nginx:
    ...
    ports:
      - "80:8000"  # 监听 80 端口
    ...
      
networks:
  ...
    
volumes:
  ...
复制代码

修改 Gunicorn 绑定的项目名称,以及让宿主机监听公网 http 默认的 80 端口。

此外还要修改 config/nginx/django_app.conf

upstream your_domain_name {
  ip_hash;
  server app:8000;
}

server {
  ...
  
  location / {
    proxy_pass http://your_domain_name/;
  }
}
复制代码

这个改动主要是为了照顾各类第三方登陆的回调地址(不改这里, GitHub、Weibo 三方登陆都会失败)。若是你没有相似的需求,不改也是能够的。好比博主的我的网站www.dusaiphoto.com,因此这里的 your_domain_name 就修改成 www.dusaiphoto.com

最后,记得将 settings.py 中的 DEBUG 配置修改好:

# DEBUG=True 注释掉
DEBUG=False
复制代码

这样就能够了!构建镜像并启动容器:

docker-compose up
复制代码

在浏览器中就能够正常访问你的网站了。

总结

如今你已经能够部署一个线上的容器化 Django 项目了,恭喜!

若本教程对你有帮助,请到GitHub给个 Star 哟,也欢迎阅读个人Django 搭建博客教程

老朋友们,下个教程见!


相关文章
相关标签/搜索