Docker部署Django+Mysql+Redis+Gunicorn+Nginx的实现
一.前言
docker技术现在非常火热,通过容器构建项目环境,运行效率和部署效率都很不错。所以最近抽空看了一些教程,然后将博客部署方式改为了docker,感觉网上没有特别好的关于docker部署django项目的教程,特意写了这篇文章,算是记录自己的心得。
本次教程的测试环境为Deepin,主要侧重于容器的编排和Django相关部署知识,一些细节方面,例如环境依赖安装,不会讲得特别详细。由于是在本地测试,所以在配置nginx相关信息时,将配置http代理而非https代理。
二.环境依赖
部署方式选择了docker加docker-compose,因此需要安装docker和docker-compose。
- docker可以通过sudoaptinstalldocker-ce命令安装。
- docker-compose可通过以下命令安装。
sudocurl-Lhttps://get.daocloud.io/docker/compose/releases/download/1.22.0/docker-compose-`uname-s`-`uname-m`>/usr/local/bin/docker-compose sudochmod+x/usr/local/bin/docker-compose
安装完成以后,输入dockerversion,看到以下画面表示docker安装成功。
输入docker-composeversion,看到以下画面表示docker-compose安装成功。
博客项目中使用到了Django,Mysql,Redis,Nginx,因此需要四个容器,每个容器对应一个应用,当然这些容器是有先后顺序的,也就是说存在依赖关系。然后通过docker-compose编排这四个容器,构建容器运行环境。
总共四个容器:
- Redis容器:缓存服务
- Mysql容器:数据存储
- Django(Gunicorn)容器:处理动态请求
- Nginx容器:反向代理,处理静态资源
下面是容器的结构图。
容器依赖关系:Django容器依赖Redis容器和Mysql容器,Nginx容器依赖Gunicorn容器。
四.项目结构
看这个教程的小伙伴请尽量把目录和教程中目录保持一致,否则在后续部署过程中极有可能会出错。
my_blog是django项目目录,deployment文件夹放置了除Django容器外的三个容器配置信息。
Dockerfile:docker环境文件
docker-compose.yml:编排容器文件
start.sh:容器初始化后执行的shell命令脚本
requirements.txt:django项目环境依赖文件
gunicorn.conf:gunicorn配置文件
deployment目录包含mysql容器配置信息,nginx容器配置信息和redis容器数据目录。
mysql:放置数据库配置信息,conf放置数据库初始化配置文件my.cnf,data用于挂载数据库数据,init放置sql脚本(导入表结构和数据,并挂载到容器中)。
nginx:放置nginx配置信息,ssl放置ssl证书
redis:挂载redis数据
容器环境和本机环境是隔离的,你可以把容器当做另一个系统,起初这个系统与你本机的系统并无关联,我们通过编写Dockerfile文件配置并构建容器环境(像在干净的系统中配置python环境一样)。
#建立python3.6环境 FROMdaocloud.io/python:3.6 #镜像作者 MAINTAINERzyk2295098032@qq.com #设置python环境变量 ENVPYTHONUNBUFFERED1 #创建my_blog文件夹 RUNmkdir/my_blog #将my_blog文件夹为工作目录 WORKDIR/my_blog #将当前目录加入到工作目录中(.表示当前目录) ADD./my_blog #利用pip安装依赖(-i表示指定清华源,默认源下载过慢) RUNpip3install-rrequirements.txt-ihttps://pypi.tuna.tsinghua.edu.cn/simple/ #设置环境变量 ENVSPIDER=/my_blog
2.编写gunicorn配置文件
编写gunicorn.conf文件,用于gunicorn的启动
workers=3#并行工作进程数 threads=2#指定每个工作者的线程数 bind=['0.0.0.0:8000']#监听内网端口8000 proc_name='my_blog'#进程名称 pidfile='/tmp/blog.pid'#设置进程文件目录 worker_class='gevent'#工作模式协程 timeout=30#超时 max_requests=6000#最大请求数
3.编写start.sh命令脚本
start.sh脚本用于启动django容器
#!/bin/bash #从第一行到最后一行分别表示: #1.守护进程执行celery,没有这个需求的小伙伴可以将第一行命令其删除 #2.收集静态文件到根目录, #3.生成数据库可执行文件, #4.根据数据库可执行文件来修改数据库 #5.用gunicorn启动django服务 celerymultistartw1-Acelery_tasks.tasksworker-linfo&& pythonmanage.pycollectstatic--noinput&& pythonmanage.pymakemigrations&& pythonmanage.pymigrate&& gunicornmy_blog.wsgi:application-cgunicorn.conf
六.构建nginx容器环境
1.nginx容器Dockefile编写
创建并编写nginx文件夹下的Dockerfile
#nginx镜像 FROMdaocloud.io/nginx #删除原有配置文件,创建静态资源文件夹和ssl证书保存文件夹 RUNrm/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./nginx.conf/etc/nginx/conf.d/
2.配置nginx.conf
nginx.conf用于反向代理域名或者ip,将动态请求分发至内部的django容器的8000端口,并配置静态资源路径。
配置反向代理时,注意host一定要改为web,web即是django容器的名称(在docker-compose.yml中配置)
#仅用于本地docker环境测试(80端口代理http请求) server{ listen80;#监听80端口 server_name127.0.0.1;#生产环境请换成域名 location/{ proxy_passhttp://web:8000;#反向代理django容器8000端口,web为django容器名称,切记不要写域名或者ip proxy_set_headerHost$host; proxy_redirectoff; proxy_set_headerX-Forwarded-For$proxy_add_x_forwarded_for; } location/static/{ alias/usr/share/nginx/html/static/;#静态资源路径 } location/media/{ alias/usr/share/nginx/html/media/;#上传文件路径 } }
七.配置mysql
1.编写my.cnf文件
my.cnf文件用于初始化mysql配置,这个文件将被挂载到容器中。
[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.导入初始化sql文件(不需要导入初始数据库的小伙伴可以忽略此步骤)
将需要导入的sql文件放入init目录下,并修改其名称为init.sql
八.利用docker-compose编排容器
编写docker-compose.yml
version:"3" services: redis: image:daocloud.io/redis:3 command:redis-server volumes: -./deployment/redis:/data ports: -"6379:6379" restart:always#always表容器运行发生错误时一直重启 db: image:daocloud.io/mysql:5.7 environment: -MYSQL_DATABASE=my_blog#数据库名称 -MYSQL_ROOT_PASSWORD=19960331#数据库密码 volumes: -./deployment/mysql/data:/var/lib/mysql#挂载数据库数据 -./deployment/mysql/conf/my.cnf:/etc/mysql/my.cnf#挂载配置文件 -./deployment/mysql/init:/docker-entrypoint-initdb.d/#挂载数据初始化sql脚本 ports: -"3306:3306" restart:always web: build:. expose: -"8000" volumes: -.:/my_blog -/tmp/logs:/tmp command:bashstart.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#挂载静态文件 -./media:/usr/share/nginx/html/media#挂载上传文件 -./deployment/nginx/ssl:/usr/share/nginx/ssl#挂载ssl证书目录 links: -web depends_on: -web restart:always
redis,db,web,nginx为容器名称。
image表示拉取镜像名称,build会在给定目录下寻找Dockerfile并构建容器环境。
expose表示将端口暴露给其他容器,但不暴露给主机(不同容器默认相互隔离)。
ports表示将该容器端口映射到主机端口(从右往左读,例如ports:-"3307:3306",是指把容器的3306端口映射到主机的3307端口),同时该容器端口也会对其他容器开放。
volumes表示挂载,就是将本机的文件和容器中的文件映射起来,容器和本地环境本来是隔离的,挂载相当于是凿了一个小洞,让两者数据可以互通。
links表示将容器互联起来。
depends_on:表示依赖关系,因为容器的启动有先后顺序,django容器依赖于mysql容器和redis容器(django需要从数据库和缓存中读写数据),而nginx依赖于django容器(nginx容器需要反向代理django容器的8000端口)
九.构建、运行容器
在构建运行容器之前,需要修改django项目的settings.py文件。
将数据库连接HOST改为mysql容器名称db
DATABASES={ 'default':{ 'ENGINE':'django.db.backends.mysql',#mysql驱动 'NAME':'my_blog',#数据库名称 'USER':'root',#登录帐号 'PASSWORD':'19960331',#登录密码 'HOST':'db',#主机地址(容器部署) #'HOST':'127.0.0.1',#主机地址 'PORT':'3306',#端口 'OPTIONS':{'charset':'utf8mb4'}, } }
将缓存配置中的host改为redis容器名称redis(如果你配置了redis作为缓存的话,没配置的话请忽略)
CACHES={ 'default':{ 'BACKEND':'django_redis.cache.RedisCache', 'LOCATION':'redis://redis:6379',#redis(容器) #'LOCATION':'127.0.0.1:6379', 'OPTIONS':{ "CLIENT_CLASS":"django_redis.client.DefaultClient", "CONNECTION_POOL_KWARGS":{"max_connections":100}, 'SOCKET_TIMEOUT':10, }, }, }
生产环境部署请将settings.py中的DEBUG=True改为DEBUG=False以关闭debug模式。
最后在项目根目录执行命令docker-composeup--build。
执行完毕以后看到以下画面表明构建成功。
在浏览器端口访问127.0.0.1或者你的公网ip,若能成功访问表明构建成功。
我也是第一次用docker-compose来部署django项目,若有写得不得当或者有误的地方麻烦大家帮忙指出。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。
声明:本文内容来源于网络,版权归原作者所有,内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:czq8825#qq.com(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。