欢迎来我的个人网站查看原文
以下所有内容都假设你已经配置好了pip和virtualenv虚拟环境,不是的话可以运行如下指令
# install pip
sudo apt-get install python3-pip
# install virtualenv
sudo pip3 install virtualenv
# create virtual environment
python3 -m virtualenv venv
# activate
source venv/bin/activate
参考: https://www.digitalocean.com/community/tutorials/how-to-install-mysql-on-ubuntu-20-04
# update the package
sudo apt update
# install MySQL
sudo apt install mysql-server
# config the MySQL e.g. set the password of root user (important!)
sudo mysql_secure_installation
为了安全起见,我们应该给每一个应用程序创建一个独立的数据库账号,并且限制该账号只能操作对应的数据库(权限管理)。这样主要是为了防止由于一个应用程序的漏洞导致黑客可以访问所有的数据。
# login to mysql as root
sudo mysql
# if you want remote connection, set host to '%'
CREATE USER '' @'' IDENTIFIED BY '' ;
# (optional) create a new DB for Django
CREATE DATABASE <name>;
# grant all privileges to all tables in database
GRANT ALL PRIVILEGES ON <name>.* TO '' @'' ;
# update
FLUSH PRIVILEGES;
exit
为了测试是否创建成功,我们可以
# start the server
systemctl status mysql.service
# check user creation
# method 1
sudo mysqladmin -p -u <username> version
# method 2
mysql -u <username> -p
use <name of database>;
有时候我们希望能远程连接到数据库上面(如:本地运行程序,使用服务器上面的数据)
参考: https://www.digitalocean.com/community/tutorials/how-to-allow-remote-access-to-mysql
sudo emacs /etc/mysql/mysql.conf.d/mysqld.cnf
bind-address
from 127.0.0.1
to 0.0.0.0
mysql -u -h -p
Nginx是用于反向代理的,可以加快我们网站的访问速度,一些静态资源的重复请求Nginx就可以处理而不需要发到后端程序重复处理,比如用户A访问了图片1,这时候假如用户B也要访问图片1,那么Nginx就会直接返回图片1而不会向后端再请求一次。
基本的安装和启动语法如下:
# install nginx
sudo apt-get install nginx
# start the nginx
sudo service nginx start
# reload/restart nginx (after modified the config)
sudo service nginx reload # only reload the config
# or
sudo service nginx restart # restart the nginx
# test nginx.conf syntax
nginx -t
进入/etc/nginx/sites-available
创建一个新的文件(如:blog.config
,后缀不重要,没有后缀也可以),写入如下内容(将所有<>
中的内容换为你的实际路径)
http访问
server {
charset utf-8;
# listen on port 80
listen 80;
server_name ;
location /static {
# e.g. /home/user1/blog/blog
alias /staticfiles;
}
location /media {
alias /media;
}
location / {
proxy_set_header Host $host;
# proxy_pass http://unix:/tmp/.socket;
# redirect URL (the URL django is listening to)
proxy_pass http://127.0.0.1:8000;
}
}
现在很多网站都支持HTTPS访问,假如希望开启https并将所有http的重定向到https的话可以这样写:
https访问
server {
listen 80;
server_name ;
# rewrite the URL to https
rewrite ^(.*)$ https://${server_name}$1 permanent;
}
server {
charset utf-8;
listen 443 ssl;
server_name xiakewei.com;
# usually we can put them in '/etc/ssl'
ssl_certificate <.crt文件路径>;
ssl_certificate_key <.key文件路径>;
location /static {
alias /staticfiles;
}
location /media {
alias /media;
}
location / {
proxy_set_header X-Forwarded-Proto https;
proxy_set_header Host $host;
# proxy_pass http://unix:/tmp/.socket;
proxy_pass http://127.0.0.1:8000;
}
}
链接该文件到/etc/nginx/sites-enabled
cd /etc/nginx/sites-enabled
sudo ln -s ../sites-available/blog.config .
可以顺便删掉default
文件(注意reload一下Nginx使得修改被应用)
如果你需要多个config(如:服务器上运行了多个Web程序),你可以为每个程序创建一个config文件(注意端口不要冲突),然后都链接到/etc/nginx/sites-enabled
里面。
找到
文件,修改以下内容:
# 禁用DEBUG模式
#(不然出错的时候会显示详细的错误信息,给黑客提供了额外信息)
DEBUG = False
# 将服务器的地址放到允许列表里面
ALLOWED_HOSTS = ['' ]
# Django会将所有的静态文件(如css,图片)统一放置到这个路径下面(Nginx访问的也是这个路径)
STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles')
# 配置HTTPs访问
SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')
SECURE_SSL_REDIRECT = True
SESSION_COOKIE_SECURE = True
CSRF_COOKIE_SECURE = True
CSRF_TRUSTED_ORIGINS = ['' ]
SECURE_HSTS_SECONDS = 31536000
SECURE_HSTS_INCLUDE_SUBDOMAINS = True
SECURE_HSTS_PRELOAD = True
注:我们项目中有很多静态文件(如:css, js…)分布在不同的APP里面,部署时需要找一个地方统一收集起来,这就是STATIC_ROOT
的作用(注意STATIC_ROOT
不能和STATIC_DIR
重复,DIR只是开发时候用的静态文件储存位置)
python3 manage.py collectstatic
运行该指令,Django会将所有app里面的静态文件统一放置到STATIC_ROOT
里面,这样Nginx就可以到一个统一的地方访问这些内容。
这里主要是针对数据库的修改,假如你修改了任何models.py
文件(数据库模型文件),那么就需要在部署之前运行以下指令来应用你的修改。
python3 manage.py makemigrations
# if no change detected, used
python3 manage.py makemigrations <app name>
python3 manage.py migrate
Gunicorn用于运行我们的Django程序
# install
pip3 install gunicorn
# run program
gunicorn -D -w 4 --bind unix:/tmp/<IP>.socket <prj name>.wsgi:application
# or
gunicorn -D -w 4 --bind localhost:8000 <prj name>.wsgi:application
可用该指令查看运行情况 — pstree -ap|grep gunicorn
至此,大功告成!Django已经欢快的跑起来了。
部署并不是一劳永逸,有时候我们发现了bug,修改完代码之后又要重启一下程序,大致步骤如下
# switch to project directory
cd <your project DIR>
# activate the virtual environment
source venv/bin/activate
# pull the latest code
git pull
# re-collect the static files
python3 manage.py collectstatic
python3 manage.py migrate
# kill & reboot gunicorn
pkill gunicorn
gunicorn -D -w 4 --bind localhost:8000 <prj name>.wsgi:application
要是觉得每次都要输入这几条指令很麻烦,可以把他们放到一个文件里面re-deploy.sh
(脚本相关内容可查看我的另一篇文章:Bash脚本入门),然后每次只需要运行一下就可以实现一键部署了。
注意pkill
会把gunicorn整个程序都杀掉,在只部署了一个程序的时候这种方式最方便,但是假如部署了多个程序,一次性全部杀掉肯定是不合理的,这时候我们可以使用下面这条指令(将
替换为你的程序名字):
# check the PID
pid=$(pstree -ap | grep -P ".*gunicorn.*.*" | head -n 1 | perl -ne '/.*,\s*(\d*)\s*.*/ and print "$1"')
# kill priginal process
kill $pid
首先获取对应程序的进程号,然后杀掉对应的进程。
一些很常见的需求:
为了实现这些定时需求,就需要引入一个新的软件Cron
,该软件是一个time-based job scheduling daemon
,专门用于这类定时任务的需求。
sudo apt update
sudo apt install cron
sudo systemctl enable cron
# edit the crontab config
crontab -e
# list the config
crontab -l
# remove the config
crontab -r
# see log
grep CRON /var/log/syslog
# change default shell to bash (default is sh)
SHELL=/bin/bash
# "At 01:00 on every day-of-week from Tuesday through Saturday."
0 1 * * 2-6 <your command>
# "At 02:30 on Saturday."
30 2 * * 6 <your command>
# e.g. echo "$(date) --- Hello" >> $HOME/out.log
注意这里的command假如你使用的是你自己编写的shell script,一定要放绝对路径 (e.g. $HOME/scripts/myscript.sh
)。还有就是假如你的脚本里面用到了一些环境变量,最好在脚本的开头增加一句source "$HOME/.profile" || exit
,因为crontab的运行环境里面只有最基础的一些简单变量(如$HOME
),所以最好重新添加一下。
注:cron/crontab表达式比较晦涩难懂,可以直接上网搜索"cron表达式生成",有很多网站有相关的功能。