在 Linux 上部署 Django 应用,nginx+gunicorn+supervisor

如果是新服务器先要进行基本的配置

部署前应用配置

开发环境与生产环境中的应用一般会有两套不同的配置。比如 DEBUG 选项,数据库配置等。

对于 setting.py 文件, 在生产环境中我们要设置 DEBUG, SECRET_KEY 以及数据库密码等私密的设置。为了项目的安全这些设置应该最好从环境变量加载,或从仅供服务的文件中读取。

为了更好的统一线上和线下两个环境, 我们使用 python-dotenv 工具. 有了这个工具, 我们可以将配置信息写在 .env 文件中,然后使用下面的代码加载配置信息到环境变量中:

# settings.py
from dotenv import load_dotenv
load_dotenv()

具体配置方法:

  1. 进入虚拟环境, 安装 python-dotenv
pip install python-dotenv
  1. 在 Django 项目根目录处建立 .env 文件(与manage.py 同目录), 并添加配置
DJANGO_DEBUG=Ture
  1. 修改 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/
                                    .gitignore
                                    requirements.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


commanddirectoryuser设置告诉supervisor如何运行应用程序。 如果计算机启动或崩溃,autostartautorestart设置会使microblog自动重新启动。 stopasgroupkillasgroup选项确保当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 https
        return 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/log
    access_log /var/log/microblog_access.log;
    error_log /var/log/microblog_error.log;

    location / {
        # forward application requests to the gunicorn server
        proxy_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地址,应该可以看到访问成功了。

应用更新

当应用更新的时候,往往需要重复下列的过程:

  1. 从 github 中拉取应用
git pull
  1. 可能需要修改 .env 文件, 增加环境变量
  2. 进入虚拟环境, 安装额外的依赖
pip install -r requirements.txt
  1. 收集静态文件
python manage.py collectstatic
  1. 数据库迁移
python manage.py makemigrations
python manage.py migrate
  1. 重启进程
sudo supervisorctl restart blogproject
  1. 重启nginx
sudo service nginx reload
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Django是一个优秀的Web框架,可以帮助开发者快速构建Web应用程序。但是,当我们需要将Django应用程序部署到生产环境时,我们需要考虑很多方面,例如性能、安全、可靠性等。本文将介绍如何使用GunicornNginxDjango应用程序部署到生产环境中。 ## 准备工作 在开始之前,我们需要在服务器上安装一些必要的软件包和库。 ### 安装Python和pip 首先,我们需要在服务器上安装Python和pip。如果您已经安装了它们,请跳过此步骤。 ```shell # Ubuntu sudo apt-get update sudo apt-get install python3 python3-pip # CentOS sudo yum update sudo yum install python3 python3-pip ``` ### 创建虚拟环境 为了避免与其他Python应用程序的依赖项冲突,我们建议在服务器上使用虚拟环境。在此过程中,我们将使用venv创建一个虚拟环境。 ```shell python3 -m venv myenv source myenv/bin/activate ``` ### 安装DjangoGunicorn 一旦我们进入虚拟环境,我们可以使用pip安装DjangoGunicorn。 ```shell pip install django gunicorn ``` ## 配置Gunicorn Gunicorn是一个Python WSGI HTTP服务器,可以处理Django应用程序的并发请求。下面是如何配置Gunicorn。 ### 创建Gunicorn配置文件 我们可以为Gunicorn创建一个配置文件。在此过程中,我们将创建一个名为`gunicorn_config.py`的文件。 ```python bind = "127.0.0.1:8000" workers = 3 user = "myuser" ``` 在这个配置文件中,我们定义了以下几个参数: - `bind`:指定Gunicorn绑定的IP地址和端口号。 - `workers`:指定Gunicorn启动的工作进程数。 - `user`:指定Gunicorn运行的用户。 请注意,我们将Gunicorn绑定到`127.0.0.1`地址,这意味着它只能在本地访问。如果您想让Gunicorn在公共IP地址上运行,请使用`0.0.0.0`。 ### 启动Gunicorn 一旦我们创建了配置文件,我们可以使用以下命令启动Gunicorn。 ```shell gunicorn myproject.wsgi:application -c gunicorn_config.py ``` 在这个命令中,我们指定了Django的WSGI入口点`myproject.wsgi:application`,以及Gunicorn配置文件`gunicorn_config.py`。 ## 配置Nginx 现在我们已经成功启动了Gunicorn,我们需要将Nginx配置为反向代理,以便客户端可以通过Nginx访问我们的应用程序。 ### 安装Nginx 如果您还没有安装Nginx,请按照以下步骤进行安装。 ```shell # Ubuntu sudo apt-get update sudo apt-get install nginx # CentOS sudo yum update sudo yum install nginx ``` ### 创建Nginx配置文件 我们需要为Nginx创建一个配置文件。在此过程中,我们将创建一个名为`myproject.conf`的文件。 ```nginx server { listen 80; server_name example.com; access_log /var/log/nginx/access.log; location / { proxy_pass http://127.0.0.1:8000; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } } ``` 在这个配置文件中,我们定义了以下几个参数: - `listen`:指定Nginx监听的端口号。 - `server_name`:指定Nginx的域名。 - `access_log`:指定Nginx的访问日志路径。 - `location`:指定Nginx的URL匹配规则和反向代理设置。 请注意,我们将Nginx绑定到`example.com`域名,并将所有请求转发到Gunicorn运行的`127.0.0.1:8000`地址。 ### 重启Nginx 一旦我们创建了配置文件,我们可以使用以下命令重新启动Nginx。 ```shell sudo service nginx restart ``` ## 结论 现在我们已经成功地将Django应用程序部署到生产环境中。我们使用Gunicorn处理并发请求,并使用Nginx作为反向代理,以提高性能和安全性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值