Centos7 安装Python3.6+Nginx+Gunicorn+Flask


 Centos7 安装Python3.6+Nginx+Gunicorn Flask

最近阿里云服务器到期了,而续费又太贵了,不得已再买过一台新的。同也打算把博客迁移到Python环境中运行。所以先在测试环境中试验一下效果。

 

安装一些常用依赖包:

  1. yum install zlib-devel bzip2-devel openssl-devel ncurses-devel sqlite-devel readline-devel tk-devel gcc make 

 

1、下载Python3.6.4并安装到系统中

  1. wget https://www.python.org/ftp/python/3.6.4/Python-3.6.4.tgz 
  2. tar xf Python-3.6.4.tgz 
  3. cd Python-3.6.4 
  4. ./configure --prefix=/opt/py36 --enable-optimizations 
  5. make && make install 

 

Collecting setuptools

Collecting pip

Installing collected packages: setuptools, pip

Successfully installed pip-9.0.1 setuptools-28.8.0

 

验证是否安装成功:

  1. [root@docker Python-3.6.4]# /opt/py36/bin/pip3 list 
  2.  
  3. DEPRECATION: The default format will switch to columns in the future. You can use --format=(legacy|columns) (or define a format=(legacy|columns) in your pip.conf under the [list] section) to disable this warning. 

 

出现这个提示可以修改配置文件或者直接添加参数:--format=(columns|legacy)

 

  1. [root@docker Python-3.6.4]# /opt/py36/bin/pip3 list --format=columns 
  2. Package    Version 
  3. ---------- ------- 
  4. pip        9.0.1   
  5. setuptools 28.8.0  

 

通过配置文件方式:在用户的家目录下创建一个目录:

  1. [root@docker py36]# mkdir ~/.pip 
  2. [root@docker py36]# cat >~/.pip/pip.conf <<EOF 
  3. > [list] 
  4. > format=columns 
  5. > EOF 

 

2、为了方便直接yum安装nginx [前提是要有epel源]

  1. yum install nginx -y  

 

添加到开机启动:

  1. systemctl enable nginx 
  2. systemctl start nginx 

 

检查是否成功运行Nginx:

  1. [root@docker yum.repos.d]# curl -I http://127.0.0.1 

3、通过pip3安装相关的插件

  1. [root@docker bin]# /opt/py36/bin/pip3 install virtualenv 
  2.  
  3. Collecting virtualenv 
  4.  
  5.   Could not fetch URL https://pypi.python.org/simple/virtualenv/: There was a problem confirming the ssl certificate: Can't connect to HTTPS URL because the SSL module is not available. - skipping 
  6.  
  7.   Could not find a version that satisfies the requirement virtualenv (from versions: ) 
  8.  
  9. No matching distribution found for virtualenv 

如果出现这样的情况,肯定是在编译Python3.6.4的时候,系统并没有安装上openssl-devel包;

解决办法:

  1. yum install openssl-devel -y  

 

再重新编译安装Python即可。

  1. root@docker Python-3.6.4]# /opt/py36/bin/pip3 install virtualenv 
  2.  
  3. Collecting virtualenv 
  4.  
  5.   Downloading virtualenv-15.1.0-py2.py3-none-any.whl (1.8MB) 
  6.  
  7.     100% |████████████████████████████████| 1.8MB 22kB/s  
  8.  
  9. Installing collected packages: virtualenv 
  10.  
  11. Successfully installed virtualenv-15.1.0 

 

安装完成后作一个软连接方便:

  1. [root@docker myproject]# ln -sf /opt/py36/bin/virtualenv /usr/bin/virtualenv 
  2.  
  3. [root@docker Python-3.6.4]# mkdir /opt/myproject 
  4.  
  5. [root@docker Python-3.6.4]# cd /opt/myproject/ 

 

创建一个虚拟环境:

 

  1. [root@docker myproject]# virtualenv py36env  
  2. Using base prefix '/opt/py36'  
  3. New python executable in /opt/myproject/py36env/bin/python3.6  
  4. Also creating executable in /opt/myproject/py36env/bin/python  
  5. Installing setuptools, pip, wheel...done. 

 

激活虚拟环境:

  1. [root@docker myproject]# source py36env/bin/activate 
  2. (py36env) [root@docker myproject]#  

 

安装flask和gunicorn,在上虚拟环境中安装:

  1. (py36env) [root@docker myproject]# pip3 install gunicorn flask 

 

 

