原文地址css
最近在學習 python,使用 flask 實現了個我的博客程序,完了想部署到服務器上。由於是新手,一路磕磕絆絆最終把它基本搞定。網上資料對新手感受都不太友好,都是零零碎碎的,因此我整理了一下,一方面做爲我本身的記錄,方便之後查閱,另外一方面也但願能幫助到跟我同樣的新手。前端
有一個服務器(否則搞毛),購買能夠參考優質國外vps推薦python
有我的域名(固然,你能夠直接使用 IP訪問,但有點奇怪不是?購買域名能夠去GoDaddymysql
能夠選擇 github 或者Bitbucket,固然你也能夠本身搭建 git服務器,但我以爲沒啥必要,我選擇Bitbucket,主要是由於它私有庫免費nginx
sudo yum install git
複製代碼
後續就跟咱們本地開發沒什麼區別了,配置 ssh key,clone代碼,就不展開了,項目目錄建議放在 /home/www/
下c++
$wget 'https://dev.mysql.com/get/mysql57-community-release-el7-11.noarch.rpm'
$sudo rpm -Uvh mysql57-community-release-el7-11.noarch.rpm
$yum repolist all | grep mysql
mysql-connectors-community/x86_64 MySQL Connectors Community 36
mysql-tools-community/x86_64 MySQL Tools Community 47
mysql57-community/x86_64 MySQL 5.7 Community Server 187
複製代碼
$sudo yum install mysql-community-server
複製代碼
$sudo service mysqld start
$sudo systemctl start mysqld #CentOS 7
$sudo systemctl status mysqld
● mysqld.service - MySQL Community Server
Loaded: loaded (/usr/lib/systemd/system/mysqld.service; enabled; vendor preset: disabled)
Active: active (running) since Sat 2017-05-27 12:56:26 CST; 15s ago
Process: 2482 ExecStartPost=/usr/bin/mysql-systemd-start post (code=exited, status=0/SUCCESS)
Process: 2421 ExecStartPre=/usr/bin/mysql-systemd-start pre (code=exited, status=0/SUCCESS)
Main PID: 2481 (mysqld_safe)
CGroup: /system.slice/mysqld.service
├─2481 /bin/sh /usr/bin/mysqld_safe --basedir=/usr
└─2647 /usr/sbin/mysqld --basedir=/usr --datadir=/var/lib/mysql --plugin-dir=/usr/...
複製代碼
說明已經正在運行中了git
$ mysql -uroot -p
複製代碼
這裏有要求你輸入密碼,Mysql安裝時會生成一個默認密碼,使用 grep "temporary password" /var/log/mysqld.log
命令,返回結果最後引號後面的字符串就是root的默認密碼github
mysql> ALTER USER 'root'@'localhost' IDENTIFIED BY 'NewPassword';
複製代碼
在 /etc/my.cnf 中設置默認的編碼web
[client]
default-character-set = utf8
[mysqld]
default-storage-engine = INNODB
character-set-server = utf8
collation-server = utf8_general_ci #不區分大小寫
collation-server = utf8_bin #區分大小寫
collation-server = utf8_unicode_ci #比 utf8_general_ci 更準確
複製代碼
mysql> CREATE DATABASE <datebasename> CHARACTER SET utf8;
複製代碼
CentOS 7 默認安裝了 Python 2,當須要使用 Python 3 的時候,能夠手動下載 Python 源碼後編譯安裝。sql
sudo mkdir /usr/local/python3 # 建立安裝目錄
$ wget --no-check-certificate https://www.python.org/ftp/python/3.6.2/Python-3.6.2.tgz # 下載 Python 源文件
# 注意:wget獲取https的時候要加上:--no-check-certifica
$ tar -xzvf Python-3.6.2.tgz # 解壓縮包
$ cd Python-3.6.2 # 進入解壓目錄
sudo ./configure --prefix=/usr/local/python3 # 指定建立的目錄
sudo make
sudo make install # 編譯安裝
複製代碼
執行./configure時可能會報錯,configure: error: no acceptable C compiler found in $PATH,這是由於未安裝合適的編譯器,安裝下就行了,
sudo yum install gcc-c++
(使用sudo yum install gcc-c++時會自動安裝/升級gcc及其餘依賴的包。)
建立 python3 的軟連接:
$ sudo ln -s /usr/local/python3/bin/python3 /usr/bin/python3
複製代碼
這樣就能夠經過 python
命令使用 Python 2,python3
來使用 Python 3。
$ sudo yum -y install epel-release # 首先安裝 epel 擴展源
$ sudo yum -y install python-pip # 安裝 python-pip
$ sudo yum clean all # 清除 cache
複製代碼
經過這種方式貌似只能安裝 pip2,想要安裝 Python 3 的 pip,能夠經過如下的源代碼安裝方式。
# 下載源代碼
$ wget --no-check-certificate https://github.com/pypa/pip/archive/9.0.1.tar.gz
$ tar -zvxf 9.0.1.tar.gz # 解壓文件
$ cd pip-9.0.1
$ python3 setup.py install # 使用 Python 3 安裝
複製代碼
建立連接:
$ sudo ln -s /usr/local/python3/bin/pip /usr/bin/pip3
複製代碼
升級 pip
$ pip install --upgrade pip
複製代碼
Gunicorn (獨角獸)是一個高效的Python WSGI Server,一般用它來運行 wsgi application(由咱們本身編寫遵循WSGI application的編寫規範) 或者 wsgi framework(如Django,Paster),地位至關於Java中的Tomcat。 WSGI就是這樣的一個協議:它是一個Python程序和用戶請求之間的接口。WSGI服務器的做用就是接受並分析用戶的請求,調用相應的python對象完成對請求的處理,而後返回相應的結果。 簡單來講gunicorn封裝了HTTP的底層實現,咱們經過gunicorn啓動服務,用戶請求與服務相應都通過gunicorn傳輸
cd /home/www/blog
mkdir venv
python3 -m venv venv
複製代碼
source venv/bin/activate
複製代碼
而後根據requirements.txt
文件安裝依賴包:
pip3 install -r requirements.txt
複製代碼
pip3 install gunicorn
複製代碼
在項目根目錄建立一個wsgi.py文件
from app import create_app
application = create_app('production')
if __name__ == '__main__':
application.run()
複製代碼
再也不經過manage.py啓動服務,那隻在開發的時候使用
啓動服務:
gunicorn -w 4 -b 127.0.0.1:8000 wsgi:application
複製代碼
nginx 是一個高性能的web服務器。一般用來在前端作反向代理服務器。所謂正向與反向(reverse),只是英文說法翻譯。代理服務,簡而言之,一個請求通過代理服務器從局域網發出,而後到達互聯網上服務器,這個過程的代理爲正向代理。若是一個請求,從互聯網過來,先進入代理服務器,再由代理服務器轉發給局域網的目標服務器,這個時候,代理服務器爲反向代理(相對正向而言)。
正向代理:{ 客戶端 ---》 代理服務器 } ---》 服務器
反向代理:客戶端 ---》 { 代理服務器 ---》 服務器 }
{} 表示局域網
nginx既能夠作正向,也能夠作反向。
$ yum -y install nginx
複製代碼
$ service nginx start
複製代碼
$ service nginx stop
複製代碼
$ service nginx restart
複製代碼
nginx配置改動了,能夠從新加載而不用先關閉再打開
$ nginx -s reload
複製代碼
啓動後 ,在瀏覽器中 輸入服務器的 ip 地址,就能夠看到
到這裏 yum
安裝 nginx
就完成了
nginx的配置文件爲:/etc/nginx/nginx.conf
server {
listen 80;
server_name adisonhyh.com;
location / {
proxy_pass http://127.0.0.1:8000;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
複製代碼
gunicorn和nginx關係:
gunicorn 能夠單獨提供服務,但生產環境通常不這樣作。首先靜態資源(jscssimg)會佔用很多的請求資源,而對於 gunicorn 來說它自己更應該關注實際業務的請求與處理而不該該把資源浪費在靜態資源請求上;此外,單獨運行 gunicorn 是沒有辦法起多個進程多個端口來負載均衡的。
nginx 的做用就是彌補以上問題,首先做爲前端服務器它能夠處理一切靜態文件請求,此時 gunicorn 做爲後端服務器,nginx 將會把動態請求轉發給後端服務器,所以咱們能夠起多個 gunicorn 進程,而後讓 nginx 做均衡負載轉發請求給多個 gunicorn 進程從而提高服務器處理效率與處理能力。最後,nginx 還能夠配置不少安全相關、認證相關等不少處理,可讓你的網站更專一業務的編寫,把一些轉發規則等其它業務無關的事情交給 nginx 作。
配置好後打開本地瀏覽器,輸入域名,應該就能訪問了。
若是你須要進程一直執行,若該進程因各類緣由中斷,也會自動重啓的話,supervisor是一個很好的選擇。 supervisor管理進程,是經過fork/exec的方式將這些被管理的進程看成supervisor的子進程來啓動,因此咱們只須要將要管理進程的可執行文件的路徑添加到supervisor的配置文件中就行了。此時被管理進程被視爲supervisor的子進程,若該子進程異常終端,則父進程能夠準確的獲取子進程異常終端的信息,經過在配置文件中設置autostart=true,能夠實現對異常中斷的子進程的自動重啓。
$ pip install supervisor
$ echo_supervisord_conf > supervisor.conf # 生成 supervisor 默認配置文件
$ vim supervisor.conf # 修改 supervisor 配置文件,添加 gunicorn 進程管理
複製代碼
在blog supervisor.conf 配置文件底部添加 (注意個人工做路徑是www/home/blog/
)
[program:blog]
command=/home/www/blog/venv/bin/gunicorn -w4 -b0.0.0.0:8000 wsgi:application ;supervisor啓動命令
directory=/home/www/blog ; 項目的文件夾路徑
startsecs=0 ; 啓動時間
stopwaitsecs=0 ; 終止等待時間
autostart=false ; 是否自動啓動
autorestart=false ; 是否自動重啓
stdout_logfile=/home/www/blog/logs/gunicorn.log ; log 日誌
stderr_logfile=/home/www/blog/logs/gunicorn.err ; 錯誤日誌
複製代碼
使用 supervsior 啓動 gunicorn
$ sudo supervisord -c supervisor.conf
$ sudo supervisorctl start blog
複製代碼
在瀏覽器地址欄輸入配置的地址便可訪問網站。
最後一步,咱們使用fabric實現遠程操做和部署。Fabric 是一個 Python 下相似於 Makefiles 的工具,可是可以在遠程服務器上執行命令。
pip install fabric
複製代碼
在 blog 目錄下新建一個fabfile.py文件
import os
from fabric.api import local, env, run, cd, sudo, prefix, settings, execute, task, put
from fabric.contrib.files import exists
from contextlib import contextmanager
env.hosts = ['204.152.201.69']
env.user = 'root'
env.password = '****'#密碼
env.group = "root"
DEPLOY_DIR = '/home/www/blog'
VENV_DIR = os.path.join(DEPLOY_DIR, 'venv')
VENV_PATH = os.path.join(VENV_DIR, 'bin/activate')
@contextmanager
def source_virtualenv():
with prefix("source {}".format(VENV_PATH)):
yield
def update():
with cd('/home/www/blog/'):
sudo('git pull')
def restart():
with cd(DEPLOY_DIR):
if not exists(VENV_DIR):
run("virtualenv {}".format(VENV_DIR))
with settings(warn_only=True):
with source_virtualenv():
run("pip install -r {}/requirements.txt".format(DEPLOY_DIR))
with settings(warn_only=True):
stop_result = sudo("supervisorctl -c {}/supervisor.conf stop all".format(DEPLOY_DIR))
if not stop_result.failed:
kill_result = sudo("pkill supervisor")
if not kill_result:
sudo("supervisord -c {}/supervisor.conf".format(DEPLOY_DIR))
sudo("supervisorctl -c {}/supervisor.conf reload".format(DEPLOY_DIR))
sudo("supervisorctl -c {}/supervisor.conf status".format(DEPLOY_DIR))
sudo("supervisorctl -c {}/supervisor.conf start all".format(DEPLOY_DIR))
@task
def deploy():
execute(update)
execute(restart)
複製代碼
如今代碼若是更新了,能夠直接在本地執行遠程部署了
fab deploy
複製代碼