【django】【专题】(部署)部署 django 项目

本文详细介绍了Django项目从源码获取到服务器部署的全过程,包括环境配置、测试运行、数据库与静态文件处理、Nginx与Gunicorn配置,以及systemd服务管理,确保项目稳定运行。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >



1 剥离项目源码 - N/A



2 首次部署

2.1 Django 项目与环境

2.1.1 获取项目源码

从你的 git 仓库下载 django 项目:

$ cd $HOME/tmp/
tmp/ $ git clone https://<path>/<to>/django-proj.git
tmp/ $ ls -F
django-proj/
tmp/ $ cd django-proj
django-proj/ $

我预期你的项目文件结构会像以下这样:

django-proj/ $ tree ./ -L 3
./
├── Docs/
│   └── n/a
├── source/
│   ├── source/
│   │   ├── __init__.py
│   │   ├── settings.py
│   │   ├── urls.py
│   │   └── wsgi.py
│   ├── functional_test/
│   │   ├── __init__.py
│   │   └── tests.py
│   ├── application/
│   │   ├── admin.py
│   │   ├── apps.py
│   │   ├── forms.py
│   │   ├── __init__.py
│   │   ├── migrations/
│   │   ├── models.py
│   │   ├── static/
│   │   ├── templates/
│   │   ├── tests/
│   │   ├── urls.py
│   │   └── views.py
│   ├── manage.py
│   └── requirements.txt
├── README.md
├── static
│   └── favicon.ico
└── virtualenv
    └── readme.virtualenv --python=python3 virtualenv.txt

* directories, * files
2.1.2 配置运行环境
django-proj/ $ ls -F
README.md virtualenv/ static/ source/ Doc/
django-proj/ $ virtualenv --python=python3 ./virtualenv/
...

django-proj/ $ cd source/
source/ $ ls -F
source/ application/ requirements.txt functional_test/ manage.py
source/ $ source ../virtualenv/bin/activate
(virtualenv) source/ $ pip install -r requirements.txt
...
(virtualenv) source/ $ deactivate 

2.2 运行测试

2.2.1 可以使用 python manage.py runserver 运行看看
source/ $ source ../virtualenv/bin/activate
(virtualenv) source/ $ python manage.py runserver
...
Ctrl+C to quit

^C
2.2.2 运行 Test Case
(virtualenv) source/ $ ### if have test case #####
(virtualenv) source/ $ python manage.py test application
(virtualenv) source/ $ python manage.py test functional_test  # 如果没有就不用运行

2.3 Django WSGI

2.3.1 使用绿色独角兽 gunicorn
(virtualenv) source/ $ pip install gunicorn  # 可能已经包含在了 requirements.txt 中了。
(virtualenv) source/ $ gunicorn source.wsgi:application
...

注意:

  1. 上面运行的 source.wsgi.application 和项目中的 application/ 文件夹不同
    项目中的 application/ 可能是其它任意名字,比如 poll/, blog/, todolists/ 等等。
    gunicorn 运行的 application 就是 application 是一个“命令”。

    关于 source.wsgi.application 这句命令你可以在 django-proj/source/source/settings.py 中可以看到:

    WSGI_APPLICATION = 'source.wsgi.application'
    
  2. 如果是 follow 上述步骤,那么当前项目源码还缺少数据库和静态文件收集。
    数据库:这个目前没什么影响,可以暂时先略过。

  3. 项目静态文件问题,gunicorn 不会自动伺服静态文件,所以你看到样式会有问题。
    但是这一步至少可以确认 django 项目的 server 是可以正常运行的。

浏览器打开 ‘http://localhost:8000’ 可以查看一下效果。


2.4 Django 项目周边 - 数据库和静态文件

2.4.1 数据库

这里仅说明 django 默认使用的 SQLite3 数据库在部署时的相关操作。

2.4.1.1 配置

我预期你的 django-proj/source/source/settings.py 文件中的数据库部分内容为如下样子:

# Database
# https://docs.djangoproject.com/en/2.1/ref/settings/#databases

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': os.path.join(BASE_DIR, '../database/db.sqlite3'),
    }
}

如果不是则可以改成以上? 代码。

如果不存在 django-proj/database/ 文件夹,则创建它!

2.4.1.2 migrate