创建一个简单的app程序:myapp.py

  1. from flask import Flask 
  2. app = Flask(__name__) 
  3.  
  4. @app.route("/") 
  5. def hello(): 
  6.     return "<h1 style='color:red'>Hello Python!</h1>
  7.  
  8. if __name__ == "__main__": 
  9.     app.run(host='0.0.0.0'

运行程序:

  1. (py36env) [root@docker myproject]# python3 myapp.py  
  2.  
  3.  * Running on http://0.0.0.0:5000/ (Press CTRL+C to quit) 
  4. 10.0.10.1 - - [21/Jan/2018 03:57:04] "GET / HTTP/1.1" 200 - 
  5. 10.0.10.1 - - [21/Jan/2018 03:57:04] "GET /favicon.ico HTTP/1.1" 404 - 

 

访问Url地址:http://10.0.10.29:5000  成功!

创建一个wsgi入口文件:wsgi.py

 

  1. from myproject import app 
  2.  
  3. if __name__ == "__main__": 
  4.  
  5.     app.run() 

 

启动程序:

  1. (py36env) [root@docker myproject]# gunicorn --bind 0.0.0.0:8000 wsgi:app  
  2.  
  3. [2018-01-21 04:08:20 +0800] [2094] [INFO] Starting gunicorn 19.7.1  
  4. [2018-01-21 04:08:20 +0800] [2094] [INFO] Listening at: http://0.0.0.0:8000 (2094)  
  5. [2018-01-21 04:08:20 +0800] [2094] [INFO] Using worker: sync  
  6. [2018-01-21 04:08:20 +0800] [2097] [INFO] Booting worker with pid: 2097  
  7. [2018-01-21 04:08:52 +0800] [2094] [CRITICAL] WORKER TIMEOUT (pid:2097)  
  8. [2018-01-21 04:08:52 +0800] [2097] [INFO] Worker exiting (pid: 2097)  
  9. [2018-01-21 04:08:53 +0800] [2099] [INFO] Booting worker with pid: 2099 

 

此时访问的时候不再是5000端口了,现在的端口是8000;

  1. [root@docker yum.repos.d]# curl -I http://10.0.10.29:8000 

为了方便添加一个开机启动gunicorn文件: /etc/systemd/system/myapp.service

 

  1. [Unit] 
  2. Description=Gunicorn instance to server myapp 
  3. After=network.target 
  4.  
  5. [Service] 
  6. User=nginx 
  7. Group=nginx 
  8. PrivateTmp=true 
  9. WorkingDirectory=/opt/myproject 
  10. Environment="PATH=/opt/myproject/py36env/bin" 
  11. ExecStart=/opt/myproject/py36env/bin/gunicorn --workers 3 --bind 0.0.0.0:8000 wsgi:app 
  12.  
  13. [Install] 
  14. WantedBy=multi-user.target 

 

启动程序:

  1. systemctl start myapp 

 

检查是否成功运行:

  1. [root@docker yum.repos.d]# systemctl status myapp 
  2.  
  3. ● myapp.service - Gunicorn instance to server myapp  
  4.    Loaded: loaded (/etc/systemd/system/myapp.service; disabled; vendor preset: disabled)  
  5.    Active: active (running) since Sun 2018-01-21 04:39:35 CST; 1min 6s ago  
  6.  Main PID: 2624 (gunicorn)  
  7.    Memory: 50.8M 
  8.  
  9.    CGroup: /system.slice/myapp.service  
  10.            ├─2624 /opt/myproject/py36env/bin/python3.6 /opt/myproject/py36env/bin/gunicorn --workers 3 --bind 0.0.0.0:8000...  
  11.            ├─2627 /opt/myproject/py36env/bin/python3.6 /opt/myproject/py36env/bin/gunicorn --workers 3 --bind 0.0.0.0:8000...  
  12.            ├─2628 /opt/myproject/py36env/bin/python3.6 /opt/myproject/py36env/bin/gunicorn --workers 3 --bind 0.0.0.0:8000... 
  13.            └─2637 /opt/myproject/py36env/bin/python3.6 /opt/myproject/py36env/bin/gunicorn --workers 3 --bind 0.0.0.0:8000... 
  14.  
  15.   
  16. Jan 21 04:39:35 docker systemd[1]: Starting Gunicorn instance to server myapp...  
  17. Jan 21 04:39:35 docker gunicorn[2624]: [2018-01-21 04:39:35 +0800] [2624] [INFO] Starting gunicorn 19.7.1  
  18. Jan 21 04:39:35 docker gunicorn[2624]: [2018-01-21 04:39:35 +0800] [2624] [INFO] Listening at: http://0.0.0.0:8000 (2624)  
  19. Jan 21 04:39:35 docker gunicorn[2624]: [2018-01-21 04:39:35 +0800] [2624] [INFO] Using worker: sync  
  20. Jan 21 04:39:35 docker gunicorn[2624]: [2018-01-21 04:39:35 +0800] [2627] [INFO] Booting worker with pid: 2627  
  21. Jan 21 04:39:35 docker gunicorn[2624]: [2018-01-21 04:39:35 +0800] [2628] [INFO] Booting worker with pid: 2628  
  22. Jan 21 04:39:35 docker gunicorn[2624]: [2018-01-21 04:39:35 +0800] [2629] [INFO] Booting worker with pid: 2629  
  23. Jan 21 04:40:11 docker gunicorn[2624]: [2018-01-21 04:40:11 +0800] [2624] [CRITICAL] WORKER TIMEOUT (pid:2629)  
  24. Jan 21 04:40:11 docker gunicorn[2624]: [2018-01-21 04:40:11 +0800] [2629] [INFO] Worker exiting (pid: 2629)  
  25. Jan 21 04:40:11 docker gunicorn[2624]: [2018-01-21 04:40:11 +0800] [2637] [INFO] Booting worker with pid: 2637 

 

添加到开机启动:

  1. [root@docker yum.repos.d]# systemctl enable myapp 
  2.  
  3. Created symlink from /etc/systemd/system/multi-user.target.wants/myapp.service to /etc/systemd/system/myapp.service. 

 

现在通过Nginx来反向代理跳转到刚才的Flask项目上;

/etc/nginx/conf.d/app.conf

这里由于只是测试环境,所以直接使用IP地址,前提是把默认的那个nginx.conf里的server注释掉,不然会跟这个配置冲突。

 

  1. server {  
  2.     listen 80;  
  3.     server_name default_server;  
  4.  
  5.  
  6.     location / {  
  7.         proxy_set_header Host $http_host;  
  8.         proxy_set_header X-Real-IP $remote_addr;  
  9.         proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 
  10.         proxy_set_header X-Forwarded-Proto $scheme;  
  11.         proxy_pass http://127.0.0.1:8000;  
  12.     }  

 

检查一下Nginx的配置,没有问题就可以启动Nginx服务了。此时直接访问IP地址,即可访问到我们的Flask项目了。