須要在阿里雲服務器部署Django-restframework框架,一開始不清楚狀況,網上找了不少的文章和辦法,東拼西湊也沒有可以徹底實現nginx和uwsgi的互通。html
參考過的文章有前端
-視頻:Nginx + uWsgi 部署 Django + Mezzanine 生產服務器python
-文章:uWSGI+django+nginx的工做原理流程與部署歷程mysql
-文章:uwsgi官方文檔linux
-文章:Django Nginx+uwsgi 安裝配置nginx
-文章:centos7 下經過nginx+uwsgi部署django應用 c++
由於是東拼西湊,因此不管是網上的文章仍是本身拼湊的配置,都是沒有辦法打通的。後來紅包求助,才瞭解到有這幾個地方:git
一、nginx執行權限sql
二、uwsgi配置數據庫
三、uwsgi設置虛擬環境
四、uwsgi安裝問題及插件安裝問題
五、django靜態文件收集處理
六、
因爲安全需求,仍是配置一個非管理員(本身操做,增長sudo受權)帳戶操做,經過命令建立用戶名密碼
adduser quinns # 新增用戶
passwd quinns # 爲quinns設置密碼
複製代碼
設置好以後,還須要開啓sudo權限,經過命令:
vi /etc/sudoers
複製代碼
而後找到有 root ALL=(ALL)那一行,而後在下面增長一行:
quinns ALL=(ALL) ALL
複製代碼
保存便可。
下面的操做,用新用戶quinns登陸來操做。
uwsgi和nginx以及anaconda的安裝會存在一些報錯問題,這裏爲了不出現這狀況,因此先安裝好依賴。
sudo yum install gcc-c++
sudo yum install wget openssl-devel bzip2-devel expat-devel gdbm-devel readline-devel sqlite-devel libxml* pcre-devel python-devel bzip2
複製代碼
經過quinns帳戶登陸,而後到quinns用戶目錄(/home/quinns)下新建一個utils目錄,把一些軟件下載在utils目錄下。
經過wget方式下載anaconda(官網)
wget https://repo.continuum.io/archive/Anaconda3-5.0.1-Linux-x86_64.sh
複製代碼
若是想更快,就安裝國內源(清華鏡像):
wget https://mirrors.tuna.tsinghua.edu.cn/anaconda/archive/Anaconda3-5.1.0-Linux-x86_64.sh
複製代碼
下載好以後sh安裝
sh Anaconda3-5.0.1-Linux-x86_64.sh
複製代碼
一路默認,到以後面安裝完的時候會提示是否添加環境變量,輸入yes便可。
若是想要後面使用更快,能夠更改倉庫鏡像(我沒試過):
conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/free/
conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/main/
conda config --set show_channel_urls yes
複製代碼
這樣的話安裝軟件都是國內源,速度比較快(據說是)
經過命令:
conda list
複製代碼
來驗證是否成功安裝並加入環境變量,若是出現list列表則表明成功,若是出現報錯提示信息則須要用命令:
source ~/.bashrc
複製代碼
來添加,而後重複conda list命令。若是仍是不行,則編輯/etc/profile文件,在底部添加環境變量及指向:
export PATH=/home/quinns/anaconda3/bin:$PATH
複製代碼
經過文件添加的環境變量需重啓服務器才能生效 sudo reboot
在確認安裝好anaconda以後,先不着急新建虛擬環境,直接在linux下輸入python,檢查默認python是否已自動替換爲python3.6。接着經過pip安裝uwsgi:
pip install uwsgi
複製代碼
若是不成功則嘗試使用aliyun的源 阿里雲的源我複製下來了,是:
http://mirrors.aliyun.com/pypi/packages/a2/c9/a2d5737f63cd9df4317a4acc15d1ddf4952e28398601d8d7d706c16381e0/uwsgi-2.0.17.1.tar.gz
複製代碼
待有安裝成功的提示出來,再經過命令:
uwsgi --version
複製代碼
來確認是否成功安裝。
經過anaconda來建立python虛擬環境:
conda create --name envname python=3.6.3
(親身經歷 3.6.5沒法啓動uwsgi,最好仍是3.6.3)
複製代碼
觀察過程,無報錯即完成安裝。
直接經過yum來安裝nginx便可,若是想安裝新版,能夠在網上尋找新方法。
sudo yum install nginx
複製代碼
若是是centos7 是默認沒有Nginx源的,須要給它添加源,才能使用Yum install 安裝
sudo rpm -Uvh http://nginx.org/packages/centos/7/noarch/RPMS/nginx-release-centos-7-0.el7.ngx.noarch.rpm
複製代碼
安裝完成後應該是自動啓動服務,在瀏覽器輸入ip便可訪問nginx的歡迎頁面。若是沒有,經過命令:
sudo service nginx start/restart
複製代碼
來啓動或者重啓nginx服務。
先下載mysql的repo源
wget http://repo.mysql.com/mysql-community-release-el7-5.noarch.rpm
複製代碼
接着安裝mysql-community-release-el7-5.noarch.rpm包
sudo rpm -ivh mysql-community-release-el7-5.noarch.rpm
複製代碼
安裝這個包後,會得到兩個mysql的yum repo源:/etc/yum.repos.d/mysql-community.repo,/etc/yum.repos.d/mysql-community-source.repo。
最後執行安裝
sudo yum install mysql-server
複製代碼
先受權
sudo chown -R root:root /var/lib/mysql
service mysqld restart # 而後重啓
複製代碼
接着重置密碼
mysql -u root //直接回車進入mysql控制檯
mysql > use mysql;
mysql > update user set password=password('quinns') where user='root';
mysql > exit;
service mysqld restart # 而後再重啓一次服務
複製代碼
重點:在實際的應用當中,咱們通常不推薦使用root帳戶,而是新增用戶並對其進行受權。
因此,這裏我要加上刪除線
mysql默認是不開啓遠程訪問的,想要在本地鏈接服務器的mysql,必須開啓:
mysql -u root -p
mysql> use mysql;
mysql> update user set host = '%' where user = 'root';
service mysqld restart # 這裏也要重啓一次服務
(過30秒或者1分鐘再測試遠程鏈接)若是不行的話,接着重啓服務一次。
CREATE USER 'username'@'host' IDENTIFIED BY 'password';
複製代碼
命令含義說明:
username:你將建立的用戶名
host:指定該用戶在哪一個主機上能夠登錄,若是是本地用戶可用localhost,若是想讓該用戶能夠從任意遠程主機登錄,可使用通配符%
password:該用戶的登錄密碼,密碼能夠爲空,若是爲空則該用戶能夠不須要密碼登錄服務器
複製代碼
好比這裏我能夠把命令改爲:
CREATE USER 'quinns'@'%' IDENTIFIED BY '123456';
複製代碼
意味着我新建了一個名爲quinns且密碼爲123456的用戶,並給它開啓了全部ip地址遠程鏈接(固然也能夠指定某個ip)
GRANT privileges ON databasename.tablename TO 'username'@'host'
複製代碼
命令含義說明:
privileges:用戶的操做權限,如SELECT,INSERT,UPDATE等,若是要授予全部則使用ALL
databasename:數據庫名
tablename:表名,若是要授予該用戶對全部數據庫和表的相應操做權限則可用*表示,如*.*
複製代碼
受權命令示例:
GRANT SELECT, INSERT ON test.user TO 'pig'@'%';
GRANT ALL ON *.* TO 'pig'@'%';
GRANT ALL ON maindataplus.* TO 'pig'@'%';
複製代碼
命令:
SET PASSWORD FOR 'username'@'host' = PASSWORD('newpassword');
複製代碼
若是是當前登錄用戶用:
SET PASSWORD = PASSWORD("newpassword");
複製代碼
例子:
SET PASSWORD FOR 'pig'@'%' = PASSWORD("123456");
複製代碼
命令:
REVOKE privilege ON databasename.tablename FROM 'username'@'host';
複製代碼
說明:
privilege, databasename, tablename:同受權部分
複製代碼
例子:
REVOKE SELECT ON *.* FROM 'pig'@'%';
複製代碼
注意:
假如你在給用戶'pig'@'%'受權的時候是這樣的(或相似的):GRANT SELECT ON test.user TO 'pig'@'%',則在使用REVOKE SELECT ON *.* FROM 'pig'@'%';命令並不能撤銷該用戶對test數據庫中user表的SELECT 操做。相反,若是受權使用的是GRANT SELECT ON *.* TO 'pig'@'%';則REVOKE SELECT ON test.user FROM 'pig'@'%';命令也不能撤銷該用戶對test數據庫中user表的Select權限。
複製代碼
具體信息能夠用命令
SHOW GRANTS FOR 'pig'@'%';
複製代碼
查看。
命令:
DROP USER 'username'@'host';
複製代碼
參考來源:傳送門
安裝好這些軟件後,須要確保獨立服務都是正常運行的。
在/home/quinns目錄下新建wwwroot目錄,而後在裏面新建一個測試文件uwsgitest.py
def application(env, start_response):
start_response('200 OK', [('Content-Type','text/html')])
return [b"Hello World, This uwsgi server is running"]
複製代碼
保存後經過命令來啓動
uwsgi --http :8000 --wsgi-file uwsgitest.py
複製代碼
看到服務啓動後,就能夠在瀏覽器訪問8080端口,若是可以正常顯示文字內容,則表明uwsgi單獨服務是能夠正常運行的。若是沒有,根據報錯找緣由。
能夠在本地,經過ssh對服務器進行鏈接,其中也包括上傳下載服務。
本地打開終端後輸入:
scp -r djangoName quinns@47.98.212.01:/home/quinns/wwwroot
複製代碼
將當前目錄的djangoName文件夾經過quinns帳戶上傳到/home/quinns/wwwroot目錄內。回車執行後輸入quinns的密碼便可看到上傳到指定的wwwroot目錄內。
本地開發環境下的django和服務器的設置有些許不同。
首先要開放ALLOWED_HOSTS,使得程序能夠遠程訪問,而後再設置靜態文件,最後再經過命令來測試是否能夠順利啓動。
找到django項目的settings.py文件,裏面有個ALLOWED_HOSTS,是接收一個空列表,如今要將服務器地址或者域名添加進去(也能夠放*號,表明全部均可以指向這裏,可是不推薦這麼作):
ALLOWED_HOSTS = ['47.98.209.107']
複製代碼
上面就算是開啓了遠程訪問,接着設置靜態(drf有一些樣式,若是不設置,經過uwsgi啓動是沒法加載的)。一樣是在settings.py文件中,下部分代碼中有個STATIC_URL = '/static/',在它下面新增一行:
STATIC_ROOT = os.path.join(BASE_DIR, "static/")
複製代碼
保存文件,而後在虛擬環境下執行命令:
python manage.py collectstatic
複製代碼
這樣django就會收集靜態文件,放到指定目錄內,也就是(static目錄內)
uwsgi能夠經過命令來啓動django項目,也能夠經過配置文件ini或者xml來啓動。這裏已ini爲例。
在項目根目錄(manage.py同目錄,其實哪一個目錄均可以,這裏是方便尋找)新建文件夾conf,而後再在conf下新建uwsgi文件夾(這倆文件夾什麼名字無所謂)。接着新建uwsgi的配置文件,這裏暫且叫作lagou_uwsgi.ini 裏面寫上uwsgi與項目的配置信息:
ite_uwsgi.ini file`
[uwsgi]
# Django-related settings
# the base directory (full path)
chdir = /home/quinns/wwwroot/GamesAPI
# Django's wsgi file
module = GamesAPI.wsgi
# the virtualenv (full path)
# process-related settings
# master
master = true
# maximum number of worker processes
processes = 4
threads = 2
# the socket (use the full path to be safe
socket = 127.0.0.1:8001
# ... with appropriate permissions - may be needed
# chmod-socket = 664
# clear environment on exit
vacuum = true
virtualenv = /home/quinns/anaconda3/envs/envgames
python-autoreload=1
logto = /home/quinns/wwwroot/GamesAPI/uwsgilog.log
stats = %(chdir)/conf/uwsgi/uwsgi.status
pidfile = %(chdir)/conf/uwsgi/uwsgi.pid
複製代碼
具體的含義在uwsgi文檔都有,這裏記錄一下:
chdir # 項目絕對路徑
module # 項目內的uwsgi.py文件,其實與項目同名便可
master
processes
threads
socket # 服務啓動地址及端口
vacuum
virtualenv # 這個就很重要了,python虛擬環境地址
python-autoreload=1 # python自啓動
logto # 自動生成日誌文件及存放路徑
stats
pidfile
複製代碼
這就算是編寫好uwsgi的配置文件了,接着編寫nginx的配置。
最好不要改動原有的ningx,來新建一個新的.conf配置文件吧。一樣在項目目錄的conf目錄內新建nginx文件夾,而後再在nginx文件夾裏新建lagou.conf配置文件,裏面寫上nginx的配置:
upstream games {
# server unix:///path/to/your/mysite/mysite.sock; # for a file socket
server 127.0.0.1:8001; # uwsgi的端口
}
# configuration of the server
error_log /home/quinns/wwwroot/nginxerror.log;#錯誤日誌
server {
# the port your site will be served on
listen 8080;
# 端口
server_name 47.98.209.107 ; # 服務器ip或者域名
charset utf-8;
# max upload size
client_max_body_size 75M; # adjust to taste
# Django media
location /media {
alias /home/quinns/wwwroot/GamesAPI/media; # 指向django的media目錄
}
# Django static
location /static {
alias /home/quinns/wwwroot/GamesAPI/static; # 指向django的static目錄
}
# Finally, send all non-media requests to the Django server.
location / {
uwsgi_pass games;
include uwsgi_params; # uwsgi服務
}
}
複製代碼
裏面都有說明了,我就不寫了。其的upstream games中的games是自定義名稱,可是要與下面的uwsgi_pass games中games名稱相同。
注意: .conf文件創建好後,要與讓nginx知道並認可,因此須要經過軟鏈接來連接到/etc/nginx/conf.d/目錄下,若是不知道軟鏈接怎麼作,能夠把這個文件copy到這個目錄下。
而後重啓服務器
sudo service nginx restart
複製代碼
有些版本的命令是:
sudo systemctl restart nginx.service
複製代碼
若是沒有報錯,應該就是能夠了。
若是有報錯,沒有重啓ng服務器,那確定是配置文件寫錯了,得去看一下。
既然uwsgi也配置好了,django項目的虛擬環境也pip install -r requirements.txt過了,ng的配置文件也寫好了。那就能夠啓動服務了。
經過linux命令來進行啓停
sudo service nginx restart/start/stop
複製代碼
若是以前啓動過,就不用重啓了。
找到剛纔編寫的lagou_uwsgi.ini配置文件目錄,經過命令來啓動:
uwsgi -i lagou_uwsgi.ini &
複製代碼
若是沒有報錯,就表明啓動了。就能夠在瀏覽器訪問以前.conf配置文件配置的8080端口了。
後期部署發現,不一樣版本的Centos對權限的設定是不同的。
好比:
不能在自定義的nginx.conf文件中填寫erro_log的配置
須要在/etc/nginx/nginx.conf裏面將user改爲root
若是發現502 bad getway,就須要查看uwsgi日誌和nginx日誌,若是在nginx日誌(默認/var/log/nginx/error.log)看到以下提示
2018/08/19 21:06:37 [crit] 967#967: *1 connect() to 127.0.0.1:8001 failed (13: Permission denied) while connecting to upstream, client: 192.168.0.103, server: 192.168.0.61, request: "GET / HTTP/1.1", upstream: "uwsgi://127.0.0.1:8001", host: "192.168.0.61:8080"
複製代碼
就表明是權限方面的問題,通過網上文章搜索,找到緣由SeLinux的致使的。
解決辦法有兩種,比較直接的是運行命令:
setsebool -P httpd_can_network_connect 1
複製代碼
後來又產生新的問題,Django的靜態文件沒法正常加載,nginx返回的是403.
解決這種問題的辦法是經過配置文件,長期關閉SeLinux,怎麼關:《煩人的linux權限問題-SeLinux》
後端api沒有問題後,前端也要部署。
前端經過npm run build打包以後,將build文件經過ssh上傳到wwwroot目錄下:
scp -r build quinns@xx.xx.xx.xx:/home/quinns/wwwroot
複製代碼
等到上傳完成後,就到nginx那裏進行靜態的部屬配置
cd /etc/nginx
複製代碼
而後打開nginx.conf文件進行編輯。
首先要給nginx文件進行訪問受權,不然有些目錄是會報錯403的。其配置文件中有:
user nginx;
複製代碼
這裏得給他改爲用戶的權限,如quinns或者root
user quinns;
複製代碼
看到server部分的代碼:
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name _;
root /usr/share/nginx/html;
# Load configuration files for the default server block.
include /etc/nginx/default.d/*.conf;
location / {
# 配置這個,才能正確跳轉路由,如47.98.110.67/detail/1
add_header Cache-Control "no-cache, no-store";
index index.html;
try_files $uri /index.html;
}
……
……
}
複製代碼
是這樣的,訪問網址80端口默認指向/usr/share/nginx/html目錄下的index.html
由於靜態打包後build也是由index.html來做爲主入口的。因此這裏只須要把root的指向改過來便可:
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name _;
#root /usr/share/nginx/html;
root /home/quinns/wwwroot/build;
# Load configuration files for the default server block.
include /etc/nginx/default.d/*.conf;
location / {
# 配置這個,才能正確跳轉路由,如47.98.110.67/detail/1
add_header Cache-Control "no-cache, no-store";
index index.html;
try_files $uri /index.html;
}
……
……
}
複製代碼
將原來的root指向註釋掉,增長build文件夾的指向
而後重啓nginx服務,打開瀏覽器訪問,就能夠看正常的頁面了。
心中一陣竊喜,這個坑終因而填上了。