上一章我们给Docker添加了一个MySQL数据库。但是,使用的开发服务器虽然使用方便,但是性能较差,可靠性低,无法用于生产环境。因此本章将实现Docker+Django+MySQL+Nginx+Gunicorn容器项目来完成最终的服务器部署。直接进入本章的初学者,建议回到教程第一章开始阅读,否则有些内容会不太容易看懂。对Django项目部署没有概念的读者也可以先看我的博文:将Django项目部署到服务器。在将Docker-compose部署到服务器之前,我们先尝试在本地部署一下。在上一篇的基础上,继续修改docker-compose.yml配置:version:"3"services:app:restart:alwaysbuild:.命令:bash-c"p??ython3manage.pycollectstatic--no-input&&python3manage.pymigrate&&gunicorn--timeout=30--workers=4--bind:8000django_app.wsgi:application"卷:-.:/code-static-volume:/code/collected_staticexpose:-"8000"depends_on:-dbnetworks:-web_network-db_networkdb:image:mysql:5.7volumes:-"./mysql:/var/lib/mysql"端口:-“3306:3306”重新启动:始终环境:-MYSQL_ROOT_PASSWORD=mypassword-MYSQL_DATABASE=django_app网络:-db_networknginx:重新启动:始终图像:nginx:最新端口:-“8000:8000”卷:-静态卷:/code/collected_static-./config/nginx:/etc/nginx/conf.ddepends_on:-appnetworks:-web_networknetworks:web_network:driver:bridgedb_network:driver:bridgevolumes:static-volume:看大体思路有点复杂:定义了3个容器,分别是app、db和nginx。容器通过定义的端口进行通信。定义了两个网络,即web_network和db_network。只有同一网络上的容器才能相互通信。不同的网络是隔离的,即使使用同一个端口也不能互通。定义了1个数据卷,静态卷。数据量对于共享相同数据的多个容器来说非常有用,你可以看到应用程序和nginx都在使用它。expose和ports都可以暴露容器的端口,不同的是expose只暴露给其他容器,而ports暴露给其他容器和主机。这样可能还是比较难理解,我们继续分解。NetworknetworkDocker允许用户为每个容器定义工作网络,通信只能在同一个网络中进行。可以看到nginx容器在web_network网络中,db容器在db_network网络中,所以两者不能通信,实际上也不需要通信。app容器同时处于web_network和db_network网络中,相当于连接三个容器的桥梁。定义网络可以隔离容器的网络环境,也方便运维人员对网络的逻辑关系一目了然。我们之前看到的数据卷是用来映射宿主机和容器目录的,其实就是挂载;现在新的静态卷称为卷。它是这样使用的:static-volume:/code/collected_static,冒号之后仍然是容器中的一个目录,但是冒号之前不是宿主目录,只是卷的名称。本质上,数据卷也实现了宿主机与容器的目录映射,只不过数据卷是由Docker管理的,你甚至不需要知道数据卷在宿主机上的具体存放位置。与挂载相比,数据卷的优势在于由Docker统一管理,不存在权限不足导致的挂载问题,也无需在不同的服务器上指定不同的路径;缺点是不适合单一的配置文件映射。和挂载一样,数据卷的生命周期与容器分离,容器删除后卷仍然存在。下次构建镜像时,指定卷的名称可以继续使用。既然Docker可以管理卷,那么删除卷就非常容易了。说明,我不告诉你,生产环境肯定不便宜。定期备份数据是一个好习惯。数据卷有一个很重要的特性:如果启动时该卷为空,则容器映射目录的所有内容都会被复制到该卷中。也就是说,只要初始化volume,容器原来的collected_static目录就不会再被使用,新添加的文件只存在于volume中,不存在于容器中。实际上静态静态文件(和媒体媒体文件)的持久化存储可以通过挂载或者数据卷来实现;每个人都可以选择使用哪一个。篇幅有限,教程不讲media媒体文件,但它的设置和static完全一样。其他配置首先修改Nginx配置文件,映射到nginx容器的config/nginx/django_app.conf:upstreamapp{ip_hash;服务器应用程序:8000;}服务器{听8000;服务器名称本地主机;位置/static/{autoindexon;别名/code/collected_static/;}location/{proxy_passhttp://app/;}}这种配置下,Nginx会监听容器的8000端口,并将接收到的请求发送给应用容器(静态文件请求除外)。在requirements.txt文件中添加gunicorn库:django==2.2mysqlclient==1.3.14gunicorn==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-composeupbrowseraccess127.0.0.1:8000又看到熟悉的Djangorocket了。和上一章类似,第一次启动容器的时候可能会出现无法连接MySQL的错误。这是因为db容器虽然已经启动,但是还没有完成初始化;重启容器后即可正常工作。如果多次启动后还是不行,那就是其他原因,检查一下。本地部署成功,接下来就是服务器部署了。服务器部署有本地部署经验,服务器部署非常非常简单。还是类似的,部署前先在服务器上安装Docker、Docker-compose、Python3等工具;使用Git将项目克隆到本地服务器。接下来按照教程流程更改settings.py、config/nginx/django_app.conf、requirements.txt的相关位置;将docker-compose.yml和Dockerfile复制到服务器。由于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绑定的项目名称,让host默认监听公网http的80端口。另外需要修改config/nginx/django_app.conf:upstreamyour_domain_name{ip_hash;服务器app:8000;}服务器{...位置/{proxy_passhttp://your_domain_name/;}}这个改动主要是为了照顾各种first三方登录的回调地址(如果不改这个,GitHub和微博三方登录会失败)。如果没有类似的需求,可以不用管它。比如博主的个人网站是www.dusaiphoto.com,那么这里的your_domain_name就改成www.dusaiphoto.com。最后记得修改settings.py中的DEBUG配置:#DEBUG=True注释掉DEBUG=False就大功告成了!构建镜像并启动容器:docker-composeup可以在浏览器中正常访问你的网站。总结现在你可以在线部署一个容器化的Django项目了,恭喜!如果这篇教程对你有帮助,请在GitHub上给个Star,也欢迎阅读我的Django搭建博客教程。老朋友们,下期教程见!如有任何问题,请在杜赛个人网站留言,我会尽快回复。教程示例代码:django-docker-tutorial或给我发邮件:dusaiphoto@foxmail.com
