这篇文章主要是为了讲解一下如何部署这个博客系统.
涉及的内容有:
-
VPS与域名
-
Nginx配置
-
Virtualenv, Gunicorn, Supervisor
这篇文章只是我的个人经验, 对于某些问题我也无法给出确定的答案:
-
Nginx的详细配置
-
其他Linux发行版无法正常使用(我的是Centos6)
这个博客系统主要由flask和bootstrap实现, 可以认为是一个flask的练手项目, 其中有很多地方借鉴了这本书.
作为这个系列的首篇文章, 主要讲解如何将这个博客系统部署到你的VPS上.
为了部署这个博客, 首先你需要有一个服务器, 当然如果是为了练习的话, 使用虚拟机就足够了.下面说一说我的购买经历.
我购买的VPS是bandwagonhost的(俗称搬瓦工,性价比高), VPS的配置是512Mb内存, 10GSSD详情, 价格为19.9$/year, 使用优惠码的话19$能拿下, 测试延迟大概250~300间.
购买VPS后, 我们需要做一些预备工作以方便我们的后续使用.
使用搬瓦工控制台的interactive-shell,输入如下指令:
$ passwd <username>
之后按要求输入两次密码即可重置root密码, 然后我们可以下载PuTTY, 利用ssh连接到远程服务器进行操作.
我们不应该直接利用root用户, 因此我们应该设置一个日常用户来进行操作.
首先, 利用PuTTY连接到目标服务器并以root用户登录,然后执行下面的指令:
$ adduser <username>
$ passwd <username>
输入用户密码, 就完成新用户的建立, 接下来, 为用户授予必要的权限, 授予怎样的权限见仁见智, 你可参考这篇文章.
在开发和测试环境下我们使用的是Sqlite数据库, 当然在部署的时候你也可以使用Sqlite, 但是更好的选择还是使用Mysql/Postgresql, 而且在某些系统中(比如我是用的Centos6), 由于Sqlite版本过低且为系统依赖, 导致部署会遇到很大的困难, 因此最好还是使用Mysql.
Mysql的安装有两种方式, 一种是直接使用yum安装, 但是这样获得Mysql版本为5.1, 此时如果使用默认的DATABASE_URI就会遇到问题, 这是因为如果使用下面这种默认格式的URI:
mysql://username:password@hostname/database
则SQLAlchemy将会使用Mysqldb这个Python库程序, 而Mysqldb并不支持5.1版本的Mysql(必须大于>5.6才支持).
所以对于Mysql的选择就有两种方法:
一是使用yum安装, DATABASE_URI使用mysql+pymysql://....格式
二是编译安装更新版本的Mysql, 参考这篇文章
在安装完成后需要进行一定的配置以及添加新用户.
# 假设root用户密码已经设置完毕
$ mysql -u root -p
# 输入密码
$ mysql> CREATE USER 'username'@'hostname' IDENTIFIED BY 'password';
# 创建博客专用的数据库
$ mysql> CREATE DATABASE <blog_db_name>;
# 为新建用户授予数据库权限
$ mysql> GRANT all ON <blog_db_name>.* TO 'username'@'hostname';
# 刷新
$ mysql> FLUSH PRIVILEGES;
# 退出后重使用新用户登录
这个没有什么难度, 直接使用yum安装即可,关于Nginx的一些简单说明:
位置/etc/nginx/*
开启服务 service nginx start/restart
结束服务
$ ps -ef | grep nginx
$ kill -QUIT <pid of nginx master>
Centos默认的Python是2.6版本的, 同时也是重要的系统依赖, 因此我们需要手动安装2.7吧呢不能的Python.
具体操作如下:
# 下载源码
$ wget https://www.python.org/ftp/python/2.7.10/Python-2.7.10.tgz
# 安装依赖(不是必要的)
$ yum install readline-devel -y
# 解压文件
$ tar xf Python-2.7.10.tgz
$ cd Python-2.7.10
# config/make/make install
$ ./configure
$ make all
$ make install
$ cd ../
# 默认安装位置在/usr/local/bin,/usr/local/lib/python2.7
配置python:
# 重命名系统自带的python
$ mv /usr/bin/python /usr/bin/python2.6
# 为新版本的python建立链接
$ ln /usr/local/bin/python2.7 /usr/bin/python
由于旧版本的Python是yum的依赖项, 因此必须修改yum文件:
$ vim /usr/bin/yum
# 打开文件后讲首行修改
/usr/bin/python ==> /usr/bin/python2.6
测试Python是否正常使用
$ python --version
接下来配置Python包管理工具pip:
首先安装setuptools:
$ wget https://bootstrap.pypa.io/ez_setup.py -O - | python - --user
然后下载并安装pip:
$ wget https://pypi.python.org/packages/source/p/pip/pip-8.1.0.tar.gz#md5=e9c3844db343f47d16040b32ad9072be
# 解压安装
$ tar xf pip-7.1.2.tar
$ cd pip-7.1.2
$ python setup.py install
# 测试是否正常运行
$ pip -V
我购买的是namesilo的域名,原价8.99$,使用优惠码后的价格是7.99$.
这个网站上会有很多域名商的优惠码, 有需要的可以参考.在付款时记得勾选Whois隐私保护服务,免费的.
这个步骤很简单, 基本上就是点点鼠标就可以实现的,你们可以参考下面这面文章
接下来要安装我们部署博客所必须的工具.
Virtualenv是一个Python工具, 它可以创建一个独立的Python环境.
单纯地这么说没什么意义, 打个或许不怎么恰当的例子:
你是一个厨师学徒, 你的师傅给你原料和店里的老汤让你尝试调出一点新味道, 你应该怎么做呢?
你可以直接往往老汤里加料, 但是很有可能一个不小心就把老汤全浪费了.
还有一个办法就是把老汤放到不同的锅里, 然后你就可以肆无忌弹的在不同的锅里加原料了, 因为调坏了一锅并不影响到其他的锅.
Virtualenv就相当于是那个锅, 你可以创建一个Virtualenv环境, 然后肆意的在里面开发, 但是你在环境中的作为并不会影响到外部或其他Virtualenv环境.
$ pip install -U virtualenv
# 新建环境
$ virtualenv --no-site-packages /project/path
$ cd /project/path
# 激活环境
$ source bin/activate
# 终止,任何目录下都可用
$ deactivate
我们使用Gunicorn作为博客的生产环境服务器
关于Gunicorn的介绍可以参考这里
请在激活Virtualenv的情况下使用:
# 在当前Virtualenv环境下安装
$ pip install gunicorn
接下来介绍一下基本的使用:
$ gunicorn -w4 -b0.0.0.0:8888 <app_name>:app
-w == --worker, 处理请求的worker数
-b == --bind, 绑定地址
app_name:app 这段代码可能会给你带来一些疑惑, 以部署flask应用为例子, 如果我们没有使用Gunicorn部署, 例如测试时, 我们会使用flask自带的服务器, 这时我们运行服务器的方式是:
# 这个文件的名称为myapp.py
# 编写flask代码
if __name__ == '__main__':
app.run()
运行这个文件即可运行服务器.
当我们使用Gunicorn时, 我们要运行的实例就是myapp中的app, 换句话说, 如果你运行flask应用的文件是runserver.py,内容是:
# flask代码
if __name__ == '__main__':
my_app.run()
那么使用Gunicorn运行的方式就是:
$ gunicorn -w4 -b0.0.0.0:1234 runserver:my_app
Supervisor是一个进程管理工具, 他的方便之处在于控制(一个或多个)进程的开启, 关闭, 重启等.
请在Virtualenv激活的情况下使用
$ pip install supervisor
在使用Supervisor管理进程之前, 我们需要对为目标程序编写配置文件.
# 以特定配置文件启动Supervisor服务端
$ supervisord -c supervisor.conf
# 结束Supervisor服务
$ ps -ed | grep supervisor
$ kill -QUIT <pid>
# 启动后常用指令
## 查看program状态
$ supervisorctl -c supervisor.conf status
## 启动程序
$ supervisorctl -c supervisor.conf start <program_name> or all
## 重新启动
$ supervisorctl -c supervisor.conf restart <program_name> or all
## 中止
$ supervisorctl -c supervisor.conf stop <program_name> or all
更多关于配置的内容可以参考这篇文章.
当我们完成了相关工具的安装后就要开始进行配置.
首先要做的是为系统写入相关的环境变量, 当然你也可以直接在config.py中写入, 但是推荐的做法是将这些变量写入环境变量中.
# 打开.bash_profile(在这里面添加环境变量只针对当前用户有效)
vim ~/.bash_profile
在.bash_profile中添加
# For Blog Deploy
export FLASK_CONFIG="production"
export FLASK_BLOG_ADMIN="your@email.com"
export SECRET_KEY="hard to guess"
export DATABASE_URL="mysql+pymysql://username:password@hostname/database"
编辑完成后,刷新一下控制台
$ source ~/.bash_profile
至此, 环境变量的设置就完成了.
现在我们可以下载博客系统的源文件准备进行部署了.
# 从github上下载源文件
$ git clone https://github.com/ezirmusitua/Jferroal-s-Blog.git
# 添加Virtualenv环境
virtualenv --no-site-packages Jferroal-s-Blog
# 进入
$ cd /path/2/blog/Jferroal-s-Blog
# 安装Gunicorn
$ pip install gunicorn
# 安装Supervisor
$ pip install supervisor
# 为博客项目添加supervisor配置文件
$ touch supervisor.conf
在supervisor.conf中添加以下内容
[program:myblog]
command=/path/2/blog/Jferroal-s-Blog/bin/gunicorn -w4 -b0.0.0.0:1234 manage:app
directory=/path/2/blog/Jferroal-s-Blog
startsecs=0
stopwaitsecs=0
autostart=false
autorestart=true
stdout_logfile=/path/2/blog/log/gunicorn.log
stderr_logfile=/path/2/blog/log/gunicorn.err
上面这段code的大致含义是:
创建一个名为myblog的程序, command是运行程序的指令, directory是程序所在位置, 后面包括开启程序的时间, 程序停止后的等待时间, 是否自动启动/重启以及日志保存位置.
当我们完成supervisor的配置后基本上是可以访问了, 但是更进一步的是配置nginx, 为博客系统添加反向代理.
对于nginx.conf(位于/etc/nginx/)的配置不多说,要注意在http配置的后面include上blog站点的配置,即
# some configuration
include /etc/nginx/sites-enabled/my_blog.conf;
# some configuration
进入/etc/nginx/sites-enabled/(没有就mkdir一个)
$ cd /etc/nginx/sites-enabled/
# 创建server配置
$ vim my_blog.conf
创建配置文件后在其中写入:
server {
listen 80; # 监听80端口
server_name www.domain.com domain.com; # 设置为域名就好
root /path/2/blog; # 站点根目录
access_log /path/2/logs/nginx/blog_access.log; # access log存放
error_log /home/path/2/logs/nginx/blog_error.log; # error log存放
charset utf-8; # 设置字符集
location / { # 对所有访问/的请求
proxy_pass http://0.0.0.0:1234; # 反向代理
proxy_set_header Host $host; # 获取真实IP
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
写入完成后, 如果nginx已经启动, 重启一下Nginx.
在上述配置都完成后,别忘记添加数据库用户和数据库,最后reboot一下,然后就可以准备开始运行
cd /path/2/blog/Jferroal-s-Blog
# 运行first run创建Admin对象
$ python manage.py first_run
# 请确保nginx已经运行
# 开启supervisor
$ supervisord -c supervisor.conf
# 运行项目
$ supervisorctl -c supervisor.conf start myblog
现在可以尝试访问域名登陆博客咯, 登陆的地址是: www.domain.com/auth/login