利用uWSGI和Nginx部署Django

9 篇文章 0 订阅
5 篇文章 0 订阅

主要内容来自于

Setting up Django and your web server with uWSGI and nginx — uWSGI 2.0 documentation

系统情况:

Ubuntu 14.04.2 LTS (实际是麒麟版)

python3 version 3.5.2(源上直接apt-get)

pip3 version 8.1.1(源上直接apt-get)

若无特殊指代,localhost即为127.0.0.1

虽说本文类别定为“翻译”,但是并没有将上述链接所代表的网页直接翻译,而是取得其中的关键步骤,另加自己的细节调整。

=== Update on 20240317. ===

- 在Ubuntu 22.04上进行了测试,仍然可行。

- 修改emperor启动方式,从rc.local变为系统service。

=== End of update on 20240317. ===

安装virtualenv并激活

安装virtualenv

我对virtualenv的理解非常浅,目前就理解为一种处理python多版本问题的“沙盒”解决方案,把想使用的python版本和对应的工具放到一个位置,不必担心系统层面的冲突。

实际安装时,使用

sudo pip3 install virtualenv

激活virtualenv

我目前理解激活(activate)virtualenv指创建一个virutalenv环境。由于我将使用python3,而在Ubuntu14中,系统的默认的python是2.7,那么在激活前的创建过程中需要指定所使用的python。在创建的同时需要指定一个virtualenv名称,virtualenv会创建相应的文件夹。实际创建virtualenv时使用如下命令

virtualenv -p /usr/bin/python3 uwsgi-tutorial

uwsgi-tutorial即指的是virtualenv名称,是沿用原网页上的描述。上述命令是我搜索得到的,原网页位置为stackoverflow。命令执行之后,会在当前文件夹下生成uwsgi-tutorial文件夹,进入该文件夹,那么我们现在所在位置为

/home/yaoyu/MySites/uwsgi-tutorial

其中yaoyu是我的用户名,MySites是我用来存放网站文件的位置(我就都不遮盖了。。)

此时,运行脚本bin/activate(该脚本位于/home/yaoyu/MySites/uwsgi-tutorial/bin)以激活该virtualenv

source bin/activate

pip install ipython

hash -r

成功激活后,终端的prompt会在最前面加上当前virtualenv的描述。上述第三条命令是令virtualenv重建对ipython的索引。参考这里

在virtualenv中安装Django

安装Django,并创建一个示例project。

pip install Django

django-admin.py startproject mysite

cd mysite

mysite即为Django的project名,并且也是文件夹名(当然mysite下面还有一个mysite)。此时,我们的位置变为

/home/yaoyu/MySites/uwsgi-tutorial/mysite

=== 20240317. ===

如后面遇到502 Bad Gateway 且无法通过修改文件夹权限解决时,可能需要讲mysite文件夹的所有parent 文件夹的权限设置成可写可执行。所以可将mysite移动到根目录,并配置好权限。给与www-data 用户组写和执行的权限。

=== End of 20240317. ===

可以现在立即测试Django project的可用性,并同时测一下端口的可用性。

python manage.py runserver 0:8000

若正常启动,则通过浏览器访问localhost:8000应能看到Django的信息。此时使用的是Django自带的development server,终端中用Ctrl+C终止Django的development server的运行。

在virtualenv中安装uWSGI

安装uWSGI(在CenOS中可能需要先安装python3x-devel,3x代表版本号)

pip install uWSGI

为了简单测试uWSGI,编写test.py文件。当前我们仍位于

/home/yaoyu/MySites/uwsgi-tutorial/mysite

新建的test.py文件内容为

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

测试uWSGI的有效性

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

此时若正常启动uwsgi,那么通过浏览器访问localhost:8000即可看到Hello Word字样。Ctrl+C 终止uwsgi。

之后可测试uWSGI与刚刚建立的Django project的数据交换。

uwsgi --http :8000 --module mysite.wsgi

我们当前仍在/home/yaoyu/MySites/uwsgi-tutorial/mysite,module wsgi即保存在

/home/yaoyu/MySites/uwsgi-tutorial/mysite/mysite/wsgi.py

此时利用浏览器访问localhost:8000应当可以看到Django的信息。


安装并配置nginx

从源上直接安装nginx。

sudo apt-get install nginx

安装完毕后,启动nginx。

sudo /etc/init.d/nginx start

此时,使用浏览器访问localhost:80(注意端口,也可以不带端口),应当可以看见nginx的欢迎信息。

为了与uWSGI连接,需要一个uwsgi_params文件和一个nginx的conf文件。uwsgi_params文件可以从如下地址获取。

https://github.com/nginx/nginx/blob/master/conf/uwsgi_params

其内容为

uwsgi_param  QUERY_STRING       $query_string;
uwsgi_param  REQUEST_METHOD     $request_method;
uwsgi_param  CONTENT_TYPE       $content_type;
uwsgi_param  CONTENT_LENGTH     $content_length;

