设为首页 收藏本站
查看: 501|回复: 0

[经验分享] Nginx+Gunicorn+virtualenv+supervisord+Postgresql部署Django应用

[复制链接]

尚未签到

发表于 2018-11-8 11:39:12 | 显示全部楼层 |阅读模式
  关于Django应用部署
  Django是一个高效、多功能和动态地进化的Web应用开发框架。目前比较流行的部署、运行Django应用方式是基于Apache的mod_wsgi模块,但更加高效、弹性,同时又更加复杂的方式是使用以下工具来部署实施:Nginx、Gunicorn、virtualenv、supervisord、Postgresql。以下详细介绍如何结合这些工具来部署Django应用到Linux上。
  准备工作
  需要有一台拥有root权限的Linux服务器,这是部署应用的平台。本文采用CentOS,域名直接使用localhost,ip地址为192.168.56.1。
  使用yum在线升级机制来更新系统:
  yum update -y
  PostgreSQL
  使用PostgreSQL来作为Django应用的后台数据库,在CentOS上安装:
  yum install postgresql-contrib postgresql postgresql-server postgresql-devel
  创建应用的数据库用户django和数据库hello_django:
  su - postgres
  createuser -P
  Enter name of role to add: django
  Enter password for new role:
  Enter it again:
  Shall the new role be a superuser? (y/n) n
  Shall the new role be allowed to create databases? (y/n) n
  Shall the new role be allowed to create more new roles (y/n) n
  createdb --owner django hello_django
  logout
  为应用添加系统用户
  为Django应用创建专门的系统用户,并加入django_webapps群组:
  groupadd django_webapps
  useradd -g django_webapps -d /django_webapps/hello_django django
  创建应用的Python虚拟环境
  创建django_webapps目录来保存web apps,创建hello_django目录存储应用,并修改应用目录的拥有者:
  mkdir -p /django_webapps/hello_django/
  chown django /django_webapps/hello_django/
  在应用目录创建虚拟环境,以django用户来创建:
  su - django
  cd /django_webapps/hello_django/
  virtualenv .
  激活虚拟环境:
  source bin /activate
  安装django:
  pip install django
  创建一个空的django项目,项目名为hello:
  django-admin.py startproject hello
  运行django自带的服务器来测试:
  cd hello
  python manage.py runserver localhost:8000
  Validating models...
  0 errors found
  June 14, 2014 - 03:28:01
  Django version 1.6.5, using settings 'hello.settings'
  Starting development server at http://localhost:8000/
  Quit the server with CONTROL-C.
  登录http://localhost:8000 ,可查看到django的欢迎页面。
  允许其他用户对应用目录写使能
  应用是以django用户来运行的,该用户具有应用目录的所有权限。如果想让其他的常规用户也能够修改应用文件,那么可以设置群组users为该目录的群拥有者,并赋予users写权限:
  chown -R django:users /django_webapps/hello_django
  chmod -R g+w /django_webapps/hello_django
  将django加入users群组中,并检查:
  usermod -a -G users `whoami`
  id
  uid=507(django) gid=510(django_webapps) groups=510(django_webapps),100(users)
  配置PostgreSQL
  为了在Django中使用PostgrelSQL,需要安装psycopg2。在安装psycopg2之前需要安装python-devel,以保证能构建python模块:
  yum install python-devel
  在虚拟环境中使用pip安装psycopg2数据库适应器:
  pip install psycopg2
  修改settings.py文件来配置数据库:
  DATABASES = {
  'default': {
  'ENGINE': 'django.db.backends.postgresql_psycopg2',
  'NAME': 'hello_django',
  'USER': 'django',
  'PASSWORD': '131415',    #此处最好使用密钥,可通过md5来加密
  'HOST': 'localhost',
  'PORT': '',            #set to empty string for default
  }
  }
  最后构建Django的初始化数据库:
  python manage.py syncdb
  注解:构建过程中会出现error:IDENT authentication failed for user “django”
  出现这个问题是因为PostgreSQL的Client Authentication 使用了ident authentication。
  通过修改pg_hba.conf可以解决,编辑/var/lib/pgsql/data/pg_hba.conf,修改为:
  # TYPE  DATABASE    USER        CIDR-ADDRESS          METHOD
  # "local" is for Unix domain socket connections only
  local   all         all                               trust
  # IPv4 local connections:
  host    all         all         127.0.0.1/32          trust
  # IPv6 local connections:
  host    all         all         ::1/128               trust
  Gunicorn
  在生产环境中,我们将不会使用Django自带的单线程的开发服务器,而是使用专门的Python WSGI 应用服务器——gunicorn,在本博的另一篇文章中有对gunicorn的详细介绍:Gunicorn
  首先在你的应用的虚拟环境中安装gunicorn:
  pip install gunicorn
  安装成功后可以测试下gunicorn是否可以运行Django 应用,在项目hello目录下运行以下命令:
  (hello_django)[django@rango hello]$ gunicorn hello.wsgi:application --bind localhost:8001
  通过访问http://localhost:8001 ,可以访问到你的Gunicorn服务器。此处特意将端口从8000改为8001是为了迫使浏览器建立一个新的连接。
  Gunicorn现在已经准备好运行你的app,现在可以配置一些选项来使得Gunicorn更加有用。此处通过编写一个shell脚本来设置一些参数,脚本保存为/django_webapps/hello_django/bin/gunicorn_start:
  #!/bin/bash
  NAME="hello_app"    # Name of the application
  DJANGODIR=/django_webapps/hello_django/hello    #Django project directory
  SOCKFILE=/django_webapps/hello_django/run/gunicorn.sock    #unix socket fro communication
  USER=django                     # the user to run as
  GROUP=django_webapps                     # the group to run as
  NUM_WORKERS=5         # how many worker processes should Gunicorn spawn
  DJANGO_SETTINGS_MODULE=hello.settings # which settings file should Django use
  DJANGO_WSGI_MODULE=hello.wsgi                 # WSGI module name
  echo "Starting $NAME as `whoami`"
  # Activate the virtual environment
  cd $DJANGODIR
  source ../bin/activate
  export DJANGO_SETTINGS_MODULE=$DJANGO_SETTINGS_MODULE
  export PYTHONPATH=$DJANGODIR:$PYTHONPATH
  # Create the run directory if it doesn't exist
  RUNDIR=$(dirname $SOCKFILE)
  test -d $RUNDIR || mkdir -p $RUNDIR
  # Start your Django Unicorn
  # Programs meant to be run under supervisor should not daemonize themselves (do not use --daemon)
  exec ../bin/gunicorn ${DJANGO_WSGI_MODULE}:application \
  --name $NAME \
  --workers $NUM_WORKERS \
  --user=$USER --group=$GROUP \
  --log-level=debug \
  --bind=unix:$SOCKFILE
  为该脚本增加可执行权限:
  chmod u+x bin/gunicorn_start
  以用户django的身份来运行这个脚本:
  su - django
  bin/gunicorn_start
  Starting hello_app as django
  2014-06-15 15:17:20 [18037] [INFO] Starting gunicorn 18.0
  2014-06-15 15:17:20 [18037] [DEBUG] Arbiter booted
  2014-06-15 15:17:20 [18037] [INFO] Listening at: unix:/django_webapps/hello_django/run/gunicorn.sock (18037)
  2014-06-15 15:17:20 [18037] [INFO] Using worker: sync
  2014-06-15 15:17:20 [18048] [INFO] Booting worker with pid: 18048
  2014-06-15 15:17:20 [18049] [INFO] Booting worker with pid: 18049
  2014-06-15 15:17:20 [18050] [INFO] Booting worker with pid: 18050
  2014-06-15 15:17:20 [18051] [INFO] Booting worker with pid: 18051
  2014-06-15 15:17:20 [18052] [INFO] Booting worker with pid: 18052
  ^C
  2014-06-15 15:17:51 [18052] [INFO] Worker exiting (pid: 18052)
  2014-06-15 15:17:51 [18051] [INFO] Worker exiting (pid: 18051)
  2014-06-15 15:17:51 [18037] [INFO] Handling signal: int
  2014-06-15 15:17:51 [18048] [INFO] Worker exiting (pid: 18048)
  2014-06-15 15:17:51 [18049] [INFO] Worker exiting (pid: 18049)
  2014-06-15 15:17:51 [18050] [INFO] Worker exiting (pid: 18050)
  2014-06-15 15:17:51 [18037] [INFO] Shutting down: Master
  注解:需要按照你自己的设置来修改脚本的路径和文件名。

  •   --workers的设置一般是按照2*CPUS+1,我的cpu为双核,所以设置为5.
  •   --name(NAME)为你的应用在某些程序(top,ps)中的标识,默认为gunicorn,此处设置为hello_app以便与其他gunicorn应用区别开来。
  •   为了能够设置--name,需要安装一个名为setproctitle的Python模块:pip install setproctitle
  通过ps可查看到哪个gunicorn属于哪个应用:
  ps aux | grep hello_app
  django   15226  0.0  0.2  15184  8068 ?        S    Jun13   0:25 gunicorn: master [hello_app]
  django   15237  0.0  0.4  27636 16556 ?        S    Jun13   0:01 gunicorn: worker [hello_app]
  django   15238  0.0  0.4  27640 16592 ?        S    Jun13   0:02 gunicorn: worker [hello_app]
  django   15239  0.0  0.4  27644 16600 ?        S    Jun13   0:01 gunicorn: worker [hello_app]
  django   15240  0.0  0.4  27656 16624 ?        S    Jun13   0:01 gunicorn: worker [hello_app]
  django   15242  0.0  0.2  19276 10820 ?        S    Jun13   0:01 gunicorn: worker [hello_app]
  Supervisord
  通过上述操作,gunicorn_start脚本已经可以工作了。为了确保脚本能够自动跟随系统启动和不期望的原因退出时能够重启,我们将会使用supervisord来完成这些工作。
  安装supervisord
  yum install supervisord
  配置hello应用:vim /etc/supervisord.conf
  [program:hello]
  command=/django_webapps/hello_django/bin/gunicorn_start            ;command to start app
  user=django                                ;user to run as
  stdout_logfile=/django_webapps/hello_django/logs/gunicorn_supervisor.log    ;path to write log messages
  redirect_stderr=true                            ;save stderr in the same log[program:hello]
  command=/django_webapps/hello_django/bin/gunicorn_start            ;command to start app
  user=django                                ;user to run as
  stdout_logfile=/django_webapps/hello_django/logs/gunicorn_supervisor.log    ;path to write log messages
  redirect_stderr=true                            ;save stderr in the same log
  创建相应的文件来存储应用的日志信息:
  mkdir -p /django_webapps/hello_django/logs/
  touch /django_webapps/hello_django/logs/gunicorn_supervisord.log
  保存好配置文件后让supervisord重载和更新,从而加入刚刚注册的应用hello:
  supervisorctl reread
  hello: available
  supervisorctr update
  hello:added process group
  检查hello应用的status以及启动、停止或重启它:
  supervisorctl status hello
  hello                            RUNNING    pid 15226, uptime 1 day, 23:26:29
  supervisorctl stop hello
  hello: stopped
  supervisorctl start hello
  hello: started
  supervisorctl restart hello
  hello: stopped
  hello: started
  通过上述设置,你的应用将会跟随系统自动重启以及因某些原因崩溃后的自动重启。
  Nginx
  接下来设置Nginx作为我们的应用的反向代理服务器。以下是关于Nginx正向代理和反向代理的一些知识补充:

  •   正向代理,也就是传说中的代理,他的工作原理就像一个跳板,简单的说,我是一个用户,我访问不了某网站,但是我能访问一个代理服务器,这个代理服务器呢,他能访问那个我不能访问的网站,于是我先连上代理服务器,告诉他我需要那个无法访问网站的内容,代理服务器去取回来,然后返回给我。从网站的角度,只在代理服务器来取内容的时候有一次记录,有时候并不知道是用户的请求,也隐藏了用户的资料,这取决于代理告不告诉网站。
      结论就是,正向代理 是一个位于客户端和原始服务器(origin server)之间的服务器,为了从原始服务器取得内容,客户端向代理发送一个请求并指定目标(原始服务器),然后代理向原始服务器转交请求并将获得的内容返回给客户端。客户端必须要进行一些特别的设置才能使用正向代理。
  •   反向代理,举例说明:用户访问 http://www.test.com/readme,但www.test.com上并不存在readme页面,他是偷偷从另外一台服务器上取回来,然后作为自己的内容返回用户,但用户并不知情。这里所提到的 www.test.com 这个域名对应的服务器就设置了反向代理功能。
      结论就是,反向代理正好相反,对于客户端而言它就像是原始服务器,并且客户端不需要进行任何特别的设置。客户端向反向代理的命名空间(name-space)中的内容发送普通请求,接着反向代理将判断向何处(原始服务器)转交请求,并将获得的内容返回给客户端,就像这些内容原本就是它自己的一样。
  •   两者区别:正向代理的典型用途是为在防火墙内的局域网客户端提供访问Internet的途径。正向代理还可以使用缓冲特性减少网络使用率。反向代理的典型用途是将防火墙后面的服务器提供给Internet用户访问。反向代理还可以为后端的多台服务器提供负载平衡,或为后端较慢的服务器提供缓冲服务。另外,反向代理还可以启用高级URL策略和管理技术,从而使处于不同web服务器系统的web页面同时存在于同一个URL空间下。
  安装nginx:
  yum install nginx
  启动nginx:
  service nginx start
  通过登录http://localhost可以访问到nginx的欢迎页面
  ps:如果系统中也安装了并启动了监听在80端口的apache,需要事先关闭apache服务,不然nginx无法启动。
  创建Django的Nginx虚拟服务器:
  在Nginx的主配置文件中创建一个新的nginx虚拟服务器配置:cat /etc/nginx/nginx.conf
  user              root;
  worker_processes  1;
  error_log  /var/log/nginx/error.log;
  #error_log  /var/log/nginx/error.log  notice;
  #error_log  /var/log/nginx/error.log  info;
  pid        /var/run/nginx.pid;
  events {
  worker_connections  1024;
  }
  http {
  include       /etc/nginx/mime.types;
  default_type  application/octet-stream;
  log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
  '$status $body_bytes_sent "$http_referer" '
  '"$http_user_agent" "$http_x_forwarded_for"';
  access_log  /var/log/nginx/access.log  main;
  sendfile        on;
  #tcp_nopush     on;
  #keepalive_timeout  0;
  keepalive_timeout  65;
  #gzip  on;
  # Nginx virtual server configuration for Django
  upstream hello_app_server {
  # fail_timeout=0 means we always retry an upstream even if it failed
  # to return a good HTTP response (in case the Unicorn master nukes a
  # single worker for timing out).
  server unix:/django_webapps/hello_django/run/gunicorn.sock fail_timeout=0;
  }
  server {
  listen 80;
  server_name localhost;
  client_max_body_size 4G;
  access_log    /django_webapps/hello_django/logs/nginx-access.log;
  error_log     /django_webapps/hello_django/logs/nginx-error.log;
  location /static/ {
  alias /django_webapps/hello_django/static/;
  }
  location /media/ {
  alias /django_webapps/hello_django/media/;
  }
  location / {
  # an HTTP header important enough to have its own Wikipedia entry:
  # http://en.wikipedia.org/wiki/X-Forwarded-For
  proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
  # enable this if and only if you use HTTPS, this helps Rack
  # set the proper protocol for doing redirects:
  # proxy_set_header X-Forwarded-Proto https;
  # pass the Host: header from the client right along so redirects
  # can be set properly within the Rack application
  proxy_set_header Host $http_host;
  # we don't want nginx trying to do something clever with
  # redirects, we set the Host: header above already.
  proxy_redirect off;
  # set "proxy_buffering off" *only* for Rainbows! when doing
  # Comet/long-poll stuff. It's also safe to set if you're
  # using only serving fast clients with Unicorn + nginx.
  # Otherwise you _want_ nginx to buffer responses to slow
  # clients, really.
  # proxy_buffering off;
  # Try to serve static files from nginx, no point in making an
  # *application* server like Unicorn/Rainbows! serve static files.
  if (!-f $request_filename) {
  proxy_pass http://hello_app_server;
  break;
  }
  }
  # Error pages
  error_page 500 502 503 504 /500.html;
  location = /500.html {
  root /django_webapps/hello_django/static/;
  }
  }
  # Load config files from the /etc/nginx/conf.d directory
  # The default server is in conf.d/default.conf
  include /etc/nginx/conf.d/*.conf;
  }
  注解:

  •   此处将user设置为超级用户root是因为nginx及其他用户没有对django项目所在目录的任何权限,如果不设置为root,登录http://localhost会显示403 forbidden错误。或者也可以添加nginx用户对应用目录的读权限。
  •   upstream表示nginx代理的上游服务器其实是gunicorn。
  重启nginx:
  service nginx restart
  登录http://localhost可以看到由Nginx和Gunicorn支持的Django欢迎页面。现在可以着手构建你自己的项目和应用,enjoy!!
  卸载Django应用
  通过以下步骤可以卸载掉不需要的应用:
  首先修改nginx配置文件来去除虚拟服务器的设置,然后重启:
  service nginx restart
  使用supervisord来停止应用,并删除supervisord配置文件中对应的应用配置信息:
  supervisorctl stop hello
  如果再也不想使用这个应用,可以考虑删除掉整个应用文件所在目录:
  rm -rf /django_webapps/hello_django/
  运行多个Django应用
  在同一个Nginx服务器上可以运行多个Django应用,通过不同的域名设置可以登录到不同的url来实现对多个django应用的访问。每一个应用将会设置自己的Python虚拟开发环境,创建专门的运行用户和对应的权限设置、数据库用户和数据库等。
  依据前文构建hello项目的步骤可以构建一个jay项目,包括数据库的创建、系统用户的设置、supervisord的设置等等。现在最重要的是Nginx虚拟服务器的设置了:
  与前文设置hello_app_server类似,可在nginx配置文件中增加jay_app_server虚拟服务器的设置:
  upstream jay_app_server {
  # fail_timeout=0 means we always retry an upstream even if it failed
  # to return a good HTTP response (in case the Unicorn master nukes a
  # single worker for timing out).
  server unix:/django_webapps/jay_django/run/gunicorn.sock fail_timeout=0;
  }
  server {
  listen 80;
  server_name jaycn.sysu;
  client_max_body_size 4G;
  access_log    /django_webapps/jay_django/logs/nginx-access.log;
  error_log     /django_webapps/jay_django/logs/nginx-error.log;
  location /static/ {
  alias /django_webapps/jay_django/static/;
  }
  location /media/ {
  alias /django_webapps/jay_django/media/;
  }
  location / {
  # an HTTP header important enough to have its own Wikipedia entry:
  # http://en.wikipedia.org/wiki/X-Forwarded-For
  proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
  # enable this if and only if you use HTTPS, this helps Rack
  # set the proper protocol for doing redirects:
  # proxy_set_header X-Forwarded-Proto https;
  # pass the Host: header from the client right along so redirects
  # can be set properly within the Rack application
  proxy_set_header Host $http_host;
  # we don't want nginx trying to do something clever with
  # redirects, we set the Host: header above already.
  proxy_redirect off;
  # set "proxy_buffering off" *only* for Rainbows! when doing
  # Comet/long-poll stuff. It's also safe to set if you're
  # using only serving fast clients with Unicorn + nginx.
  # Otherwise you _want_ nginx to buffer responses to slow
  # clients, really.
  # proxy_buffering off;
  # Try to serve static files from nginx, no point in making an
  # *application* server like Unicorn/Rainbows! serve static files.
  if (!-f $request_filename) {
  proxy_pass http://jay_app_server;
  break;
  }
  }
  # Error pages
  error_page 500 502 503 504 /500.html;
  location = /500.html {
  root /django_webapps/jay_django/static/;
  }
  }
  可以修改hello_app_server服务器的server_name为hello.sysu
  保存配置文件并重启nginx:
  service nginx restart
  最后设置好域名,以便DNS服务器能够解析刚才设置好的两个域名:vim /etc/hosts
  192.168.56.1    hello.sysu jaycn.sysu
  通过登录每个域名来测试服务器上的app是否设置正确:
  http://hello.sysu
  http://jaycn.sysu
  ——游响云停


运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.iyunv.com/thread-632373-1-1.html 上篇帖子: zabbix3.0.4监控nginx性 下篇帖子: 如何用nginx源码制作rpm包的详解
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表