运行以下命令迁移/创建一个空白的数据库文件:

(virtualenv) source/ $ python manage.py migrate --noinput
2.4.2 django 项目的静态文件
2.4.1 收集静态文件

当前项目目录结构预期如下:

$ tree ./ -L 1
./
├── database/
├── Docs/
├── source/
├── README.md
└── virtualenv/

创建 static 目录:

$ mkdir static
$ tree ./ -L 1
./
├── database/
├── Docs/
├── source/
├── README.md
├── static/
└── virtualenv/

执行 collectstatic 前

我的方式首先是要修改一下 settings.py 文件如下:

[...]

STATIC_URL = '/static/'

## uncomment this \/ when need runining `python manage.py collectstatic`
STATIC_ROOT = os.path.abspath(os.path.join(BASE_DIR, '../static'))

#STATICFILES_DIRS = [
#    os.path.join(BASE_DIR, '../static'),
#]

注意上面的 ../static 使用的是针对项目文件夹的相对路径。
最后 STATIC_ROOT 变量绑定的值会是这个放置静态文件的 static/ 文件夹的绝对路径。
需要将该文件中 STATICFILES_DIRS 的配置内容注释掉。

然后执行

(virtualenv) $ ls -F
database/  source/               README.md  static/
Docs/      virtualenv/
(virtualenv) $ cd source/
$ python manage.py collectstatic
........output.......
.....................

相信你已经注意到了有的命令行有指示 (virutalenv) $ 有的命令行没有(只有单独的 $)。
和执行 python 程序有关的命令都需要 (virtualenv) $。它代表了当前激活了虚拟环境并且是在该虚拟环境下运行的。
激活虚拟环境的方式上面写过很多次了,这里再单独提醒一下:

django-proj/ $ source ./virtualenv/bin/activate
# or source/ $ source ../virtualenv/bin/activate  ## 这只是代表当前所在目录位置不同而已
django-proj/ $ deactivate  ## 退出当前虚拟环境。

最后不要忘记改回 settings.py 文件的配置
(至少在我的情况下,是需要改回去的。)

[...]

STATIC_URL = '/static/'

## uncomment this \/ when need runining `python manage.py collectstatic`
# STATIC_ROOT = os.path.abspath(os.path.join(BASE_DIR, '../static'))

STATICFILES_DIRS = [
    os.path.join(BASE_DIR, '../static'),
]

2.5 配置 nginx

回顾一下,我们现在完成了哪些工作。
首先 安装/下载了 django 项目代码 ⇒ 配置了 server 运行的环境
⇒ 运行了 server ⇒ 运行了测试
⇒ 安装了 gunicorn,通过 django 的 wsgi 运行 server
⇒ 完成了数据库和静态文件的环境设置

现在我们使用 nginx 做代理服务。
以监听 11100 端口为例,配置 nginx。

2.5.1 安装 nginx
$ sudo apt install nginx

如果已经安装 Apache,并且发生 nginx 安装出错的话,则可以修改一下 Apache 的默认监听端口80,然后重启 Apache,再次安装 nginx。

2.5.2 简单的 nginx 配置
server {
	listen 11100;
	server_name <your-domain>;

	location / {
		proxy_pass http://localhost:8000;
	}
}

将上面配置代码保存为 <your-domain> 文件(例如 example.com);放在 /etc/nginx/sites-available/ 文件夹下(例如 /etc/nginx/sites-available/example.com)。
然后运行如下命令:

$ sudo ln -s /etc/nginx/sites-available/<your-domain> \
             /etc/nginx/sites-enabled/<your-domain>
$ sudo service nginx reload # 有 restart, stop, start 等命令可用。
$ cd <path>/<to>/django-proj/source
$ ../virtualenv/bin/python manage.py runserver
# or $ ../virtualenv/bin/gunicorn source.wsgi.application

现在你可以启动浏览器,访问 http://localhost:11100/ 来访问该项目
或者它运行在你的域名对应的服务器上,访问 http://<your-domain>:11100/ 来访问。

注意,如果使用上面 line 6 代替 line 5 运行,则目前静态文件加载会有问题,下一节进一步配置 nginx 会解决。

2.5.3 Nginx 的 Django 项目的静态文件配置

修改上面的配置文件,其它内容不变,增加以下 line 4~6 内容:

