Django 服务部署(Nginx+uWSGI)

现有的脚本、工具想找个统一的地方能让开发和其他人员使用,就想弄个网站。调研了下,发现Django不错,虽然都说性能不好,但上手快、敏捷开发,符合我们内部使用需求,就用他了。下面记录我搭建Django服务的过程

一、申请服务器(阿里云、腾讯云等等,略)

注:下面的命令是在linux下的,如果是CentOS的,把相应命令改成yum的命令即可

二、安装和开d发环境一致的python版本

1、安装python3.6

apt-get install software-properties-common 
add-apt-repository ppa:jonathonf/python-3.6 
apt-get update 
apt-get install python3.6

2、创建软连接

cd /usr/bin 

# 如果还需要保留python2的,则下面删除python的软连接不用操作
rm python 
ln -s python3.6 python  
rm python3 
ln -s python3.6 python3

3、安装pip

apt-get install python3-pip 

pip3 install --upgrade pip

如果是CentOS系统,可以参考这篇文章

4、安装虚拟环境(可选)

pip3 install virtualenv

5、创建虚拟环境(可选)

virtualenv mysite_env  #创建虚拟环境

source mysite_env/bin/activate  # 进入虚拟环境
deactivate #退出虚拟环境

若出现找不到virtualenv命令提示,可参考这篇文章

三、安装Git(或其他的代码管理工具)

# 安装Git
apt-get install git

# clone项目代码
git clone XXX项目地址

CentOS系统下编译安装(yum安装的版本过低)可参考这篇文章

四、安装项目依赖包

1、生成、安装依赖包

# 在开发环境生成requirements.txt文件

pip freeze >requirements.txt

# 由于默认的pip freeze命令生成的依赖包是你环境下所有的包,不是跟你项目相关的包也会生成,可能会有很多,所以这里我使用第三方包 pipreqs

pipreqs ./

# pipreqs 会去遍历你项目目录,尽可能的识别你的依赖包,但可能会遗漏,需要你检查下

# 在服务器上安装依赖文件

pip install -r requirements.txt

2、安装依赖包时报错的解决

  • 问题1:安装mysqlclient出现“OSError: mysql_config not found”错误

    解决方法:

apt-get install libmysqlclient-dev python3-dev

# CenOS系统下的命令

yum install mysql-devel gcc gcc-devel python-devel
  • 问题2:matplotlib安装报错

    解决方法见这篇文章

  • 问题3: 提示xadmin-2.0.1找不到,这是因为xadmin针对Django2版本的包是手动安装的(增强的后台管理插件,不需要的可不装)

    解决方法:

# 手动安装
pip install git+git://github.com/sshwsfc/xadmin.git@django2

五、安装配置mysql数据库

1、安装mysql

wget https://dev.mysql.com/get/mysql-apt-config_0.8.10-1_all.deb 

dpkg -i mysql-apt-config_0.8.10-1_all.deb 
apt-get update 
apt-get install mysql-server 

# 然后设置密码

CentOS系统下安装mysql可参考这篇文件(mysql5.6)

2、配置数据库(配置文件一般在/etc/my.cnf 文件里)

[mysqld]
# 设置默认使用的端口
port=3306 
# 允许最大连接数
max_connections=200 
# 允许连接失败的次数。这是为了防止有人试图攻击数据库
max_connect_errors=10 
# 服务端使用的字符集
character-set-server=utf8mb4 
# 数据库字符集对应一些排序等规则使用的字符集
collation-server=utf8mb4_general_ci 
# 创建新表时将使用的默认存储引擎
default-storage-engine=INNODB 
# 默认使用“mysql_native_password”插件作为认证加密方式
# MySQL8.0默认认证加密方式为caching_sha2_password
default_authentication_plugin=mysql_native_password

3、创建用户、创建库

#进入数据库
mysql -u root -p 

# 创建库
CREATE DATABASE mysite_db DEFAULT CHARSET=utf8 DEFAULT COLLATE utf8_unicode_ci