uwsgi_param  REQUEST_URI        $request_uri;
uwsgi_param  PATH_INFO          $document_uri;
uwsgi_param  DOCUMENT_ROOT      $document_root;
uwsgi_param  SERVER_PROTOCOL    $server_protocol;
uwsgi_param  REQUEST_SCHEME     $scheme;
uwsgi_param  HTTPS              $https if_not_empty;

uwsgi_param  REMOTE_ADDR        $remote_addr;
uwsgi_param  REMOTE_PORT        $remote_port;
uwsgi_param  SERVER_PORT        $server_port;
uwsgi_param  SERVER_NAME        $server_name;

将该uwsgi_params文件复制到Django project的文件夹,即

/home/yaoyu/MySites/uwsgi-tutorial/mysite

并在同样位置创建mysite_nginx.conf文件,内容为

# mysite_nginx.conf

# the upstream component nginx needs to connect to
upstream django {
    # server unix:///home/yaoyu/MySites/uwsgi_tutorial/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 {
    # the port your site will be served on
    listen      8000;
    # the domain name it will serve for
    server_name .example.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/yaoyu/MySites/uwsgi-tutorial/mysite/media;  # your Django project's media files - amend as required
    }

    location /static {
        alias /home/yaoyu/MySites/uwsgi-tutorial/mysite/static; # your Django project's static files - amend as required
    }

    # Finally, send all non-media requests to the Django server.
    location / {
        uwsgi_pass  django;
        include     /home/yaoyu/MySites/uwsgi-tutorial/mysite/uwsgi_params; # the uwsgi_params file you installed
    }
}

mysite_nginx.conf文件的内容包括上游数据源的描述,目前为localhost:8001,nginx监听8000端口向client提供web服务,server的media文件位置以及static文件位置,最后是这个server的根位置。将mysite_nginx.conf以符号连接的形式插入到nginx的默认服务器列表里。

sudo ln -s /home/yaoyu/MySites/uwsgi-tutorial/mysite/mysite_nginx.conf /etc/nginx/sites-enabled/

收集Django project的static文件。修改/home/yaoyu/MySites/uwsgi-tutorial/mysite/mysite/settings.py,添加如下一行

STATIC_ROOT = os.path.join(BASE_DIR, "static/") # Need import os

然后执行

python manage.py collectstatic

将自动生成一个新文件夹static。启动nginx进行测试

sudo /etc/init.d/nginx restart

此时由于没有任何实际server在运行,于是访问localhost:8000是显示Bad Geteway。但是仍可以测试nginx的运行。在

/home/yaoyu/MySites/uwsgi-tutorial/mysite

下新建media文件夹,进入media文件夹,并复制一个png图片进来,然后利用localhost:8000/media/文件名.png的形式通过浏览器查看这个图片,若成功显示图片,代表nginx的配置是正确的。
 

nginx,uWSGI和Django联调

首先通过uwsgi和test.py还有nginx进行联调。在

/home/yaoyu/MySites/uwsgi-tutorial/mysite

运行

uwsgi --socket :8001 --wsgi-file test.py

此时通过浏览器访问localhost:8000,此时应有Hello world字样。uwsgi通过localhost的8001端口向nginx提供数据,nginx再通过localhost的8000端口向浏览器提供数据。用Ctrl+C退出uwsgi。

现在利用Unix socket代替TCP端口。上面的测试使用的是8001端口,通过修改mysite_nginx.conf中upstream django中的描述(即将原来注释掉的socket描述恢复,而注释8001端口的描述。)再重启nginx服务

sudo /etc/init.d/nginx restart

另外,在Ubuntu系统上,nginx服务是默认已www-data用户和www-data用户组启动的。这里可以将当前用户添加至www-data用户组

sudo usermod -a -G www-data yaoyu

可能需要重新登录。之后可利用group或者id命令查看。

启动uwsgi

uwsgi --socket mysite.sock --wsgi-file test.py --chmod-socket=644 --chown-socket=yaoyu:www-data

=== 20240317. ===

使用775作为权限。

=== End of 20240317. ===

推荐此时再另开一个Terminal,并输出nginx的error log

tail -f /var/log/nginx/error.log

通过浏览器访问localhost:8000,此时若出现Bad Gateway错误,并且nginx的error log提示Permission denied或connection refused。这表示nginx没有对mysite.sock文件的操作权限(仅限Ubuntu系统,对于CentOS或者Fedora可能是与SELinux有关)。处理方案是采用tmpfiles.d,可参考

tmpfiles.d

方案原理是将socket文件放置在一个nginx和uWSGI都有足够权限的位置,比较理想的位置是/run(或者其变种/var/run),在/run下建立一个文件夹位置,并设定该文件夹的权限。具体做法是在/etc/tmpfiles.d下新建一个conf文件,这里我们用mysite-socket.conf命名,其内容为

# Create directory for my sites.

d /run/mysite-socket 0775 www-data www-data -

这表示建立/run/mysite-socket 文件夹,并设定好权限位以及所有者和所有群,并不设定过期清空时间。