...
	server_name <your-domain>

    location /static {
        alias /<path>/<to>/django-proj/static;
    }

	location / {
...

现在:

$ sudo service nginx reload
$ cd <path>/<to>/django-proj/source
$ ../virtualenv/bin/gunicorn source.wsgi:application
...

访问使用 gunicorn 启动的 server 能够正确地加载静态文件了。

2.5.4 使用 UNIX 套接字

再一次修改上面地配置文件:

...
    location /static {
        alias /<path>/<to>/django-proj/static;
    }

	location / {
		proxy_set_header Host $host;
		proxy_pass http://unix:/run/gunicorn-<your-domain>/gunicorn.socket;
	}
}

然后重启 nginx(sudo service nginx reload)。

现在 gunicorn 的启动方式需要换一换:

其中,应该先提前创建 sudo mkdir /run/gunicorn-<your-domain>/ 文件夹一下再运行。

$ cd <path>/<to>/django-proj/source
$ ../virtualenv/bin/gunicorn \
    --bind unix:/run/gunicorn-<your-domain>/gunicorn.socket \
    source.wsgi:application
...

现在因为使用了 UNIX 套接字,现在已经和 django 默认的 8000 端口无关了。
即,从 ngnix 的配置文件可以看出来它不再代理 8000 端口了。

其中, gunicorn-<your-domain>.socketgunicorn-<your-domain>.com 是为了一致性而命名的,实际上它可以起其它无含义的名称亦可,但是需要和下文的 systemd 的相关配置一致!

完整示例:

example.com 站点为例,一份完整的 /etc/nginx/sites-available/example.com 示例:

server {
    listen 11100;
    server_name example.com;
    
    location /static {
        alias /home/example_user/django-proj/static;
    }

    location / {
        proxy_set_header Host $host;
        proxy_pass http://unix:/run/gunicorn-example.com/gunicorn.socket;
    }
}

然后开启 django 项目 server 的服务:

$ cd /home/example_user/django-proj/source
$ ../virtualenv/bin/gunicorn \
    --bind unix:/run/gunicorn-example.com/gunicorn.socket \
    source.wsgi:application
...

在“用户”网络使用浏览器访问 http://example.com/ 测试(当然,真的访问 example.com 是得不到想要的结果的,example 的意思当然就是把它替换成真实的域名)。

2.5.5 总结

nginx 的配置先简单代理了 django 在本地运行的服务器(localhost:8000)。
然后为 nginx 增加了伺服静态文件的配置,这样可以完整代理通过 gunicorn 运行的本地服务器。
最后进一步修改了 nginx 文件,代理的服务器不再直接通过 django 的默认 port,而是 UNIX 套接字。


2.6. systemd

现在已经有了 Nginx 的配置文件,可以运行 Nginx 代理服务器。
为了使项目能够在服务器上自动“开机”运行,我们预期托管给 systemd。

为此我们还需要三个配置文件:

  1. tmpfiles.d 配置文件。
  2. 两个 systemd 配置文件。

其中 tmpfiles.d 负责管理本机该项目运行的服务的临时文件夹。
该文件夹下用来放置如 .pid 这样在软件运行时产生的文件;
还有上面配置 nginx 提到过的 .socket - 这个文件是 nginx <- 通信 -> wsgi(Gunicorn) 必须的,也是运行时产生。

systemd 的两个配置文件在系统启动时,systemd 进程会根据配置启动相关进程。

2.6.1 tmpfiles.d
d /run/gunicorn-<your-domain> 0755 nobody nobody -

将上面内容保存在 /etc/tmpfiles.d/gunicorn-<your-domain>.conf 文件中。
gunicorn-<your-domain>.conf 预期是不存在的,需要创建。

/run/gunicorn-<your-domain> 是指示由其管理的临时文件夹。当然,它的名称也是可以自己定义的。
但是需要和下面的 systemd 的配置文件中的内容保持一致。

gunicorn-<your-domain>.conf 文件名也是自己定义的,这里我仍然按照简单的显而易见的规则为其命名。

2.6.2 systemd

本段参考 Gunicorn 官方文档中 systemd 配置文件部分1

