在 Linux 上部署 Django 应用,nginx+gunicorn+supervisor
如果是新服务器先要进行基本的配置
部署前应用配置
开发环境与生产环境中的应用一般会有两套不同的配置。比如 DEBUG 选项,数据库配置等。
对于 setting.py 文件, 在生产环境中我们要设置 DEBUG, SECRET_KEY 以及数据库密码等私密的设置。为了项目的安全这些设置应该最好从环境变量加载,或从仅供服务的文件中读取。
为了更好的统一线上和线下两个环境, 我们使用 python-dotenv
工具. 有了这个工具, 我们可以将配置信息写在 .env
文件中,然后使用下面的代码加载配置信息到环境变量中:
# settings.py
from dotenv import load_dotenv
load_dotenv()
具体配置方法:
- 进入虚拟环境, 安装 python-dotenv
pip install python-dotenv
- 在 Django 项目根目录处建立
.env
文件(与manage.py 同目录), 并添加配置
DJANGO_DEBUG=Ture
- 修改 setting.py 文件,将一些关键配置改成从环境变量中读取, 没有就设为默认值
import os
from dotenv import load_dotenv
load_dotenv()SECRET_KEY = os.environ.get('SECRET_KEY', 'mzi&f@)*4985)m19oj+x-hg4$hi!478v)+dz)bh+mgiz!zjg9n')
DEBUG = os.environ.get('DJANGO_DEBUG', False)
# 当 DEBUG=Flase 时, 设置的能够访问的主机
ALLOWED_HOSTS = ['127.0.0.1', 'localhost', '.xxmblog.top', '<服务器的IP地址>']
# 数据库设置, 便于在生产环境中直接改为 MySQL 数据库
DATABASES = {'default': {'ENGINE': os.environ.get('DATABASE_ENGINE') or 'django.db.backends.sqlite3','NAME': os.environ.get('DATABASE_NAME') or os.path.join(BASE_DIR, 'db.sqlite3'),'USER': os.environ.get('DATABASE_USER'), # 用户名,可以自己创建用户'PASSWORD': os.environ.get('DATABASE_PASSWORD'), # 密码'HOST': os.environ.get('DATABASE_HOST'), # mysql服务所在的主机ip'PORT': os.environ.get('DATABASE_PORT'), # mysql服务端口}
}
# ...
STATIC_URL = '/static/'
# 增加下面的, 便于在生产环境中收集静态文件
STATIC_ROOT = os.path.join(BASE_DIR, 'static')
接下来,关键的是,.env
保存一些私密的配置,不要添加到git中。
开发环境的 .env
:
DJANGO_DEBUG 为非空字符串时为 Ture, 不设置默认为 Flase
# 其他一些数据库配置
生产环境中的 .env
设置后面单独说明。
当有其他生产环境和开发环境不同的配置时,都让Django从环境变量中读取,我们就写在.env
文件中。这样部署的时候就不用修改源代码了。
其他配置:
- 静态文件收集
为了使 Nginx 方便的处理静态文件的请求,生产环境中需要将全部静态文件收集到一个统一的目录下。
先添加如下配置:
STATIC_ROOT = os.path.join(BASE_DIR, 'static')
STATIC_ROOT 指明了静态文件的收集目录,到生产环境中有用
- 导出依赖库
进入虚拟环境, 执行下列命令
pip freeze > requirements.txt
会生成一个 requirements.txt 文件, 里面包含了虚拟环境中安装的所有依赖。
到了服务器上,只需要执行
pip install -r requirements.txt
就能安装里面列的所有库了。
上传到 Github
注意到
.env
文件不能上传,服务器应该自己建一个
db.sqlite3
不上传, 因为这是本地的测试数据库, 到了生产环境, 应该用其他的数据库了
venv
文件夹不上传
在服务器上安装应用
在自己的家目录下(如 home/xxm/
) 创建文件夹
➜ ~ mkdir sites
➜ ~ mkdir sites/www.xxmblog.com
所有的网站放在 sites 目录中,网站的项目以域名区分, 进入 www.xxmblog.com
目录。
通过 git clone
将应用下载到该目录中
然后进入项目目录并创建虚拟环境:
$ python3 -m venv venv
$ source venv/bin/activate
此时的项目结构:
home/xxm/sites/www.xxmblog.top/blog-django/blogproject/venv/.gitignorerequirements.txt
安装项目依赖
先安装必要的包
(venv) $ pip install -r requirements.txt
除了requirements.txt中的包之外,还要安装生产部署需要的两个包。gunicorn软件包是Python应用程序的生产Web服务器。 mysqlclient 软件包包含MySQL驱动程序
(venv) $ pip install gunicorn mysqlclient
如果安装 mysqlclient 出现错误, 运行下面的命令。
sudo apt-get install python-dev python3-dev
sudo apt-get install libmysqlclient-dev
pip install pymysql
pip install mysqlclient
配置 MySQL
MySQL 的安装不做说明, 具体讲述如何让 Django 使用 MySQL 数据库。
下列命令创建名为 blog-django 的新数据库,并创建一个具有完全访问权限的同名用户:
mysql> create database blogdjango character set utf8 collate utf8_bin;
mysql> create user 'blogdjango'@'localhost' identified by '<db-password>';
mysql> grant all privileges on blogdjango.* to 'blogdjango'@'localhost';
mysql> flush privileges;
mysql> quit;
需要用你选择的密码来替换<db-password>
, 这将是 blogdjango 数据库用户的密码,所以不要使用你已为root用户选择的密码
接下来就是修改 setting.py 文件,让 Django 使用刚刚创建的数据库。但是由于我们前面使用了 dotenv,seeting.py 的一些配置已经从环境变量中读取, 所以我们只需配置 .env
文件即可
配置 .env
创建一个 .env
文件, 与 manage.py 同目录。
在里面输入:
SECRET_KEY=<随机字符串>
DATABASE_ENGINE=django.db.backends.mysql
DATABASE_NAME=blogdjango
DATABASE_USER=blogdjango
DATABASE_PASSWORD=<刚刚创建用的密码>
DATABASE_HOST=localhost
DATABASE_PORT=3306
SECRET_KEY 使用一个随机字符串
DJANGO_DEBUG 不设置时,DEBUG为FALSE
其他为MySQL的数据库配置
收集静态文件
虚拟环境下继续运行 python manage.py collectstatic
命令收集静态文件到 static 目录下:
数据库迁移
虚拟环境下继续运行 python manage.py migrate 命令创建数据库文件:
python manage.py makemigrations
python manage.py migrate
创建超级用户
虚拟环境下继续运行 python manage.py createsuperuser 命令创建一个超级用户,方便我们进入 Django 管理后台
尝试运行一下应用
python manage.py runserver
如果上面的命令没有出错的话,一般就没有问题了。
设置 Gunicorn 和 Supervisor
当使用 python manage.py runserver
运行服务器时, 我们使用的是 Django 自带的Web服务器。这个服务器在开发过程中很有用,但并不适用于生产环境,所以我们改用 Gunicorn, 它是一个纯粹的Python Web服务器, 并且支持高并发。
尝试在 gunicorn 下启动 blogproject:
gunicorn -b localhost:8000 -w 4 blogproject.wsgi:application
-b
告诉 gunicorn 在哪里监听请求,我在8000端口上监听了内部网络接口。在没有外部访问的情况下,运行 Python Web 服务器很快。当有外部请求的时候,我们就需要一个更快的Web服务器,比如 nginx,它可以优化客户端的所有静态文件的请求,并将任何请求转发到内部服务器。后面我们会设置 nginx。
-w
配置gunicorn将运行多少worker
blogproject.wsgi:application
告诉gunicorn如何加载应用程序实例. 冒号前的名称是包含应用程序的模块,冒号后面的名称是此应用程序的名称。
运行了上面的命令后,我们看到:
(venv) ➜ blogproject git:(master) ✗ gunicorn -b localhost:8000 -w 4 blogproject.wsgi:application
[2019-08-16 11:18:50 +0800] [5674] [INFO] Starting gunicorn 19.9.0
[2019-08-16 11:18:50 +0800] [5674] [INFO] Listening at: http://127.0.0.1:8000 (5674)
[2019-08-16 11:18:50 +0800] [5674] [INFO] Using worker: sync
[2019-08-16 11:18:50 +0800] [5677] [INFO] Booting worker with pid: 5677
[2019-08-16 11:18:50 +0800] [5678] [INFO] Booting worker with pid: 5678
[2019-08-16 11:18:50 +0800] [5680] [INFO] Booting worker with pid: 5680
[2019-08-16 11:18:50 +0800] [5679] [INFO] Booting worker with pid: 5679
gunicorn 监听 http://127.0.0.1:8000, 并启动了4个worker.
[Ctrl+C]
退出进程。
可以看到,目前我们想要启动服务器,每次都要输入一遍上面的命令,如果进程崩溃了,还要手动输入上面的命令让服务器重新启动。这真的很傻,所以我们使用一个 supervisor 的应用。
supervisor 的功能:
- 可以让这个进程后台运行,并持续监控
- 如果服务器崩溃退出,这个进程可以重新自动启动
- 而且如果机器重新启动,服务器在启动时自动运行,而无需人工登录和启动
安装:
sudo apt-get install supervisor
supervisor 使用配置文件来告诉它要监视什么程序以及如何在必要时重新启动它们
配置文件必须存储在 /etc/supervisor/conf.d
中
对于我们这个 blogproject 应用,我们创建一个 blogproject.conf 配置文件:
/etc/supervisor/conf.d/blogproject.conf:Supervisor配置。
[program:blogproject]
command=/home/xxm/sites/www.xxmblog.com/blog-django/venv/bin/gunicorn -b localhost:8000 -w 4 blogproject.wsgi:application
directory=/home/xxm/sites/www.xxmblog.com/blog-django/blogproject
user=xxm
autostart=true
autorestart=true
stopasgroup=true
killasgroup=true
command
,directory
和user
设置告诉supervisor如何运行应用程序。 如果计算机启动或崩溃,autostart
和autorestart
设置会使microblog自动重新启动。 stopasgroup
和killasgroup
选项确保当supervisor需要停止应用程序来重新启动它时,它仍然会调度成顶级gunicorn进程的子进程。
编写此配置文件后,必须重载supervisor服务的配置才能导入它:
$ sudo supervisorctl reload
像这样,这个gunicorn web服务器就已经启动和运行,并处于监控之中!
查看状态:
sudo supervisorctl status
如果出现下面的内容,可能是配置文件出错了
blogproject FATAL Exited too quickly (process log may have details)
如果是下面表示正在运行:
blogproject RUNNING pid 5865, uptime 0:00:03
其他命令
sudo supervisorctl stop xxx # 关闭 xxx
sudo supervisorctl restart xxx # 重启 xxx
配置 Nginx
由 gunicorn 启动的 blogproject 应用服务器现在运行在本地端口8000. 我们想要让服务器能够被外部世界访问。
首先打开两个端口 80 和 443 用来处理应用程序的 Web 通讯。如果是阿里云服务器需要在控制台上配置安全组。
我们直接使用 https, 配置端口80将所有流量转发到将要加密的端口443.
首先创建一个 SSL 证书, 这个证书只能用来测试,当用户访问的时候, Web 浏览器会警告用户证书不是由可信证书颁发机构颁发的。
mkdir certs
openssl req -new -newkey rsa:4096 -days 365 -nodes -x509 \-keyout certs/key.pem -out certs/cert.pem
生成的时候填写的信息,将包含在 SSL 证书中, 用户在浏览器访问的时候可以查看。
命令的结果将生成名为key.pem和cert.pem的两个文件。
为了使用 nginx, 为我们就要编写一个配置文件,这个文件位于 /etc/nginx/sites-enabled
中,
通常刚安装完 Ngnix,在这个位置有一个默认的测试站点, 我们将其删除:
$ sudo rm /etc/nginx/sites-enabled/default
然后创建 blogproject 配置文件:
/etc/nginx/sites-enabled/blogproject:Nginx配置。
server {# 监听 80 端口listen 80;server_name _;location / {# redirect any requests to the same URL but on httpsreturn 301 https://$host$request_uri;}
}
server {# 监听 443 端口listen 443 ssl;# 服务器域名server_name _;# 刚刚生成的自签名ssl证书的位置ssl_certificate /home/xxm/sites/www.xxmblog.com/blog-django/certs/cert.pem;ssl_certificate_key /home/xxm/sites/www.xxmblog.com/blog-django/certs/key.pem;# 将访问和错误日志写入 /var/logaccess_log /var/log/microblog_access.log;error_log /var/log/microblog_error.log;location / {# forward application requests to the gunicorn serverproxy_pass http://localhost:8000;proxy_redirect off;proxy_set_header Host $host;proxy_set_header X-Real-IP $remote_addr;proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;}# 所有URL 带有 /static 的请求均由 Nginx 处理,alias 指明了静态文件的存放目录。location /static {alias /home/xxm/sites/www.xxmblog.com/blog-django/blogproject/static;expires 30d;}
}
添加此文件后,你需要告诉nginx重新加载配置以激活它:
$ sudo service nginx reload
浏览器输入域名或者服务器的IP地址,应该可以看到访问成功了。
应用更新
当应用更新的时候,往往需要重复下列的过程:
- 从 github 中拉取应用
git pull
- 可能需要修改
.env
文件, 增加环境变量 - 进入虚拟环境, 安装额外的依赖
pip install -r requirements.txt
- 收集静态文件
python manage.py collectstatic
- 数据库迁移
python manage.py makemigrations
python manage.py migrate
- 重启进程
sudo supervisorctl restart blogproject
- 重启nginx
sudo service nginx reload
在 Linux 上部署 Django 应用,nginx+gunicorn+supervisor相关推荐
- 在Centos8上部署Django环境(Nginx+mysql+uwsgi)
前言:笔者通过阿里云的学生"在家实践计划"获得了一台2核4G的云ECS实例,并安装了Centos8镜像.于是尝试部署一套Django的生产环境.笔者选择了 Nginx + uwsg ...
- 开源项目新蜂商城在Linux上部署,mysql+nginx
newbee-mall是一项基于Spring Boot的在线商城系统,非常适合新手了解学习Spring Boot框架 源码新蜂商城后端接口 newbee-mall-api 新蜂商城 Vue3 版本 n ...
- heroku创建linux主机,在 Heroku 上部署 Django 应用
在 Heroku 上部署 Django 应用 Heroku是一个很棒的平台,它有很多的控件,并且搭建环境相对来说也比较容易.本指南中,我将一步一步指导你在Heroku平台上部署一个简单地Django应 ...
- 【Flask】Nginx+Gunicorn+Supervisor部署一个Flask项目:步骤总结
为什么要使用gunicorn? Flask 作为一个 Web 框架,内置了一个 webserver, 但这自带的 Server 到底能不能用? 官网的介绍: While lightweight and ...
- [转]Docker部署Django由浅入深系列(下): 八步部署Django+Uwsgi+Nginx+MySQL+Redis
在上篇教程中,我们手动构建了两个容器,一个容器放Django + Uwsgi,另一个容器放Nginx,成功部署了一个简单的Django项目.然而在实际的生产环境中,我们往往需要定义数量庞大的 dock ...
- Docker部署Django由浅入深系列(中): 双容器部署Django + Uwsgi + Nginx
本文是使用Docker部署Django由浅入深系列的中篇,我们将构建两个容器,一个容器放Django + Uwsgi,另一个容器放Nginx.我们将了解不同容器间是如何通信的,并学会正确配置uwsgi ...
- 在Linux上部署各种软件总结
实战章节:在Linux上部署各类软件 前言 为什么学习各类软件在Linux上的部署 在前面,我们学习了许多的Linux命令和高级技巧,这些知识点比较零散,同学们跟随着课程的内容进行练习虽然可以基础掌握 ...
- 一、netcore跨平台之 Linux上部署netcore和webapi
文章目录 一.netcore跨平台之 Linux上部署netcore和webapi 第一步,你得先创建一个netcore的接口,这个我就简单创建一个接口 第二步,你得准备一个linux服务器,然后安装 ...
- 怎样在linux上部署web服务器
linux上部署web服务器 1.从Apache官网下载源码. 2.卸载原来已经存在的httpd. 3.挂载光盘准备部署httpd. 4.源码编译安装httpd, 解包 , 配置(--prefix:指 ...
最新文章
- 2022-2028年中国无溶剂聚氨酯复膜胶行业市场调查研究及发展前景规划报告
- 微信小程序 在使用wx.request时显示加载中
- 表框mysql_mysql 表的操作
- 计算机强势专业大学,计算机专业实力最强的6所大学,认可度高,竞争优势大,值得选择...
- Spring5.0 Kafka2.11
- centos挂载windows共享目录
- 编译moveit!时缺失manipulation_msgs相关文件
- 特征筛选3——卡方检验筛选特征(单变量筛选)
- 【看这一篇就够了】如何删除gitHub仓库中的文件
- HanLP里使用DAT存取字典的方法
- GB2312 一二级中文汉字字库(带拼音)
- MC74HC595驱动
- 2017中国云计算技术大会将于5月18-19日在京召开
- R语言如何做独立样本t检验
- linux时间同步到win7,mac与win7时间不同步怎么办_mac与win7时间不准如何解决
- 让logo设计更有设计感的几个方法
- (转)一共81个,开源大数据处理工具汇总
- Android 自定义View之咖啡杯动画
- 2019-详细Android Studio开发百度地图(4)—百度地图_路线规划的实现
- Ubuntu部署sbt
热门文章
- ORA-22859 无效的列修改
- 2021 年百度之星·程序设计大赛 - 初赛二 1002 随机题意(区间贪心)
- 2021牛客暑期多校训练营2,签到题CDFKI
- linux的manual手册不存在,Linux笔记
- 液晶显示屏的C语言编码,单片机液晶汉字显示c语言程序
- eclipse java开发实例_eclipse+webservice开发实例
- JavaScript文档对象模型DOM节点操作之兄弟节点(4)
- HDU 4553:约会安排(区间合并)
- cube 一站式云原生开源机器学习平台
- python应用系列教程——python使用SocketServer实现网络服务器,socket实现客户端