然后,修改mysite_uwsgi.conf的描述,将socket文件指向于/run/mysite-socket文件夹内。重启计算机。之后查看/run的内部是否有mysite-socket文件夹,并确认它的权限位和所有者情况。


调试成功后进行Django的联调。通过Ctrl+C退出uWSGI,在

/home/yaoyu/MySites/uwsgi-tutorial/mysite

重新启动uWSGI

uwsgi --socket /run/mysite-socket/mysite.sock --module mysite.wsgi --chmod-socket=664 --chown-socket=yaoyu:www-data

在浏览器中访问localhost:8000应当可以看到Django的信息。用Ctrl+C退出uWSGI。

为了避免使用命令启动uWSGI并实现自动化启动uWSGI,编写uWSGI的ini文件。命名为mysite_uwsgi.ini

# mysite_uwsgi.ini file
[uwsgi]

# === 20240317. ===
# PID and log.
pidfile         = /var/run/uwsgi/%n.pid
daemonize       = /var/log/uwsgi/%n.log
# === End of 20240317. ===

# Django-related settings
# the base directory (full path)
chdir           = /home/yaoyu/MySites/uwsgi-tutorial/mysite

# Django's wsgi file
module          = mysite.wsgi

# the virtualenv (full path)
home            = /home/yaoyu/MySites/uwsgi-tutorial

# process-related settings
# master
master          = true

# maximum number of worker processes
processes       = 10

# the socket (use the full path to be safe
socket          = /home/yaoyu/MySites/uwsgi-tutorial/mysite/mysite.sock

# ... with appropriate permissions - may be needed
chmod-socket    = 775
chown-socket    = yaoyu:www-data

# clear environment on exit
vacuum          = true

=== 20240317. ===

生成/var/log/uwsgi目录。

sudo mkdir /var/log/uwsgi
sudo chown -R yaoyu:www-data /var/log/uwsgi
chmod -R g+w /var/log/uwsgi

由于ubuntu 22.04 上 /var/run 即为 /run 的符号链接,添加run_uwsgi.conf文件到/etc/tmpfiles.d

# Create /run/uwsgi.
d /run/uwsgi 0775 yaoyuh www-data -

重启系统。

=== End of 20240317. ===

使用ini文件启动uWSGI

uwsgi --ini mysite_uwsgi.ini

同样通过浏览器访问localhost:8000,成功后终止uWSGI。

在virtualenv外安装调试uWSGI

为了能够部署服务器,uWSGI不能仅运行在virtualenv中,需要在其外也能够正常运行。

以上的调试工作实际上完全在uwsgi-tutorial virtualenv中进行的,现在退出该virtualenv。执行

deactivate

安装uWSGI

sudo pip3 install uwsgi

安装完毕后,在

/home/yaoyu/MySites/uwsgi-tutorial/mysite

下测试uWSGI

uwsgi --ini mysite_uwsgi.ini

通过浏览器访问localhost:8000,应看到Django信息。用Ctrl+C退出uWSGI。

uWSGI的emperor mode

运行于emperor mode下的uWSGI,可以通过监视conf文件的变化,重新启动服务。emperor mode需要使用uWSGI的vassal文件夹进行配置,新建

/etc/uwsgi/vassals (需要root权限)

在该文件夹下添加符号连接

sudo ln -s /home/yaoyu/MySites/uwsgi-tutorial/mysite/mysite_uwsgi.ini /etc/uwsgi/vassals/

以emperor mode启动uWSGI

sudo uwsgi --emperor /etc/uwsgi/vassals --uid yaoyu --gid www-data

利用浏览器访问localhost:8000,应可看到Django信息。利用Ctrl+C退出uWSGI(emperor mode)。

配置uWSGI随系统启动

=== 20240317. ===

配置/etc/rc.local文件(需要root权限),将上述uWSGI的emperor mode启动命令添加到rc.local文件的exit 0前。(貌似不加uid和gid也可以。)

/usr/local/bin/uwsgi --emperor /etc/uwsgi/vassals --uid yaoyu --gid www-data --daemonize /var/log/uwsgi-emperor.log


保存文件,重新启动系统。重新启动之后,直接通过浏览器访问localhost:8000,应当可以看到Django信息。

在 /lib/systemd/system/ 下添加 uwsgi-emperor.service文件,需要sudo

[Unit]
Description=uWSGI Emperor
After=network.target

[Service]
ExecStart=/usr/local/bin/uwsgi --emperor /etc/uwsgi/vassals
Restart=always
User=yaoyu
Group=www-data
Environment=LOGTO=/var/log/uwsgi/service.log

之后执行

sudo systemctl enable uwsgi-emperor.service
sudo systemctl start uwsgi-emperor.service

使用

sudo systemctl status uwsgi-emperor.service

来检查service 启动情况。

=== End of 20240317. ===

总结

多看官方网页,多用google,耐心不要急。初期尽量使用源,而不要自己编译python3什么的,别说我没提醒过。。。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值