systemd 是个什么东东的参考:
The importance of Devuan
Linux:为什么那么多人讨厌systemd?
Systemd 入门教程:命令篇 (了解即可)
Node 应用的 Systemd 启动

2.6.2.1 gunicorn.socket

/etc/systemd/system/gunicorn-<your-domain>.socket

[Unit]
Description=<your-domain>'s gunicorn socket

[Socket]
ListenStream=/run/gunicorn-<your-domain>/gunicorn.socket

[Install]

WantedBy=sockets.target

2.6.2.2 gunicorn.service

/etc/systemd/system/gunicorn-<your-domain>.service

[Unit]
Description=gunicorn-<your-domain>'s gunicorn daemon
Requires=gunicorn-<your-domain>.socket
After=network.target

[Service]
PIDFil=/run/gunicorn-<your-domain>/pid
User=nobody
Group=nobody
RuntimeDirectory=gunicorn-<your-domain>
WorkingDirectory=/<USER>/django-proj/source/
ExecStart=/<USER>/django-proj/virtualenv/bin/gunicorn \
          --pid /run/gunicorn-<your-domain>/pid \
          --bind unix:/run/gunicorn-<your-domain>/gunicorn.socket \
          source.wsgi:application
ExecReload=/bin/kill -s HUP $MAINPID
ExecStop=/bin/kill -s TERM $MAINPID
PrivateTmp=true

[Install]
WantedBy=multi-user.target

其中:

  • line 15 是基于 WorkingDirectory 的路径;即 source.wsgi:application 是相对路径,完整路径是 /<USER>/django-proj/source/source.wsgi:application
  • line 7,13,14 的 /run/gunicorn-<your-domain>/ 文件夹基于上文的 tmpfiles.d 配置创建。
  • line 11 中,/<USER>/django-proj/ 是整个站点服务文件夹,自动化部署时,如果没有,则创建;其下的 source/ 是 Django 项目根目录。

    关于 source/ 这个根目录,它等效于当前处于 /<USER>/django-proj/ 目录下的时候,执行 django-admin startproject source 这一命令的效果。所以说 source/ 是 Django 项目(源代码)的根目录。而它的往上一级还有称为 django-proj/ 的目录是为了放置整个项目的其它文件,比如 Docs/ (还有显然后来创建的 virtualenv/ 文件夹)等等。

2.6.3 Systemd 下该 HTTP 服务的运行与测试

Enable

$ sudo systemctl enable /etc/systemd/system/gunicorn-<your-domain>.socket

Start

$ sudo systemctl start /etc/systemd/system/gunicorn-<your-domain>.socket

enable 只是在 *.socket 文件第一次存在在 ‘system/’ 文件夹下的时候运行。
之后重启整个 django web 服务器项目只需要使用:
sudo systemctl restart /etc/systemd/system/gunicorn-<your-domain>.socket 即可。

如果项目(软件)已经部署好了,则可以运行:

$ curl --unix-socket /run/gunicorn-<your-domain>/gunicorn.socket http

这样能够测试和启动 gunicorn 提供 http server 服务,配置运行正常的情况下,这里应该有 HTML 输出。

它可能是一个 HTTP 错误消息,这也是成功的表现。只要不是 curl 工具的错误提示!

用户环境(客户端)发起的请求,需要 Nginx 代理处理链接。

(逻辑是:nginx -交给-> unix socket -> gunicorn(wsgi) -> django url+view)

所以要从用户环境测试,则需要配置好 nginx,然后启动 nginx 就完成了(前面已经介绍过了)。

如果出现问题:

$ sudo systemctl list-socekts --all | grep gunicorn-<your-domain>.socket
$ sudo systemctl list-socekts | grep gunicorn-<your-domain>.socket

这个命令可以看出 systemctl enable 这一步有没有出问题。
systemctl start 这一步有问题的话会有提示。



3 自动化部署 - N/A



4 升级服务器上的 Django 项目 - n/a

这是在上面“首次部署”之后,已经部署在了服务器上之后。
现在要升级部署过的项目。



5 HTTPS on Nginx Proxy Django Server

这篇博文 ? 足够好,参考它完成使用 HTTPS。



Reference

  1. 《Python 测试驱动开发》
  2. How to Setup a SSL Certificate on Nginx for a Django Application



  1. Deploying Gunicorn > systemd ↩︎

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值