Home >  > Django部署到nginx(python服务器搭建)

Django部署到nginx(python服务器搭建)

0

环境:

Ubuntu Server 18.04
后来又改为:
Ubuntu Server 16.04

总结:
Python web的部署要注意版本问题,因为import了很多库,有的库只兼容3.5,到3.6就不兼容了。
需要先在postgresql中建立好数据库、用户名、密码,才能执行makemigrations。

一、安装pip3及virtualenv

sudo apt-get install python3-pip
pip3 install virtualenv

这里安装的是pip3,可以下面的命令查看。

pip3 --version

另外,其实pip\pip3这两个命令效果是一样的,没有区别。只是当一台电脑同时有多个版本的Python的时候,用pip3就可以自动区分用Python3来安装库,是为了避免和Python2发生冲突。

不过我最开始无法使用sudo apt-get install python-pip安装pip,出现如下的错误:

sudo apt-get install python-pip
Reading package lists... Done
Building dependency tree
Reading state information... Done
E: Unable to locate package python-pip

经查,可能用以下的方法解决。

sudo apt-get install software-properties-common
sudo apt-add-repository universe
sudo apt-get update
sudo apt-get install python-pip

二、创建虚拟环境
在当前用户的文件夹内,一般是/home/user/,使用以下命令,同时创建sites文件夹、www.test.com文件夹,存放网站。

June-24-2018 更新:
其实也可以将网站放到var/www/目录下面,在www文件夹下面建立虚拟环境(虚拟环境目录会位于www目录下),然后再新建网站项目。

再执行:

mkdir -p ~/sites/www.test.com

创建一个网站目录。

进入到www.test.com这个文件夹,执行

virtualenv --python=python3.6 env

命令,创建虚拟环境,提示:
Command 'virtualenv' not found, but can be installed with:

sudo apt install virtualenv

执行sudo apt install virtualenv重新安装即可。再执行virtualenv --python=python3.6 env即可。

最后检查一下虚拟环境是否创建成功,运行 ls 命令列出当前目录下的文件和文件夹,看到 env 这个文件夹说明虚拟环境创建成功。

三、激活虚拟环境
首先确保在www.test.com这个文件夹,再执行以下命令。

source env/bin/activate

四、克隆项目
找到项目地址:

在www.test.com目录下面,执行以下命令:

git clone https://github.com/agusmakmun/Django-Blog-Python-Learning.git

克隆完成后,使用ls命令可以看到www.test.com目录下面有env、和Django-Blog-Python-Learning两个文件夹。

五、安装requirements

进入到Django-Blog-Python-Learning文件夹,即requirements.txt文件所在的文件夹。

pip3 install -r requirements.txt

结果出现如下的错误:

Error: pg_config executable not found.

Please add the directory containing pg_config to the PATH or specify the full executable path with the option:

python setup.py build_ext --pg-config /path/to/pg_config build ...

or with the pg_config option in 'setup.cfg'.

Command "python setup.py egg_info" failed with error code 1 in /tmp/pip-install-6xk2hem5/psycopg2/

执行sudo apt install libpq-dev命令,错误信息变成了:

Error: could not determine PostgreSQL version from '10.3'

Command "python setup.py egg_info" failed with error code 1 in /tmp/pip-install-5bcx4e7j/psycopg2/

再执行以下命令:

sudo apt-get install postgresql

还是上面的错误。

没办法,通过vi requirements.txt,将psycopg2==2.6.2修改为2.7.1,然后又出现如下的错误信息:

ValueError: zlib is required unless explicitly disabled using --disable-zlib, aborting

这里发现版本的问题,因为我的python版本是3.6,需要Pillow >= 4.0.0 < 5.0.0才行,所以又将requirements.txt中的Pillow==3.3.1修改为4.1.1,终于安装成功了。

七、测试django
运行python manage.py runserver命令,出现如下错误:

symbol __res_maybe_init version GLIBC_PRIVATE not defined in file libc.so.6 with link time reference

然后进入python,发现使用import psycopg2命令出错,于是使用以下命令重新安装