# 创建用户
CREATE USER 'test’@‘localhost’ IDENTIFIED BY ’Test123456@‘;
# 用户授权该表全部权限
GRANT ALL PRIVILEGES ON mysite_db.* TO ’Test123456@‘;
# 刷新入库生效
FLUSH PRIVILEGES;

4、数据库导出导入

# 从开发库里导出
mysqldump -u root -p mysite_db > data.sql

# 把data.sql文件拷到服务器上(可以用工具,也可以用scp命令)
scp data.sql [email protected]:/home/data.sql

# 进入服务器数据库
mysql -u root -p mysite_db

# 导入数据文件
source data.sql;

5、如果不是通过数据库导入方式建表的,那重新创建表即可

python3 manage.py makemigrations
python3 manage.py migrate
python3 manage.py createcachetable  # 缓存表的名称需在setting文件里已设置

六、测试启动

启动测试下,服务是否正常

python3 manage.py runserver 0.0.0.0:80

七、用Nginx+uWSGI部署

1、安装uwsgi(可参考官方文档)

# 安装uwsig
pip3 install uwsgi

2、基础测试
创建一个名为 test.py的文件,vim编辑文件:

def application ( env,start_response ):
    start_response ('200 OK',[('Content-Type','text / html' )])
    return  [ b “Hello World” ]  #python3 

3、测试运行

uwsgi --http:8000 --wsgi-file test.py  
# 说明 --http :8000 使用http协议 端口8000  --wsgi-file test.py 加载指定文件
# 如果出现HelloWorld说明可用

# 如果出现--- no python application found, check your startup logs for errors —错误,说明python版本有多个,而你的uwsgi不是装在默认的那个python里,所以可以在虚拟机里创建一个只有一个python的环境启动,或者在/etc/profile里把python路径改成安装uwsgi的python路径
# 访问不了,还有可能是服务器没有开放8000端口,比如阿里云是默认关闭8000端口的,去开启即可

4、使用uwsgi测试你的项目

# 进入的项目文件夹(与manage.py同一级) 

# 确保项目可以正常工作

python3 manage.py runserver 0.0.0.0:8000

# 如果发现django模块不能导入,则是因为没有添加环境变量,具体命令如下:vim ~/.bash_profile,添加django的路径export PATH=$HOME 在此部分添加,用冒号隔开,具体格式请搜索 $PATH。

# 如果地址不能访问,检查django项目的settings.py设置,把 ALLOWED_HOSTS = [] 改为 ALLOWED_HOSTS = ['*’]

# 如果还是不能访问,查看8000端口是否开放

# 用uwsgi运行项目

uwsgi --http :8000 --chdir /home/mysite --home /home/mysite_env --module mysite.wsgi:application

# 上面具体参数设置可见[官方文档](https://docs.djangoproject.com/en/2.1/howto/deployment/wsgi/uwsgi/#configuring-and-starting-the-uwsgi-server-for-django)

5、安装nginx(CentOS)

# 安装nginx(已装过的可略)

# 下载

