CentOS 7中使用Apache + mod_wsgi部署Django項目
我在把博客部署到伺服器上時,本以為網上教程那麼多,跟著來就行,但到頭來還是踩了不少坑。一方面是軟體版本更新迭代較快,有的教程已經不適用了,另一方面是由於剛接觸時分不清不同環境間的區別,導致參考了錯誤的部署方法。這篇文章中,我會記錄下部署網站的過程,以及碰到的坑。另外,歡迎來我的博客轉轉https://www.fossen.cn。
一、 部署前的準備
伺服器和域名是搭建網站的必需品。我買的阿里雲伺服器,學生價118一年,真的很便宜。阿里雲有關伺服器的購買以及登錄的文檔非常詳細,還有不少免費的視頻教程,這裡就不贅述了。
關於域名,如果你只是想學習web開發,並不打算正式運營網站,則完全可以不購買域名,使用ip地址就可以部署網站並且瀏覽網站。但如果你是打算正式開辦一個網站,我建議域名應該早一點購買,因為要通過域名瀏覽網站必須在工信部備案,備案可能要花費半個月到一個月的時間,你可以利用這段時間完成網站的部署與測試。
在正式介紹部署過程之前,先列出部署過程中用到的主要工具:
- 伺服器系統CentOS 7
- Python 3.6
- Apache (httpd 2.4)
- mod_wsgi 3.4或4.5.24
- mariadb 5.5 (MySQL)
- Django 2.0.1
下面將正式介紹如何部署django項目,這裡我假設你具備Linux的基本知識。
首先,使用putty登錄遠程主機,最好用有sudo許可權的非root用戶登錄,然後開始部署網站。
二、安裝python
雖然我的伺服器系統自帶python2,但我是在python3下開發的django,所以還是得再安裝一個python3。由於python2與3可以共存,所以不需要刪除原裝的python2。而且最好不要刪除python2,因為有的程序依賴python2,比如yum。
我當時安裝python3時上網搜到的教程都是源碼編譯的,受此誤導,以為不能yum安裝python3,後來才發現可以yum。於是當時傻乎乎的去源碼編譯安裝python3,中間踩了很多坑,基本都是依賴不全造成的。所以極其不建議初學者源碼編譯,用yum可以省很多事。
最方便且安全的安裝方法就是用yum,這會自動安裝所有的依賴(yum是Cent OS中常用的軟體包管理軟體,地位類似於python中的pip,其他系統如Ubuntu則是apt):
$ sudo yum install python36 python36-devel
但是我的yum源只能獲取python3.6.3,目前最新的版本是3.6.4,如果非要用最新版的Python就只能源碼編譯了,方法我會寫在另一篇文章中,感興趣的可以看看Linux下源碼編譯安裝Python3。
安裝完以後輸入python3
即可進入python3解釋器,你還可以輸入python
或python2
進入python2解釋器,二者可以共存。
注意!有的網上教程可能會讓你更改軟鏈python連接到python3,這樣做的好處僅僅是在打開python解釋器時可以直接用python
指令,但是這樣做的代價則是其他依賴python2的程序可能會因此崩潰。除非你知道自己在做什麼,否則不要動原來的python軟鏈,使用python3
指令進入解釋器比較安全。
三、安裝Apache並配置mod_wsgi
先安裝Apache(其軟體名叫做httpd),並確保開發包也一併安裝了
$ sudo yum install httpd httpd-devel
安裝好後啟動Apache
$ apachectl start
然後在web瀏覽器輸入你的伺服器ip,如果能看見測試頁面則表示Apache運行成功。
mod_wsgi也可以yum安裝,但是其版本可能已經過時,在我的yum源中只有3.4,而當時最新版已經到了4.5.24(現在有更新的版本)。如果想使用最新版的mod_wsgi,建議編譯源碼安裝。幸運的是mod_wsgi官方文檔的安裝教程很詳細。
先下載源碼,下載的位置為當前文件夾,下載完成後解壓
$ wget https://github.com/GrahamDumpleton/mod_wsgi/archive/4.5.24.tar.gz$ tar xvfz mod_wsgi-4.5.24.tar.gz
然後配置時,用–with-python選項指定python可執行文件的位置,
$ ./configure –with-python=/usr/local/python3/bin/python
如果不指定程序會也自動檢索python的位置,但由於我的伺服器上同時有python2和3,並且python軟鏈指向的是python2,所以默認mod_wsgi會找到python2,那麼Apache在運行時打開的也會是python2。為了讓mod_wsgi正確的找到python3,所以要用–with-python選項。即使不用這一項也沒事,後面用Apache配置django項目時還可以通過WSGIPythonHome指令另外指定Python的路徑。
另外還有一個—with-apxs選項用來指定Apache構建工具apxs的位置,如果安裝出錯,提示找不到apxs,那麼就要確保安裝了apxs,並用這個選項指定其位置。
下一步就是構建編譯
$ sudo make$ sudo make install
如果源碼編譯安裝的過程中出錯了,產生的錯誤大部分都是依賴不全造成的,仔細查看錯誤信息中的提示,安裝相關依賴即可。最好是在安裝前就確保相關的依賴都有,可以用yum deplist mod_wsgi
來查看所有的依賴。
mod_wsgi安裝完成後,還需要在Apache中載入該模塊,修改Apache的配置文件(你的配置文件位置可能跟我的不太一樣)。
$ sudo vim /etc/httpd/conf/httpd.conf
然後在文件中加入下面一行,最後的選項是mod_wsgi.so的位置。
LoadModule wsgi_module /usr/lib64/httpd/modules/mod_wsgi.so
改完以後重啟Apache使配置生效。
$ apachectl restart
成功的話在瀏覽器訪問伺服器id可以看到測試頁。如果啟動失敗,查看錯誤日誌,其位置在配置文件里能夠找到。根據提示找出錯誤原因,mod_wsgi的官方文檔中也列出了常見的bug。
$ sudo vim /var/log/httpd/error_log
例如,我在配置mod_wsgi的時候碰到了一個由python引起的錯誤,打開錯誤日誌,裡面的關鍵信息如下:
error while loading shared libraries: libpython3.6.4.so.1.0: cannot open shared object file: No such file or directory
出現找不到libpython3.6m.so.1.0文件(如果是不同版本的python則後綴代號不同)的錯誤,可能的原因有兩種,一是有該文件但是不在Apache的工作目錄下,二是沒有這個文件。
用find / -name libpython3.6m.so.1.0
命令找到該文件,並連接到mod_wsgi.so所在的庫文件夾即可,一般會在/usr/lib或/usr/lib64中。例如我的文件路徑分別為,/usr/lib64/httpd/modules/mod_wsgi.so和/usr/local/python3/lib/libpython3.6m.so.1.0,即把libpython3.6m.so.1.0鏈接到/usr/lib64中即可。
如果你是源碼編譯的python,而且找不到libpython3.6m.so.1.0文件,那麼可能是在配置項時沒有加--enable-shared ,則需要重新編譯python。
$ ./configure --enable-shared
四、安裝mariadb(MySQL)
我使用資料庫的是MySQL,雖然在CentOS 7上不支持MySQL,但是用mariadb可以完全代替MySQL。直接用yum安裝就行,別忘了開發包mariadb-devel:
$ sudo yum install mariadb mariadb-server mariadb-devel
相關命令:
$ sudo systemctl start mariadb #啟動mariadb$ sudo systemctl stop mariadb #停止mariadb$ sudo systemctl restart mariadb #重啟mariadb$ sudo systemctl enable mariadb #設置開機自啟$ mysql_secure_installation #初始化,首次啟動db時需要$ mysql -u root –p #登錄mariadb
安裝後設置root密碼,之後使用就跟MySQL完全一樣了,跟django也是兼容的,資料庫的操作就不贅述了。有關django和資料庫連接的方法請參考django的官方文檔MySQL notes。
五、部署Django項目
安裝django,由於pip默認是安裝python2的庫,要安裝python3的庫得用pip3。我用的MySQL還需要安裝python的資料庫API驅動mysqlclient。
$ sudo pip3 install django mysqlclient
安裝好後部署代碼,先將本地項目代碼上傳至GitHub,項目中有些文件務必不要加入git倉庫,可以在.gitignore中定義這些文件。比如*.pyc和migrations文件夾下的文件,這些是自動產生的,不需要上傳;保存了敏感信息的settings.py也不應該上傳,並且這樣可以讓你開發環境和生產環境下使用不同的配置,比如DEBUG和ALLOWED_HOSTS選項;還有media文件夾一般存放用戶上傳的文件,開發環境下的文件和生產環境中的文件會有衝突,不能加入git倉庫。一些如css、js或背景圖片之類的網站前端所必要的文件,應該放在static文件夾中,這些則應該加入git。
項目代碼上傳至GitHub後,在伺服器上用git複製項目代碼,複製的代碼會保存在當前文件夾下,建議保存在登錄用戶的主目錄下。
$ cd /usr/fossen/website$ sudo git clone [url]
其中url要替換成遠程倉庫地址,/usr/fossen/website則是我的項目文件夾要存放位置。以後如果需要更新代碼,只需要將開發機器上的代碼push至GitHub,然後在伺服器上sudo git pull就行。
然後進入項目文件夾,我在GitHub上的項目名是fossensite,亦即文件夾名。由於setting.py沒有加入git,需要我們手動創建,用vim打開,將本地項目中setting.py的代碼複製進去,修改ALLOWED_HOSTS和DATABASES等需要修改的選項。編輯完畢後記得保存。
$ cd fossensite$ sudo vim fossensite/settings.py
然後遷移資料庫,確保在setting中註冊了相應的INSTALLED_APPS。日後更新代碼,也應在需要時修改setting.py以及遷移資料庫。
$ python3 manage.py makemigrations$ python3 manage.py migrate
接下來要修改Apache配置文件,這裡可以參考Django官方文檔How to use Django with Apache and mod_wsgi。
WSGIScriptAlias / /usr/fossen/website/fossensite/fossensite /wsgi.pyWSGIPythonHome /path/to/pythonWSGIPythonPath /usr/fossen/website/fossensite <Directory /usr/fossen/website/fossensite/fossensite ><Files wsgi.py>Require all granted</Files></Directory>
WSGIScriptAlias右邊第一項是網址url,第二項是項目中wsgi文件存放的位置,這一行表示該url開頭的所有http請求都交給wsgi.py處理,即交給django項目處理。
WSGIPythonHome指定python的安裝位置,需要指向不同的版本的python時可用。如果之前編譯mod_wsgi時指定默認使用的python版本是自己想運行的版本,則不用這一條指令。
WSGIPythonPath確保django項目可以正確導入至python解釋器中。
Directory則是為了確保Apache有許可權訪問wsgi.py文件。
另外,同樣也是為了確保Apache有許可權訪問django項目下所有的文件,還需要讓Apache以特定用戶的身份運行。如果Apache無許可權訪問django項目的文件,伺服器會返回403頁面。對Apache配置文件進行如下修改:
User fossenGroup fossen
我在伺服器上的用戶名叫fossen,django項目也是放在fossen的主目錄/usr/fossen下,只有讓Apache以fossen的身份運行,它才有許可權訪問django項目下的文件。或者你也可以將項目代碼放在apache擁有許可權的目錄下,因為apache默認以apache用戶身份運行。
完成上述操作後,重啟Apache,再從瀏覽器中用ip訪問伺服器,這時如果返回了django項目的主頁,則項目部署成功。
推薦閱讀:
※php-cgi和php-fpm有什麼關係?
※PHP寫的API如何防止拒絕服務攻擊?
※Linux-CentOs7-Apache安裝
※Apache 流框架 Flink,Spark Streaming,Storm對比分析(二)
※並發的HTTP請求,apache是如何響應的,以及如何調用php文件的?