pip3 uninstall psycopg2
pip3 install --no-binary :all: psycopg2

安装后,使用import psycopg2命令无错。

运行python manage.py runserver命令,又出现以下错误:

ValueError: cannot use LOCALE flag with a str pattern

在网上搜索了一下,应该是Python版本的问题。

That was one of the changes in Python 3.6 regular expressions how the LOCALE flag is handled. For example, your behave version should work on Python 3.5.2.

七、更改ubuntu版本

没办法,到了这里陷入死局,只得改用ubuntu 16.4。

一切照前面的操作,安装requirements.txt的时候还是报Error: pg_config executable not found.错误,执行sudo apt install libpq-dev之后终于安装成功了。

然后再安装PostgreSQL,执行python manage.py shell,测试数据库连接是否成功,如果没有出错信息,就表示成功了:

但是执行python manage.py makemigrations的时候,出现错误信息:FATAL: password authentication failed for user "database_user"。

在这里纠结到底要不要先在服务器上的PostgreSQL上先建立数据库和用户名,于是按这里https://www.howtoing.com/fatal-ident-authentication-failed-for-user-postgres/的教程,重新建立了一个数据库与用户名。

$ sudo -u postgres psql
postgres=# password
postgres=# create user "test" with password '123456';
postgres=# create database "myapp_development" owner "testdb";

sudo -u postgres psql是打开客户端工具(psql),sudo -u postgres 是使用postgres 用户登录的意思。

可是还是出现FATAL: password authentication failed for user "test"的出错信息。

然后又通过https://blog.csdn.net/wang1144/article/details/53637990这里的方法,用

find / -name pg_hba.conf

命令找到pg_hba.conf文件(记住,执行这个命令要先使用sudo -i切换到root账户),将最后几行设置为trust,还是不行。

然后又按https://stackoverflow.com/questions/19778510/psql-fatal-password-authentication-failed-for-user的方法。

还是不行,然后因为这里修改了postgres的密码,我再将settings.py中的username、password改为postgres以及新的密码,再次执行python manage.py makemigrations,错误信息又变成了:django.db.utils.OperationalError: FATAL: database "testdb" does not exist

然后进入数据库,通过\du、 \l命令分别查看用户名、数据库

这里又有一个坑,我是看了这篇教程才明白过来的。因为之前不是也作过增加testdb数据库的操作吗?但是上面用\l根本查不到这个数据库,我又试着用create database testdb新建一次,用\l命令还是查不到。

原来初次安装后,默认生成一个名为postgres的数据库和一个名为postgres的数据库用户。这里需要注意的是,同时还生成了一个名为postgres的Linux系统用户。首先要切换到postgres这个linux用户,来生成其他用户和新数据库才行。我在网上查找了一大堆教程,走了好多弯路,都没有将这个问题说明白。

第一种方法,使用PostgreSQL控制台。

首先,新建一个Linux新用户,可以取你想要的名字,这里为dbuser。

sudo adduser dbuser
然后,切换到postgres用户。

sudo su - postgres
下一步,使用psql命令登录PostgreSQL控制台。

psql
这时相当于系统用户postgres以同名数据库用户的身份,登录数据库,这是不用输入密码的。如果一切正常,系统提示符会变为"postgres=#",表示这时已经进入了数据库控制台。以下的命令都在控制台内完成。

第一件事是使用password命令,为postgres用户设置一个密码。

password postgres
第二件事是创建数据库用户dbuser(刚才创建的是Linux系统用户),并设置密码。

CREATE USER dbuser WITH PASSWORD ';password';;
第三件事是创建用户数据库,这里为exampledb,并指定所有者为dbuser。

CREATE DATABASE exampledb OWNER dbuser;
第四件事是将exampledb数据库的所有权限都赋予dbuser,否则dbuser只能登录控制台,没有任何数据库操作权限。

GRANT ALL PRIVILEGES ON DATABASE exampledb to dbuser;
最后,使用q命令退出控制台(也可以直接按ctrl+D)。

q

然后再执行python manage.py makemigrations,就成功了。