wget [http://nginx.org/download/nginx-1.14.1.tar.gz](http://nginx.org/download/nginx-1.14.1.tar.gz)

# 解压

tar -xzvf nginx-1.14.1.tar.gz

# 进入目录

cd nginx-1.14.1/

# 安装依赖

yum install -y pcre pcre-devel

yum install -y openssl openssl-devel

# 创建Nginx的用户组及用户

groupadd nginx

useradd -s /sbin/nologin -M -g nginx nginx

# 编译及安装

./configure --user=nginx --group=nginx --prefix=/usr/local/nginx   --with-http_stub_status_module --with-http_ssl_module

make && make install

# 检查并启动(以下三个命令都要运行)

/usr/local/nginx/sbin/nginx -t   # 测试nginx.conf的配置是否正确  

/usr/local/nginx/sbin/nginx  # 直接启动

/usr/local/nginx/sbin/nginx -s reload  # 重启

/usr/local/nginx/sbin/nginx -c /usr/local/nginx/conf/nginx.conf  # 根据nginx.conf里的配置,启动nginx服务  

# 具体可参考[Linux(CentOS 6.5) 下Nginx 安装,重启和停止](https://blog.csdn.net/greensomnuss/article/details/80986238)

6、配置nginx(CentOS)

# 将/usr/local/nginx/conf目录下的uwsgi_params文件复制到你的项目目录
cp /usr/local/nginx/conf/uwsgi_params /home/mysite/

 
# 创建myconfs文件夹 
mkdir /home/myconfs

 
# 创建一个名为mysite_nginx.conf的文件(可以在任意路径,只要你能找到,这里我把它放在/home/myconfs/)
vim /home/myconfs/mysite_nginx.conf
# 按自己路径写入配置信息(如下)

具体配置(可见nginx文档)

upstream django {
    # server unix:///path/to/your/mysite/mysite.sock; # for a file socket
    server 127.0.0.1:8001; # for a web port socket (we'll use this first)
}

# configuration of the server
server {
    # 你的网站监听的端口,此处先用8000端口测试,正式部署可以改为80或其他
    listen      8000;
    # 你的网站的域名
    server_name *.com; # substitute your machine's IP address or FQDN
    charset     utf-8;

    # max upload size
    client_max_body_size 75M;   # adjust to taste

    # Django media
    location /media  {
        alias /home/mysite/media;  # 你的media的文件目录
    }

    location /static {
        alias /home/mysite/collected_static; # 你的项目收集的静态文件目录(后边会将收集静态文件)
    }

    # Finally, send all non-media requests to the Django server.
    location / {
        uwsgi_pass  django;
        include     /home/mysite/uwsgi_params; # uwsgi_params 文件所在目录
    }
}

# 这个配置文件告诉nginx提供来自文件系统的媒体和静态文件,以及处理那些需要Django干预的请求。对于一个大型部署,让一台服务器处理静态/媒体文件,让另一台处理Django应用,被认为是一种很好的做法,但是现在,这样就好了。

让nginx的根文件载入你的mysite_nginx.conf配置的信息:
vim /usr/local/nginx/conf/nginx.conf


Django 服务部署(Nginx+uWSGI)_第1张图片

7、部署静态文件

# 在运行nginx之前,你必须收集所有的Django静态文件到静态文件夹里
# 编辑项目的settings   
vim /home/mysite/mysite/settings.py
#添加 
STATIC_ROOT = os.path.join(BASE_DIR, "collected_static/")

 
# 然后运行(如果之前用虚拟环境的,记得进入虚拟环境再操作) 
python3 manage.py collectstatic

8、基本的nginx测试

# 启动nginx

/usr/local/nginx/sbin/./nginx

# 如果已经启动,则重启

/usr/local/nginx/sbin/./nginx -s reload

# 要检查是否正确的提供了媒体文件服务,上传一张图片(这里我上传的文件为 1.jpg)到 /home/sysite/media文件夹中

# 然后访问[http://example.com:8000/media/1.jpg](http://example.com:8000/media/1.jpg) - 如果这能正常工作,那么至少你知道nginx正在正确的提供文件服务。

# 最好将你的nginx先停止, 再开启,而不是重载

9、配置uwsgi,创建ini文件方便处理。ini参考如下
创建一个名为mysite_uwsgi.ini的文件

[uwsgi] 
chdir = /home/mysite  # 你的项目目录
home = /home/mysite_env # 如果有虚拟环境,则需要指定虚拟环境目录; 没有则注释掉
module = mysite.wsgi:application  # 指向自己Django项目目录下mysite目录下的wsgi文件
master = True 
processes = 4  # 使用进程数
harakiri = 60  # 最大超时时间
max-requests = 5000  # 最大请求数,到了后就会自动重启
socket = 127.0.0.1:8001  # socket连接地址和端口,和之前nginx配置一致
pidfile = /home/mysite_uwsgi/master.pid  # 在失去权限前,将pid写到指定的pidfile文件中
daemonize = /home/mysite_uwsgi/mysite.log # 使进程在后台运行,并将日志打到指定的日志文件或者udp服务器
# chmod-socket    = 664  # 如果没有权限访问uWSGI的socket,这里可以设置权限
vacuum = True  # 服务退出或重启,自动删除pid和socket文件

10、运行uWSGI

uwsgi -d --ini mysite_uwsgi.ini
# 参数 -d 为后台运行。此时你的django项目已经部署成功。
# 注意,必须nginx也要启动才能正常访问

11 、官方参考地址

nginx测试命令:nginx -t
查看uwsgi进程:ps -aux | grep uwsgi 
正常关闭uwsgi进程:uwsgi --stop /home/mysite_uwsgi/master.pid 
强制关闭全部uwsgi进程:ps -aux | grep uwsgi |awk '{print $2}'|xargs kill -9 
重新加载uwsgi:uwsgi --reload /home/mysite_uwsgi/master.pid 

参考文档: 
(Django官网)https://docs.djangoproject.com/en/2.1/howto/deployment/wsgi/uwsgi/ 
(uwsgi中文)https://uwsgi-docs-zh.readthedocs.io/zh_CN/latest/tutorials/Django_and_nginx.html 
(uwsgi英文)https://uwsgi.readthedocs.io/en/latest/tutorials/Django_and_nginx.html 
(自强学堂)https://code.ziqiangxuetang.com/django/django-nginx-deploy.html 

八、使用Nginx+Gunicorn部署(其他方案)

可参考:Centos上Python应用部署详情(Nginx 和 Gunicorn 部署 Django项目)

九、配置清单(发布环境配置修改)

1、开发环境和生产环境配置分开
把原先的settings.py改名为settings_base.py,创建settings_development.py和settings_production.py文件。把基础共用的配置保留在base文件里,在development文件里只保留Degbu、DATABASES等其他需单独配置的设置,在production文件里同样,development和production继承base文件。注意配置不要重复

Django 服务部署(Nginx+uWSGI)_第2张图片

如果settings文件需要另起一个文件夹存放,比如放在mysite/settings下,那记得修改settings_base.py里的BASE_DIR设置

同时修改manage.py文件里的配置路径(开发环境):
修改wsgi.py文件里的配置路径(生产环境):

2、修改生产环境的配置:秘钥不明文显示

  • 修改Debug为False
  • 重新生成SECRET_KEY秘钥,并设置从环境变量里读取的方式获取(不在配置文件里明文显示)
  • 数据库密码也一样,从环境变量里读取的方式获取(不在配置文件里明文显示)
  • 邮箱的授权码也一样设置
# 重新生成秘钥方法
from django.core.management import utils
utils.get_random_secret_key()  # 该方法可以生成秘钥

# linux里设置环境变量
vim /etc/profile 
# 在文件最后面加上配置(如下图)
# 然后生效
source /etc/profile

3、修改生产环境的配置:增加日志文件配置(官方文档说明)
在settings_production.py文件最后增加日志配置

# 日志配置,若需要其他设置,可参考官方文档
LOGGING = {
    'version': 1,
    'disable_existing_loggers': False,
    'handlers': {
        'file': {
            'level': 'DEBUG',
            'class': 'logging.FileHandler',
            'filename': ‘/home/mysite_debug.log',
        },
    },
    'loggers': {
        'django': {
            'handlers': ['file'],
            'level': 'DEBUG',
            'propagate': True,
        },
    },
}

在服务器上创建并修改mysite_debug.log文件的权限

chmod 666 mysite_debug.log

4、修改生产环境的配置:更改邮件设置的端口和认证方式
有些云服务器对25端口有严格的限制,所以我们把端口和认证方式改成SSL的:

# 端口改成465,记得在服务器上把465端口开放
EMAIL_PORT = 465
# EMAIL_USE_TLS 改成 EMAIL_USE_SSL
EMAIL_USE_SSL = True

5、增加404、500错误页面
把404.html和500.html等文件放到templates根目录下即可

6、增加favicon.ico图标(浏览器图标)

  • 第一种方法(这种方法可行):
    把favicon.ico图标放到项目misite目录下(目录可以自定),然后同步到GITHUB,服务器pull同步数据
    编辑nginx配置文件(vim /home/myconfs/mysite_nginx.conf):
location /favicon.ico  {
        # 你的favicon.ico文件path
        alias /home/mysite/mysite/favicon.ico;
    }
  • 第二种方法(这个方法我在开发环境可以,部署到生产环境还是不行):
    把favicon.ico文件放到根目录的static目录下,然后修改urls.py,如下
from django.contrib.staticfiles.views import serve

urlpatterns = [
 ...
 path('favicon.ico', serve, {'path': 'favicon.ico'}),
]
  • 第三种方法(这种方法可以用,但admin管理界面里默认是没有这个文件的)
# 修改base.html文件,在head里增加读取favicon.ico

7、设置上传文件目录的权限

# 修改media目录的权限
chmod 777 media/

8、重新汇聚静态文件

python3 manage.py collectstatic

9、重启nginx和uwsgi测试

十、正常运行后发现的问题记录和处理

1、django-ckeditor插件里上传图片是报server 500错误
解决方法:网上有说把media文件夹权限改成777,但我不行,我把/usr/local/nginx/conf/nginx.conf配置文件里第一行原值#user nobody; 修改为 user root;并保存。使用 /usr/local/nginx/sbin/nginx -s reload 命令重新加载配置文件即可。


但我不想用root,但试了改成nginx用户等都不行,暂时没有找到其他办法。
2、我们在页面编辑的时候,总是要写代码的,但现在的django-ckeditor插件还没有设置插入代码的功能
解决方法:在settings设置里,修改CKEDITOR_CONFIGS的设置:

CKEDITOR_CONFIGS = {
    'default': {
        'width': 'auto',
        'toolbar': (
            ['div', 'Source', '-', 'Preview'],
            ['Copy', 'Cut', 'Paste', 'PasteText', 'PasteFromWord',],
            ['Undo', 'Redo', '-', 'Find', 'Replace', '-', 'SelectAll', 'RemoveFormat'],
            ['Bold', 'Italic', 'Underline', 'Strike', '-', 'Subscript', 'Superscript'],
            ['NumberedList', 'BulletedList', '-', 'Outdent', 'Indent', 'Blockquote'],
            ['JustifyLeft', 'JustifyCenter', 'JustifyRight', 'JustifyBlock'],
            ['Link', 'Unlink', 'Anchor'],
            ['Image', 'Flash', 'Table', 'HorizontalRule', 'Smiley', 'SpecialChar', 'PageBreak'],
            ['Styles', 'Format', 'Font', 'FontSize'],
            ['TextColor', 'BGColor'],
            ['Maximize', 'ShowBlocks', '-', 'About'],
            ['CodeSnippet', '-', 'Print'],
        ),

        # 插件
        'extraPlugins': ','.join(['codesnippet', 'prism', 'widget', 'lineutils', ]),
    },
}

# 其中插件codesnippet既是代码编辑功能,记得在toolbar里加上'CodeSnippet’按钮
# prism为代码高亮插件

3、加了codesnippet后,可以编辑代码了,但当非编辑状态下看的时候,发现代码没有高亮显示,不美观
解决方法:增加prism插件(详细步骤可见这篇文章).

  • 从ckeditor官网下载 插件prism(点这里直接下载),然后将其解压到ckeditor/static/ckeditor/ckeditor/plugins路径下,同样的我们需要在CKEDITOR_CONFIGS里将extraPlugins对应的value里加入插件 'prism' 和另外两个插件"lineutils"、"widget" ,这两个插件无须下载,在django-ckeditor中已经有了.

  • 去prismjs官网下载css文件http://prismjs.com/download.html,选择你喜欢的主题,勾选支持的语言,以及别忘选择line-numbers功能,下载后把他解压到自己项目的static/下

  • 然后在模板中引用静态文件即可

你可能感兴趣的:(Django 服务部署(Nginx+uWSGI))