CentOS 部署 flask项目的方法详细过程及踩坑

参考自http://www.jb51.net/article/132849.html

 

 

最近在学习 python,使用 flask 实现了个个人博客程序,完了想部署到服务器上。因为是新手,一路磕磕绊绊最终把它基本搞定。网上资料对新手感觉都不太友好,都是零零碎碎的,所以我整理了一下,一方面作为我自己的记录,方便以后查阅,另一方面也希望能帮助到跟我一样的新手。

前提

  1. 有一个服务器(不然搞毛),购买可以参考优质国外vps推荐
  2. 有个人域名(当然,你可以直接使用 IP访问,但有点奇怪不是?购买域名可以去GoDaddy

1.安装git

可以选择 github 或者Bitbucket,当然你也可以自己搭建 git服务器,但我觉得没啥必要,我选择Bitbucket,主要是因为它私有库免费

?
1
sudo yum install git

后续就跟我们本地开发没什么区别了,配置 ssh key,clone代码,就不展开了,项目目录建议放在 /home/www/ 下

2. 安装 Mysql

添加 MySQL YUM 源

?
1
2
3
4
5
6
7
$ 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

安装最新版本

?
1
$ sudo yum install mysql-community-server

启动 MySQL 服务

?
1
2
3
4
5
6
7
8
9
10
11
12
$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/...

说明已经正在运行中了

修改密码

?
1
$ mysql -uroot -p

这里有要求你输入密码,Mysql安装时会生成一个默认密码,使用 grep "temporary password" /var/log/mysqld.log 命令,返回结果最后引号后面的字符串就是root的默认密码

?
1
mysql> ALTER USER 'root' @ 'localhost' IDENTIFIED BY 'NewPassword' ;

修改编码

在 /etc/my.cnf 中设置默认的编码

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
[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 更准确

创建数据库

?
1
mysql> CREATE DATABASE <datebasename> CHARACTER SET utf8;
通过yum安装失败了,本人重新通过下载源码安装,本来写了好好的一篇新手博客,结果。。。没保存就关闭了浏览器,结果想死的心都有了,就再也不想重写了,也写不出来了。

安装过程参考了:http://www.jb51.net/article/87160.htm的博客

 

2.1系统约定

安装文件下载目录:/data/software
Mysql目录安装位置:/usr/local/mysql
数据库保存位置:/data/mysql
日志保存位置:/data/log/mysql

2.2下载mysql

在官网:http://dev.mysql.com/downloads/mysql/ 中,选择以下版本的mysql下载:

执行如下命名:
#mkdir /data/software
#cd /data/software
#wget http://dev.mysql.com/get/Downloads/MySQL-5.7/mysql-5.7.13-linux-glibc2.5-x86_64.tar.gz

2.3解压压缩包到目标位置

# mkdir /usr/local/mysql
#cd /dat/software
#pwd

执行后如下:

#ls

#cd /usr/local
#pwd

# tar -xzvf /data/software/mysql-5.7.13-linux-glibc2.5-x86_64.tar.gz

#ls

--修改文件名
# mv mysql-5.7.13-linux-glibc2.5-x86_64 mysql         
#ls

2.4创建数据仓库目录
--/data/mysql 数据仓库目录
# mkdir /data/mysql         
#ls /data/

2.5新建mysql用户、组及目录
#      ---新建一个msyql组
# useradd -r -s /sbin/nologin -g mysql mysql -d /usr/local/mysql     ---新建msyql用户禁止登录shell

2.6改变目录属有者
#cd /usr/local/mysql
#pwd
#chown –R mysql .
#chgrp –R mysql .

#chown -R mysql /data/mysql

2.7配置参数
# bin/mysqld --initialize --user=mysql --basedir=/usr/local/mysql --datadir=/data/mysql

 此处需要注意记录生成的临时密码,如上文:YLi>7ecpe;YP
#bin/mysql_ssl_rsa_setup  --datadir=/data/mysql

2.8修改系统配置文件

# cp my-default.cnf /etc/my.cnf
# cp mysql.server /etc/init.d/mysql

# vim /etc/init.d/mysql
修改以下内容:

# vim /etc/my.cnf
修改以下内容:

2.9启动mysql

#bin/mysqld_safe --user=mysql &

bin/mysql --user=root –p
--输入第6步生成的临时密码

mysql> set password=password('A123456');

mysql>grant all privileges on *.* to root@'%' identified by 'A123456';
mysql> flush privileges;

mysql> use mysql;
mysql> select host,user from user;

2.10添加系统路径
# vim /etc/profile
添加:
export PATH=/usr/local/mysql/bin:$PATH
如下:

# source /etc/profile

2.11配置mysql自动启动
# chmod 755 /etc/init.d/mysql
# chkconfig --add mysql
# chkconfig --level 345 mysql on

 

ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using passwor)参考了:https://blog.csdn.net/lisongjia123/article/details/57418989

 

3. 安装python3 pip3

Python3的安装配置详细过程参照https://blog.csdn.net/qq_35304570/article/details/80302872

CentOS 7 默认安装了 Python 2,当需要使用 Python 3 的时候,可以手动下载 Python 源码后编译安装。

安装 Python 3

?
1
2
3
4
5
6
7
8
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 的软链接:

?
1
$ sudo ln -s /usr/local/python3/bin/python3 /usr/bin/python3

这样就可以通过 python 命令使用 Python 2, python3 来使用 Python 3。

安装 pip

?
1
2
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,可以通过以下的源代码安装方式安装

参考:https://blog.csdn.net/a2011480169/article/details/77414500/

1、下载:

# wget –no-check-certificate https://pypi.python.org/packages/source/s/setuptools/setuptools-19.6.tar.gz#md5=c607dd118eae682c44ed146367a17e26

 

2、解压 
tar -zxvf setuptools-19.6.tar.gz

[root@iz2zea81ksgk8xh72ofrr0z software]# ll |grep setuptools-19.6
drwxr-xr-x 10  501 games    4096 Aug 19 17:34 setuptools-19.6
-rw-r--r--  1 root root   641502 Jan 25  2016 setuptools-19.6.tar.gz

3、进入setuptools-19.6编译安装

cd setuptools-19.6.tar.gz

python3 setup.py build

python3 setup.py install

到这里如果你还没有报错的话,说明setuptools已经安装成功了,但是在这里我遇到了一个坑,当我执行python3 setup.py install时出现了错误,报错信息如下:

Compression requires the (missing) zlib module.

出错原因:提示的很清楚,缺少 zlib模块导致安装失败 
处理方式: 
1、先安装缺少的模块(2行命令) 
yum install zlib 
yum install zlib-devel 
2、下载zlib成功后, cd Python-3.6.0a1的目录,重新执行下面的这个命令:

make && make install

3、重新进入setuptools-19.6目录,再次执行下面的命令:

python3 setup.py install

到这里问题解决,setuptools-19.6安装成功.


接下来我们安装Pip3 
1、下载 
wget –no-check-certificate https://pypi.python.org/packages/source/p/pip/pip-8.0.2.tar.gz#md5=3a73c4188f8dbad6a1e6f6d44d117eeb 
2、解压 
tar -zxvf pip-8.0.2.tar.gz

[root@iz2zea81ksgk8xh72ofrr0z software]# ll |grep pip
drwxr-xr-x  7  501 games    4096 Aug 19 17:44 pip-8.0.2
-rw-r--r--  1 root root  1130183 Aug 19 17:40 pip-8.0.2.tar.gz

3、进入pip-8.0.2目录,编译安装:

cd pip-8.0.2

python3 setup.py build

python3 setup.py install

到这里pip3就安装成功了,可以检查一下:

[root@iz2zea81ksgk8xh72ofrr0z software]# whereis pip3
pip3: /usr/local/bin/pip3 /usr/local/bin/pip3.6

我当时到这里以为安装成功了,但是当执行pip3的时候,报错了,信息如下:

cannot import name HTTPSHandler.

问题:提示的很清楚,缺少 HTTPSHandler模块导致安装失败 
处理方式: 
1、先安装缺少的模块(2行命令)

yum install openssl
yum install openssl-devel

2、下载 HTTPSHandler成功后, cd Python-3.6.0a1的目录,重新执行下面的这个命令:

make && make install

当我执行完上一行命令之后,出现了下面的日志(部分)

Ignoring indexes: https://pypi.python.org/simple
Collecting setuptools
Collecting pip
Installing collected packages: setuptools, pip
  Found existing installation: setuptools 19.6
    Uninstalling setuptools-19.6:
      Successfully uninstalled setuptools-19.6
  Found existing installation: pip 8.0.2
    Uninstalling pip-8.0.2:
      Successfully uninstalled pip-8.0.2
Successfully installed pip setuptools

从最后一行Successfully installed pip setuptools可以看出,我的setuptools和pip随之跟着也成功了,验证一下:

[root@iz2zea81ksgk8xh72ofrr0z software]# pip3

Usage:   
  pip <command> [options]

Commands:
  install                     Install packages.
  download                    Download packages.
  uninstall                   Uninstall packages.
  freeze                      Output installed packages in requirements format.
  list                        List installed packages.
  show                        Show information about installed packages.
  search                      Search PyPI for packages.
  wheel                       Build wheels from your requirements.
  hash                        Compute hashes of package archives.
  completion                  A helper command used for command completion
  help                        Show help for commands.

General Options:
  -h, --help                  Show help.
  --isolated                  Run pip in an isolated mode, ignoring environment variables and user configuration.
  -v, --verbose               Give more output. Option is additive, and can be used up to 3 times.
  -V, --version               Show version and exit.
  -q, --quiet                 Give less output.
  --log <path>                Path to a verbose appending log.
  --proxy <proxy>             Specify a proxy in the form [user:passwd@]proxy.server:port.
  --retries <retries>         Maximum number of retries each connection should attempt (default 5 times).
  --timeout <sec>             Set the socket timeout (default 15 seconds).
  --exists-action <action>    Default action when a path already exists: (s)witch, (i)gnore, (w)ipe, (b)ackup.
  --trusted-host <hostname>   Mark this host as trusted, even though it does not have valid or any HTTPS.
  --cert <path>               Path to alternate CA bundle.
  --client-cert <path>        Path to SSL client certificate, a single file containing the private key and the
                              certificate in PEM format.
  --cache-dir <dir>           Store the cache data in <dir>.
  --no-cache-dir              Disable the cache.
  --disable-pip-version-check
                              Don't periodically check PyPI to determine whether a new version of pip is available for
                              download. Implied with --no-index.

OK,大功告成! 
总结一下注意的点,每次安装完缺少的模块之后,都需要:cd Python-3.6.0a1的目录,重新执行下面的这个命令:

make && make install

 

 

 

创建链接:

?
1
$ sudo ln -s /usr/local/python3/bin/pip /usr/bin/pip3

升级 pip

?
1
$ pip install --upgrade pip

4. 安装 gunicorn

Gunicorn (独角兽)是一个高效的Python WSGI Server,通常用它来运行 wsgi application(由我们自己编写遵循WSGI application的编写规范) 或者 wsgi framework(如Django,Paster),地位相当于Java中的Tomcat。 WSGI就是这样的一个协议:它是一个Python程序和用户请求之间的接口。WSGI服务器的作用就是接受并分析用户的请求,调用相应的python对象完成对请求的处理,然后返回相应的结果。 简单来说gunicorn封装了HTTP的底层实现,我们通过gunicorn启动服务,用户请求与服务相应都经过gunicorn传输

创建虚拟环境

?
1
2
3
cd /home/www/blog
mkdir venv
python3 -m venv venv

激活虚拟环境:

?
1
source venv/bin/activate

然后根据 requirements.txt 文件安装依赖包:

?
1
pip3 install - r requirements.txt

安装gunicorn

?
1
pip3 install gunicorn

在项目根目录创建一个wsgi.py文件

?
1
2
3
4
5
6
from app import create_app
 
application = create_app( 'production' )
 
if __name__ = = '__main__' :
   application.run()

不再通过manage.py启动服务,那只在开发的时候使用

启动服务:

?
1
gunicorn -w 4 -b 127.0.0.1:8000 wsgi:application

5. 安装 Nginx

nginx 是一个高性能的web服务器。通常用来在前端做反向代理服务器。所谓正向与反向(reverse),只是英文说法翻译。代理服务,简而言之,一个请求经过代理服务器从局域网发出,然后到达互联网上服务器,这个过程的代理为正向代理。如果一个请求,从互联网过来,先进入代理服务器,再由代理服务器转发给局域网的目标服务器,这个时候,代理服务器为反向代理(相对正向而言)。

正向代理:{ 客户端 ---》 代理服务器 } ---》 服务器

反向代理:客户端 ---》 { 代理服务器 ---》 服务器 }

{} 表示局域网

nginx既可以做正向,也可以做反向。

?
1
$ yum -y install nginx

启动 nginx 服务

?
1
$ service nginx start

停止 nginx 服务

?
1
$ service nginx stop

重启 nginx 服务

?
1
$ service nginx restart

平滑重启

nginx配置改动了,可以重新加载而不用先关闭再打开

?
1
$ nginx -s reload

启动后 ,在浏览器中 输入服务器的 ip 地址,就可以看到

到这里 yum 安装 nginx 就完成了

添加配置

nginx的配置文件为: /etc/nginx/nginx.conf

?
1
2
3
4
5
6
7
8
9
10
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;
     }
}
  1. 监听http默认的端口号80
  2. server_name:个人网站域名
  3. 把请求代理到本机的8000端口(gunicorn启动服务指定的端口) 剩下proxy_set_header照抄