再执行python manage.py migrate,显示所有东西都OK,再执行python manage.py runserver。

还是无法访问,再将runserver命令换成:python manage.py runserver 0.0.0.0:8000,再在浏览器中输入http://192.168.0.4:8000/,终于看到django的页面了。

这里又有一个坑,就是我的sucureCRT连接太久,自动断掉了,但是python manage.py runserver还在运行,下次连接上去的时候,无法终止这个服务,解决方法是:

sudo netstat -tulpn | grep :8000
kill -9 2197

也有人说可以使用pkill -f "manage.py runserver"命令。

八、建立后台账号

执行以下命令创建一个django后台账号。

python manage.py createsuperuser 

然后,我们就可以登陆后台了。

九、安装 uwsgi 及 测试 uwsgi

pip3 install uwsgi

使用以上命令安装uwsgi,安装完成之后,使用vi test.py命令创建test.py文件。

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

再执行以下命令启动 uwsgi 服务

uwsgi --http :8000 --wsgi-file test.py

再在浏览器中输入http://192.168.0.4:8000/,可以看到“Hello World”字样,表示配置成功了。

然后执行以下命令,测试django

uwsgi --http :8001 --plugin python --module blogproject.wsgi

出现--- no python application found, check your startup logs for errors ---的错误。

然后,按志强学堂的教程,在项目根目录建立了一个uwsgi.ini文件。

[uwsgi]
socket = /home/kevin168/sites/www.test.com/Django-Blog-Python-Learning.sock
chdir = /home/kevin168/sites/www.test.com/Django-Blog-Python-Learning
wsgi-file = blogproject/wsgi.py
touch-reload = /home/kevin168/sites/www.test.com/Django-Blog-Python-Learning/reload
 
processes = 2
threads = 4
 
chmod-socket = 664
chown-socket = kevin168:www-data
 
vacuum = true

另一种配置:

然后再新建一个空白的 reload 文件,然后执行

sudo uwsgi --ini uwsgi.ini 

出现from django.core.wsgi import get_wsgi_application ImportError: No module named "django"。然后又在网上找到解决方案,说是在wsgi.py里面添加下面的代码:

sys.path.append('/home/kevin168/sites/www.test.com/env/lib/python3.5/site-packages')

问题得到解决,现在执行uwsgi --http :8001 --plugin python --module blogproject.wsgi,没有出错信息,在浏览中输入http://192.168.0.4:8001/,可以看到效果了。

注意:在这一步执行uwsgi命令的时候要进入到项目文件夹里面,不然看不到效果。加上--plugin python是告诉uWSGI在使用python插件,不然很有可能会出错。注意这时项目的静态文件是不会被加载的,需要用nginx做静态文件代理。

总结
在这一步走了很多弯路,其实

uwsgi --http :8001 --plugin python --module blogproject.wsgi

这一步是多余的,只要安装好uwsgi ,配置好uwsgi.ini,然后执行uwsgi --ini uwsgi.ini命令,通过http://192.168.0.4可以访问就可以了。

十、安装Nginx

sudo apt-get install nginx

再使用sudo service nginx start命令,启动Nginx 服务,然后在浏览器中输入虚拟机的IP地址,看到Welcome to nginx!界面,就表示Nginx配置成功了。

新建一个网站配置文件

sudo vim /etc/nginx/sites-available/test.conf

写入以下内容

