Django是一个基于Python的开源网络框架,于2005年公布1.0版本,目前被Django Software Fundation维护。截稿前的Stable版本是3.0.8。Django遵从MVC架构模式,在我们开发的过程中,需要在models.py文件内定义我们的模型,在views.py中定义我们针对每一个HTTP/HTTPS请求所要执行的任务。
举个例子来说,当前端通过GET HTTP://yoursite.com/login/这个URL访问我们的服务器,Django会自动调用views.py文件中,绑定了/login/这个URL的函数或者是方法,再将返回值返回给前端。如果只是单纯的使用Django进行开发的话,最终返回的一般会是一个由django渲染好的html文件,也就是我们平常所见的网页。
但是,现在更多的是前后端分离的项目,前端通过调用API与后端进行数据的传输,在这种情况下,我们就不需要Django来渲染页面,而只是需要后端返回一个json格式的文件。
对于以上的问题,我们可以使用Django REST Framework来提高我们的开发效率。具体的的使用方法,我会在后面的blog中为大家提供。
Vue.js是由华裔工程师尤雨溪开发并维护的渐进式JavaScript前端框架。与2014年发布初始版本。适用于SPA(Single Page Application)开发。Vue.js所关注的,就是MVC架构模式中的View(视图)层。作为前端框架,它可以很方便的通过axios与后端进行数据通信,并根据其遵从的MVVM架构模式,低延迟的将数据渲染到页面上。
@vue/cli脚手架工具使得vue的开发工作变得更加便捷,这也是现在主流前端的开发方法。
Gunicorn (Green Unicorn) 是一个Python 的 WSGI (Web Server Gateway Interface) HTTP server。可以用来代理基于python的Web应用程序。在我们的实例中,我们使用Gunicorn代理Django Web Application到Unix Socket,再使用Nginx将与gunicorn绑定的socket代理到我们的域名或者IP地址上。
Nginx (Engine X) 是由俄罗斯开发团队开发并维护的异步框架的网站服务器,也可以用作反向代理,负载均衡和HTTP缓存等任务。在我们的例子中,我们主要使用的是其反向代理的功能,将与gunicorn绑定的socket代理到我们的域名或者IP地址上。
首先需要更新系统内的包:
$ sudo apt update $ sudo apt upgrade忽略这一步可能会导致环境安装失败。
检查 nginx 是否安装成功:
$ which nginx这里我们默认 project/settings.py中的 STATICFILES_DIRS, STATIC_ROOT, MEDIA_URL, 以及MEDIA_ROOT 已经设置好。前两项为必须设置,后两项只有在项目有传输图片或者视频等功能的时候才需要配置。 我们同样默认项目的结构如下:
project/ ├── db.sqlite3 ├── frontend │ ├── README.md │ ├── axios.js │ ├── babel.config.js │ ├── dist │ ├── node_modules │ ├── package-lock.json │ ├── package.json │ ├── public │ ├── src │ └── vue.config.js ├── manage.py ├── app1 │ ├── __init__.py │ ├── __pycache__ │ ├── admin.py │ ├── apps.py │ ├── models.py │ ├── tests.py │ ├── urls.py │ └── views.py ├── media ├── requirements.txt └── project ├── __init__.py ├── __pycache__ ├── app.yaml ├── asgi.py ├── settings.py ├── urls.py └── wsgi.py其中 /project/project/是我们配置项目的APP, /project/app1/是我们的后端程序,/project/frontend/是我们的前端服务器程序。我们默认使用nodejs完成前端工作. 在我们的例子中,/project/project/settings.py里的STATIC_ROOT指向frontend/dist/。
由于我们使用Nginx来部署我们的项目,所有的静态文件(static files)都会被Nginx分发。
$ python manage.py collectstatic You have requested to collect static files at the destination location as specified in your settings: /path/to/your/dist This will overwrite existing files! Are you sure you want to do this? Type 'yes' to continue, or 'no' to cancel: yes x static files copied to '/path/to/your/dist', y unmodified.在新建的文件里写入:
[Unit] Description=gunicorn socket [Socket] ListenStream=/run/gunicorn.sock [Install] WantedBy=sockets.target其中 [Unit] section 描述我们新建的socket, [Socket] section 定义了我们未来socket文件要存储的位置,而[Install] section确定了 socket 文件会在正确的时间被创建
由于我们需要gunicorn以一个service的形式来传递数据,我们需要新建一个gunicorn.service文件
$ sudo vim /etc/systemd/system/gunicorn.service在新建的文件里写入:
[Unit] Description=gunicorn daemon Requires=gunicorn.socket After=network.target [Service] # 这里的 user 需要被替换成已存在的用户,如果用户不存在的话会导致Gunicorn启动失败 User=user Group=www-data WorkingDirectory=/home/user/path/to/project ExecStart=/home/user/myenv/bin/gunicorn \ --access-logfile - \ --workers 3 \ --bind unix:/run/gunicorn.sock \ myproject.wsgi:application [Install] WantedBy=multi-user.target我们现在可以启动刚刚创建好的 gunicorn.socket,注意是 .socket 而不是 .service。这会自动在/run/文件夹下创建一个gunicorn.sock 文件。当有对该socket连接是,systemd会自动启动 gunicorn.service来处理该连接。
$ sudo systemctl start gunicorn.socket $ sudo systemctl enable gunicorn.socket首先检查gunicorn.socket的运行状态
$ sudo systemctl status gunicorn.socket ● gunicorn.socket - gunicorn socket Loaded: loaded (/etc/systemd/system/gunicorn.socket; enabled; vendor preset: enabled) Active: active (running) since Fri 2020-06-26 01:51:15 UTC; 16h ago Listen: /run/gunicorn.sock (Stream) Tasks: 0 (limit: 4373) Memory: 0B CGroup: /system.slice/gunicorn.socket Jun 26 01:51:15 dev-1 systemd[1]: Listening on gunicorn socket.接下来检查 gunicorn.sock文件是否存在
$ file /run/gunicorn.sock /run/gunicorn.sock: socket现在我们只是启动了gunicorn.socket,而没有启动gunicorn.service。这是因为gunicorn.socket还没有收到任何连接。我们可以通过以下命令去检查gunicorn.service 的运行状态:
$ sudo systemctl status gunicorn Output● gunicorn.service - gunicorn daemon Loaded: loaded (/etc/systemd/system/gunicorn.service; disabled; vendor preset: enabled) Active: inactive (dead)为了激活gunicorn.service,我们可以调用 curl 命令:
$ curl --unix-socket /run/gunicorn.sock localhost之后,再输入上述命令来检查gunicorn.service是否被激活。 如果在gunicorn.service已经启动之后,修改了/etc/systemd/system/gunicorn.service文件,则需要运行以下命令来重启服务
$ sudo systemctl daemon-reload $ sudo systemctl restart gunicorn现在项目本身和gunicorn已经配置完成,剩下的就是 Nginx了。 首先,我们需要到 /etc/nginx/sites-available/这个文件夹内,并创建一个配置文件
$ cd /etc/nginx/sites-available $ sudo vim myproject_conf在新建的文件内写入:
upstream your-gunicorn { server unix:/run/gunicorn.sock; } # 这一项只有你需要使用HTTPS only的情况下才需要添加 # 监听80端口,并将其301 permenantly redirect 到https协议的地址 server { listen 80 default_server; server_name _; return 301 https://$host$request_uri; } server { # Nginx 监听的端口,如果是http:// 则监听80,https:// 则监听443 listen 80; # 输入ip地址和/或域名,用空格分开。如果需要用https,则必须要有域名 server_name 0.0.0.0 example.com; # 指向项目的根目录 root /root/of/your/project; # 以下3项配置只有需要用到https协议的时候才是必须的。其中ssl_sertificate和ssl_certificate_key可以由certbot自动填充 ssl on; ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem; # managed by Certbot ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem; # managed by Certbot location = /favicon.ico { access_log off; log_not_found off; } # 分发静态文件 location /static/ { autoindex on; alias /your/static/root/in/settings/py; expires 1M; access_log off; add_header Cache-Control "public"; proxy_ignore_headers "Set-Cookie"; } # 分发媒体文件 location /media/ { autoindex on; alias /your/media/root/in/settings/py; } location @proxy_to_app { proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header Host $http_host; proxy_redirect off; proxy_pass http://your-gunicorn; } location / { try_files $uri @proxy_to_app; } }写入完成后,需要link到sites-enabled/内。保险起见,我们先将sites-enabled/内与新建配置文件重名的文件都删掉:
$ sudo rm /etc/nginx/sites-enabled/myproject_conf之后再link:
$ sudo ln -s /etc/nginx/sites-available/myproject_conf /etc/nginx/sites-enabled/检查一下配置语法是否有误:
$ sudo nginx -t如果没有错误的话直接重启 Nginx 即可:
$ sudo systemctl restart nginx大功告成!
我们可以通过 Let’s Encrypt 申请一个免费的证书。但前提是我们需要有一个自己的域名。在我们的例子中,我们的网站运行在Nginx,使用Debian 10(buster)主机。
安装 Certbot $ sudo apt-get install certbot python-certbot-nginx选择如何运行
2.1 允许certbot修改我们的config文件 $ sudo certbot --nginx
2.2 只得到证书,之后手动配置 $ sudo certbot certonly --nginx
测试自动renew
$ sudo certbot renew --dry-run之后如果在我们的config文件内看到有certbot修改过的痕迹,就说明证书安装成功了。
[1] https://www.digitalocean.com/community/tutorials/how-to-set-up-django-with-postgres-nginx-and-gunicorn-on-debian-9#checking-for-the-gunicorn-socket-file
[2] https://uwsgi-docs.readthedocs.io/en/latest/tutorials/Django_and_nginx.html
[3] https://certbot.eff.org/lets-encrypt/debianbuster-nginx