gunicorn和nginx关系:

gunicorn 可以单独提供服务,但生产环境一般不这样做。首先静态资源(jscssimg)会占用不少的请求资源,而对于 gunicorn 来讲它本身更应该关注实际业务的请求与处理而不应该把资源浪费在静态资源请求上;此外,单独运行 gunicorn 是没有办法起多个进程多个端口来负载均衡的。

nginx 的作用就是弥补以上问题,首先作为前端服务器它可以处理一切静态文件请求,此时 gunicorn 作为后端服务器,nginx 将会把动态请求转发给后端服务器,因此我们可以起多个 gunicorn 进程,然后让 nginx 作均衡负载转发请求给多个 gunicorn 进程从而提升服务器处理效率与处理能力。最后,nginx 还可以配置很多安全相关、认证相关等很多处理,可以让你的网站更专注业务的编写,把一些转发规则等其它业务无关的事情交给 nginx 做。
配置好后打开本地浏览器,输入域名,应该就能访问了。

6.supervisor

如果你需要进程一直执行,若该进程因各种原因中断,也会自动重启的话,supervisor是一个很好的选择。 supervisor管理进程,是通过fork/exec的方式将这些被管理的进程当作supervisor的子进程来启动,所以我们只需要将要管理进程的可执行文件的路径添加到supervisor的配置文件中就好了。此时被管理进程被视为supervisor的子进程,若该子进程异常终端,则父进程可以准确的获取子进程异常终端的信息,通过在配置文件中设置autostart=true,可以实现对异常中断的子进程的自动重启。

安装 supervisor

?
1
2
3
$ pip install supervisor
$ echo_supervisord_conf > supervisor.conf  # 生成 supervisor 默认配置文件
$ vim supervisor.conf            # 修改 supervisor 配置文件,添加 gunicorn 进程管理

在blog supervisor.conf 配置文件底部添加 (注意我的工作路径是 www/home/blog/ )

?
1
2
3
4
5
6
7
8
9
[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

?
1
2
$ sudo supervisord -c supervisor.conf
$ sudo supervisorctl start blog

在浏览器地址栏输入配置的地址即可访问网站。

7. fabric

最后一步,我们使用fabric实现远程操作和部署。Fabric 是一个 Python 下类似于 Makefiles 的工具,但是能够在远程服务器上执行命令。

安装 fabric

?
1
pip install fabric

在 blog 目录下新建一个fabfile.py文件

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
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)

现在代码如果更新了,可以直接在本地执行远程部署了

?
1
fab deploy

 

 

  • 10
    点赞
  • 53
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值