server {   # 这个server标识我要配置了
        listen 80;  # 80 是http默认的端口, 443 是https默认的端口(网页一般使用这两个端口)
        server_name 192.168.0.4;  # 你访问的路径前面的url名称
        access_log  /var/log/nginx/access.log;  # Nginx日志配置
        error_log  /var/log/nginx/error.log;    # Nginx错误日志配置
        charset  utf-8; # Nginx编码
        gzip on;  # 启用压缩,这个的作用就是给用户一个网页,比如3M压缩后1M这样传输速度就会提高很多
        gzip_types text/plain application/x-javascript text/css text/javascript application/x-httpd-php application/json text/json image/jpeg image/gif image/png application/octet-stream;  # 支持压缩的类型

        error_page  404           /404.html;  # 错误页面
        error_page   500 502 503 504  /50x.html;  # 错误页面

        # 指定项目路径uwsgi
        location / {        # 这个location就和咱们Django的url(r'^admin/', admin.site.urls),
            include uwsgi_params;  # 导入一个Nginx模块他是用来和uWSGI进行通讯的
            uwsgi_connect_timeout 30;  # 设置连接uWSGI超时时间
            # 指定uwsgi的sock文件所有动态请求就会直接丢给他
            uwsgi_pass unix:/home/kevin168/sites/www.test.com/Django-Blgo-Python-Learning.sock;  
        }

        # 指定静态文件路径
        location /static/ {
            alias  /opt/project_teacher/teacher/static/;
            index  index.html index.htm;
        }
        }

激活网站:

sudo ln -s /etc/nginx/sites-available/test.conf /etc/nginx/sites-enabled/test.conf

然后将/etc/nginx/sites-enabled 下面的default删除。

测试配置语法问题

sudo service nginx configtest 或 /path/to/nginx -t

sudo service nginx configtest 或 /path/to/nginx -t

sudo service nginx reload

十一、测试效果
执行以下命令:

sudo uwsgi --ini uwsgi.ini 

然后输入IP地址,就可以看到网站正常显示了。

十二、静态文件
使用http://192.168.0.4/admin/登陆后台的时候,发现后台登陆页面的样式全是乱的,所以肯定静态文件这儿没有弄好。
首先执行“python manage.py collectstatic”登陆,得到如下错误:

You're using the staticfiles app without having set the STATIC_ROOT setting to a filesystem path.

然后我将static_root设成STATIC_ROOT=os.path.join(BASE_DIR, 'static'),又得到了如下的错误:

The STATICFILES_DIRS setting should not contain the STATIC_ROOT setting。

后来看了志强学堂的文章,才知道static_root, staticfiles_dirs的区别是什么,staticfiles_dirs主要是用来放公用的文件的,所以我干脆将STATICFILES_DIRS注释掉了。

STATIC_URL = '/static/'
 
# 当运行 python manage.py collectstatic 的时候
# STATIC_ROOT 文件夹 是用来将所有STATICFILES_DIRS中所有文件夹中的文件,以及各app中static中的文件都复制过来
# 把这些文件放到一起是为了用apache等部署的时候更方便
STATIC_ROOT = os.path.join(BASE_DIR, 'collected_static')
 
# 其它 存放静态文件的文件夹,可以用来存放项目中公用的静态文件,里面不能包含 STATIC_ROOT
# 如果不想用 STATICFILES_DIRS 可以不用,都放在 app 里的 static 中也可以
STATICFILES_DIRS = (
    os.path.join(BASE_DIR, "common_static"),
    '/path/to/others/static/',  # 用不到的时候可以不写这一行
)
 
# 这个是默认设置,Django 默认会在 STATICFILES_DIRS中的文件夹 和 各app下的static文件夹中找文件
# 注意有先后顺序,找到了就不再继续找了
STATICFILES_FINDERS = (
    "django.contrib.staticfiles.finders.FileSystemFinder",
    "django.contrib.staticfiles.finders.AppDirectoriesFinder"
)

蜗牛博客July-03-2018更新:
运行 python manage.py collectstatic这个命令的执行目的,就是将在开发模式中定义的静态目录,统一拿到STATIC_ROOT目录下,在nginx部署时,对外提供“/static”(STATIC_URL)为访问URL:
(1).首先从Django的扩展包中,将admin管理后台的jss 和css等静态文件拷贝到配置文件中的STATIC_ROOT目录下。

(2).然后将STATICFILES_DIRS 列表中所有目录下的内容也拷贝到STATIC_ROOT目录下

最终的配置如下:

经过一晚上的多次尝试,终于弄好了。

附一张图:

视频:https://www.bilibili.com/video/av10247256
https://www.bilibili.com/video/av10244432

暧昧帖

本文暂无标签

发表评论

*

*