最近做的一个项目需要将原先服务器上部署好的环境重新搭建在新的服务器上,项目采用的是flask+uwsgi+nginx架构。在网上搜集资料踩坑无数,整整花了三天时间才把环境部署成功(前后一共部署了两次,两次都成功了)。我发现网上的部署教程绝大部分无法按照他给出的步骤最终实现成功部署,总会有步骤的遗漏导致中途要更换大量的教程,前前后后花费很多时间。而且,很多教程假定开发者在部署过程没有遇到任何报错,事实上,我在第二次部署的过程中,按照一模一样的步骤进行仍然遇到了第一次部署中没有出现的报错。因此,本文会尽可能给出详细的版本信息以及可能出现的问题解决,也请大家在遇到我没有提及的报错时,可以在评论区及时提醒我补全解决策略。
本文不涉及原理的解释,仅从如何部署成功的角度来进行说明,因此,如若读者想知道这样配置背后的原理,可以在CSDN查找其他的相关博文。
因为本文产生的背景是将一台服务器已搭建好的环境迁移到另一台服务器上,因此会有部分内容与flask+uwsgi+nginx+mysql部署不直接相关,包括数据库文件迁移等等,读者根据自身项目需要取用本文方法。
搭建Python环境包含两部分内容,一部分是ubuntu系统自身python版本的配置,一部分是uwsgi使用python版本的配置。
ubuntu@VM-0-6-ubuntu:/$ python -V
Python 2.7.17
ubuntu@VM-0-6-ubuntu:/$ python3 -V
Python 3.6.9
ubuntu系统自带了Python2.7和Python3.6,我所开发的项目需要用的Python版本为3.7,因此我参考了下述链接中给出的方法进行了Python3.7的安装与配置:
How to upgrade to python 3.7 on Ubuntu 18.10
腾讯云服务器实际运行如下:
ubuntu@VM-0-6-ubuntu:/$ sudo apt-get install python3.7
ubuntu@VM-0-6-ubuntu:/$ sudo update-alternatives --install /usr/bin/python3 python3 /usr/bin/python3.6 1
update-alternatives: using /usr/bin/python3.6 to provide /usr/bin/python3 (python3) in auto mode
ubuntu@VM-0-6-ubuntu:/$ sudo update-alternatives --install /usr/bin/python3 python3 /usr/bin/python3.7 2
update-alternatives: using /usr/bin/python3.7 to provide /usr/bin/python3 (python3) in auto mode
ubuntu@VM-0-6-ubuntu:/$ sudo update-alternatives --config python3
There are 2 choices for the alternative python3 (providing /usr/bin/python3).
Selection Path Priority Status
------------------------------------------------------------
* 0 /usr/bin/python3.7 2 auto mode
1 /usr/bin/python3.6 1 manual mode
2 /usr/bin/python3.7 2 manual mode
Press to keep the current choice[*], or type selection number:
ubuntu@VM-0-6-ubuntu:/$ python3 -V
Python 3.7.5
ubuntu@VM-0-6-ubuntu:/$ pip3 -V
pip 9.0.1 from /usr/lib/python3/dist-packages (python 3.7)
至此python3.7安装与配置完成,在控制台查看python3版本,默认指向python3.7,且pip3指向的安装地址也是python3.7。我之前参考过各类安装其他版本python的教程,链接给出的教程是最简单最方便的,推荐大家更换python版本时使用上述方法。
我们上述安装的python3.7是ubuntu系统现在默认使用的python3版本,而之后配置uwsgi时,我们可以指定uwsgi启动的python路径,(我的个人理解)但这个路径只能是python虚拟环境,因此我们要在服务器里安装virtualenv虚拟环境,参考的链接如下:
ubuntu 上用virtualenv安装python不同版本的开发环境
腾讯云服务器实际运行如下:
ubuntu@VM-0-6-ubuntu:/$ sudo apt-get install python-virtualenv
这里要注意,我们要安装的虚拟环境同样是python3.7版本,而且虚拟环境安装指令会将虚拟环境安装在当前目录下,因此我们可以新建一个目录专门用来存放各个不同的虚拟环境,方便我们开发其他项目时使用;也可以将虚拟环境安装在项目目录下。此处我选择新建一个目录专门存放各种虚拟环境。
ubuntu@VM-0-6-ubuntu:~$ mkdir env
ubuntu@VM-0-6-ubuntu:~$ ls
env
ubuntu@VM-0-6-ubuntu:~$ cd env
ubuntu@VM-0-6-ubuntu:~/env$ ls
ubuntu@VM-0-6-ubuntu:~/env$
进入到env目录后,我们用virtualenv命令新建一个python3.7的虚拟环境:
ubuntu@VM-0-6-ubuntu:~/env$ virtualenv -p /usr/bin/python3.7 py37env
Running virtualenv with interpreter /usr/bin/python3.7
Using base prefix '/usr'
/usr/lib/python3/dist-packages/virtualenv.py:1086: DeprecationWarning: the imp module is deprecated in favour of importlib; see the module's documentation for alternative uses
import imp
New python executable in /home/ubuntu/env/py37env/bin/python3.7
Also creating executable in /home/ubuntu/env/py37env/bin/python
Please make sure you remove any previous custom paths from your /home/ubuntu/.pydistutils.cfg file.
Installing setuptools, pkg_resources, pip, wheel...done.
ubuntu@VM-0-6-ubuntu:~/env$ ls
py37env
如果启用虚拟环境,我们会看到命令行前面会多一个括号出来,括号里是我们的虚拟环境名称,当前为未启用状态,现在我们将虚拟环境启动:
ubuntu@VM-0-6-ubuntu:~/env$ source py37env/bin/activate
(py37env) ubuntu@VM-0-6-ubuntu:~/env$ python -V
Python 3.7.5
(py37env) ubuntu@VM-0-6-ubuntu:~/env$ python3 -V
Python 3.7.5
(py37env) ubuntu@VM-0-6-ubuntu:~/env$ pip -V
pip 21.3.1 from /home/ubuntu/env/py37env/lib/python3.7/site-packages/pip (python 3.7)
(py37env) ubuntu@VM-0-6-ubuntu:~/env$ pip3 -V
pip 21.3.1 from /home/ubuntu/env/py37env/lib/python3.7/site-packages/pip (python 3.7)
此时python和python3都指向python3.7,pip和pip3均属于python3.7,虚拟环境配置成功。
我们在/home/ubuntu目录下新建一个test目录,用于后续flask、uwsgi以及nginx的测试,进入test目录,并在test目录下新建一个run.py文件,编写最简单的flask代码,进行flask运行情况测试:
(py37env) ubuntu@VM-0-6-ubuntu:~$ mkdir test
(py37env) ubuntu@VM-0-6-ubuntu:~$ ls
env test
(py37env) ubuntu@VM-0-6-ubuntu:~$ cd test
(py37env) ubuntu@VM-0-6-ubuntu:~/test$ vim run.py
简单的flask代码如下:
from flask import Flask
app = Flask(__name__)
@app.route('/')
def index():
return 'hello world'
if __name__ == '__main__':
app.run('0.0.0.0')
控制台当前处于虚拟环境下,安装flask包后,运行run.py:
(py37env) ubuntu@VM-0-6-ubuntu:~/test$ pip3 install flask
(py37env) ubuntu@VM-0-6-ubuntu:~/test$ python3 run.py
* Serving Flask app 'run' (lazy loading)
* Environment: production
WARNING: This is a development server. Do not use it in a production deployment.
Use a production WSGI server instead.
* Debug mode: off
* Running on all addresses.
WARNING: This is a development server. Do not use it in a production deployment.
* Running on http://2.2.2.2:5000/ (Press CTRL+C to quit)
此时打开浏览器,输入公网ip地址和端口号6.6.6.6:5000应该会显示hello world:
这里可能访问之后无法显示hello world或无法建立连接,那么有两个地方需要注意(其他教程大多只会修改第一部分,而忽略了第二部分):
设置腾讯云服务器的安全组,如下图所示位置:
我在这里图方便,就设置了开放全部端口,当然,仅就这次配置任务而言,开放22、80、443、5000、3306等端口就已经完全够用。
ubuntu@VM-0-6-ubuntu:~$ sudo ufw status
Status: inactive
ubuntu@VM-0-6-ubuntu:~$ sudo ufw enable
Command may disrupt existing ssh connections. Proceed with operation (y|n)? n
Aborted
这里我们看到防火墙处于关闭状态,我们也可以选择开启防火墙,然后手动将22、80、443、5000、3306等端口开启,但这里有一个大坑,就是当我们开启防火墙的时候,终端会提示打开防火墙会断开ssh连接,而ssh访问的是服务器的22端口,如果我们开启防火墙,很容易和服务器断开连接后无法登录,
ubuntu@VM-0-6-ubuntu:~$ sudo ufw enable
Command may disrupt existing ssh connections. Proceed with operation (y|n)? y
Firewall is active and enabled on system startup
ubuntu@VM-0-6-ubuntu:~$ sudo ufw allow 22
Rule added
Rule added (v6)
ubuntu@VM-0-6-ubuntu:~$ sudo ufw status
Status: active
To Action From
-- ------ ----
22 ALLOW Anywhere
22 (v6) ALLOW Anywhere (v6)
如果幸运的话,我们开启防火墙后仍可以保持和服务器的连接,那一定要赶快开启22端口;如果没来得及开启22端口,我们就只能通过腾讯云控制台提供的VNC登录,在里面进行防火墙的设置:
上述设置完成后,我们就可以正常通过6.6.6.6:5000访问到hello world页面。
uwsgi安装在本文里采用的是源码安装的方法,参考的链接如下(注意!按原教程方法可能出现报错!):
uwsgi下载安装配置(二)采用编译的方式安装uwsgi
首先,我们在项目目录/home/ubuntu下新建一个uwsgi文件夹,进入文件夹中,将最新的uwsgi安装包下载到该目录下面:
(py37env) ubuntu@VM-0-6-ubuntu:~$ mkdir uwsgi
(py37env) ubuntu@VM-0-6-ubuntu:~$ ls
env test uwsgi
(py37env) ubuntu@VM-0-6-ubuntu:~$ cd uwsgi/
(py37env) ubuntu@VM-0-6-ubuntu:~/uwsgi$ wget http://projects.unbit.it/downloads/uwsgi-latest.tar.gz
--2022-01-16 21:34:17-- http://projects.unbit.it/downloads/uwsgi-latest.tar.gz
Resolving projects.unbit.it (projects.unbit.it)... 148.251.4.146
Connecting to projects.unbit.it (projects.unbit.it)|148.251.4.146|:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 804906 (786K)
Saving to: ‘uwsgi-latest.tar.gz’
uwsgi-latest.tar.gz 100%[====================================>] 786.04K 25.7KB/s in 26s
2022-01-16 21:34:44 (30.2 KB/s) - ‘uwsgi-latest.tar.gz’ saved [804906/804906]
解压缩后,进入到最新版uwsgi的文件夹下,开始构建:
(py37env) ubuntu@VM-0-6-ubuntu:~/uwsgi$ tar -zxvf uwsgi-latest.tar.gz
(py37env) ubuntu@VM-0-6-ubuntu:~/uwsgi$ ls
uwsgi-2.0.20 uwsgi-latest.tar.gz
(py37env) ubuntu@VM-0-6-ubuntu:~/uwsgi$ cd uwsgi-2.0.20/
(py37env) ubuntu@VM-0-6-ubuntu:~/uwsgi/uwsgi-2.0.20$ python3 uwsgiconfig.py --build
此时按照原教程会出现下述报错:
In file included from plugins/python/python_plugin.c:1:0:
plugins/python/uwsgi_python.h:2:10: fatal error: Python.h: No such file or directory
#include
^~~~~~~~~~
compilation terminated.
一番查找后,解决办法如下:
(py37env) ubuntu@VM-0-6-ubuntu:~/uwsgi/uwsgi-2.0.20$ sudo apt-get install python3.7-dev
下载python3.7-dev包后,再次构建,发现构建成功:
(py37env) ubuntu@VM-0-6-ubuntu:~/uwsgi/uwsgi-2.0.20$ sudo python3 uwsgiconfig.py --build
############## end of uWSGI configuration #############
total build time: 9 seconds
*** uWSGI is ready, launch it with ./uwsgi ***
接着运行install指令(为避免奇奇怪怪的错误出现,建议能用sudo尽量用sudo):
(py37env) ubuntu@VM-0-6-ubuntu:~/uwsgi/uwsgi-2.0.20$ sudo python3 setup.py install
############## end of uWSGI configuration #############
total build time: 0 seconds
*** uWSGI is ready, launch it with /usr/local/bin/uwsgi ***
running build
running build_py
creating build
creating build/lib
copying uwsgidecorators.py -> build/lib
running install_lib
copying build/lib/uwsgidecorators.py -> /usr/local/lib/python3.7/dist-packages
byte-compiling /usr/local/lib/python3.7/dist-packages/uwsgidecorators.py to uwsgidecorators.cpython-37.pyc
running install_egg_info
running egg_info
creating uWSGI.egg-info
writing uWSGI.egg-info/PKG-INFO
writing dependency_links to uWSGI.egg-info/dependency_links.txt
writing top-level names to uWSGI.egg-info/top_level.txt
writing manifest file 'uWSGI.egg-info/SOURCES.txt'
reading manifest file 'uWSGI.egg-info/SOURCES.txt'
writing manifest file 'uWSGI.egg-info/SOURCES.txt'
Copying uWSGI.egg-info to /usr/local/lib/python3.7/dist-packages/uWSGI-2.0.20.egg-info
running install_scripts
通过ls命令可以看到当前目录下多了可执行的uwsgi,但由于现在不是全局命令,需要设置一个软链接:
(py37env) ubuntu@VM-0-6-ubuntu:~/uwsgi/uwsgi-2.0.20$ sudo ln -s /home/ubuntu/uwsgi/uwsgi-2.0.20/uwsgi /usr/bin/uwsgi
回到项目目录,进行测试,看看是否可以全局使用uwsgi:
(py37env) ubuntu@VM-0-6-ubuntu:~/uwsgi/uwsgi-2.0.20$ cd ~
(py37env) ubuntu@VM-0-6-ubuntu:~$ uwsgi
*** Starting uWSGI 2.0.20 (64bit) on [Sun Jan 16 21:53:57 2022] ***
compiled with version: 7.5.0 on 16 January 2022 13:46:17
os: Linux-4.15.0-159-generic #167-Ubuntu SMP Tue Sep 21 08:55:05 UTC 2021
nodename: VM-0-6-ubuntu
machine: x86_64
clock source: unix
detected number of CPU cores: 1
current working directory: /home/ubuntu
detected binary path: /usr/local/bin/uwsgi
!!! no internal routing support, rebuild with pcre support !!!
*** WARNING: you are running uWSGI without its master process manager ***
your processes number limit is 7188
your memory page size is 4096 bytes
detected max file descriptor number: 1024
lock engine: pthread robust mutexes
thunder lock: disabled (you can enable it with --thunder-lock)
The -s/--socket option is missing and stdin is not a socket.
至此,uwsgi安装成功。
在这里首先要提醒读者的一点是,测试uwsgi与flask连通与最终测试uwsgi、flask、nginx连通的uwsgi配置是不同的,且最根本的不同在于是采用http连接还是socket连接。我在一开始参考各种教程时忽略了这一点,导致我在安装nginx前,一直无法通过外网访问uwsgi+flask运行的结果(此处无法访问是因为设置了socket连接,socket连接在没有配置和启动nginx时无法通过外网访问)。因此在本文的教程中,为直观测试uwsgi+flask的连接,我们先采取http连接。
回到项目目录下的test文件夹中,我们新建一个uwsgi.ini文件,这个文件就是用来启动相应配置的uwsgi,我们在其中写入一些最基本的参数(关于如何具体写参数,我也不是很清楚,本文偏重于顺利安装),关键要注意设置成http而非socket:
(py37env) ubuntu@VM-0-6-ubuntu:~$ ls
env test uwsgi
(py37env) ubuntu@VM-0-6-ubuntu:~$ cd test
(py37env) ubuntu@VM-0-6-ubuntu:~/test$ ls
run.py
(py37env) ubuntu@VM-0-6-ubuntu:~/test$ vim uwsgi.ini
[uwsgi]
master = true
http=:5000
chdir = /home/ubuntu/test
wsgi-file=/home/ubuntu/test/run.py # 对应启动flask的文件
callable=app
processes=4
threads=2
buffer-size = 65536
vacuum=true
pidfile =/home/ubuntu/test/ubuntu/uwsgi.pid # 指定生成记录pid文件的地址
virtualenv=/home/ubuntu/env/py37env # 指定运行的python环境
配置完uwsgi,我们通过uwsgi启动flask,并再次访问6.6.6.6:5000,查看是否能正常访问:
(py37env) ubuntu@VM-0-6-ubuntu:~/test$ uwsgi --ini uwsgi.ini
[uWSGI] getting INI configuration from uwsgi.ini
*** Starting uWSGI 2.0.20 (64bit) on [Sun Jan 16 22:09:20 2022] ***
compiled with version: 7.5.0 on 16 January 2022 13:46:17
os: Linux-4.15.0-159-generic #167-Ubuntu SMP Tue Sep 21 08:55:05 UTC 2021
nodename: VM-0-6-ubuntu
machine: x86_64
clock source: unix
detected number of CPU cores: 1
current working directory: /home/ubuntu/test
writing pidfile to /home/ubuntu/test/uwsgi.pid
detected binary path: /usr/local/bin/uwsgi
!!! no internal routing support, rebuild with pcre support !!!
chdir() to /home/ubuntu/test
your processes number limit is 7188
your memory page size is 4096 bytes
detected max file descriptor number: 1024
lock engine: pthread robust mutexes
thunder lock: disabled (you can enable it with --thunder-lock)
uWSGI http bound on :5000 fd 4
uwsgi socket 0 bound to TCP address 127.0.0.1:39563 (port auto-assigned) fd 3
Python version: 3.7.5 (default, Dec 9 2021, 17:04:37) [GCC 8.4.0]
Set PythonHome to /home/ubuntu/env/py37env
Python main interpreter initialized at 0x564ba1da7da0
python threads support enabled
your server socket listen backlog is limited to 100 connections
your mercy for graceful operations on workers is 60 seconds
mapped 1031110 bytes (1006 KB) for 8 cores
*** Operational MODE: preforking+threaded ***
WSGI app 0 (mountpoint='') ready in 0 seconds on interpreter 0x564ba1da7da0 pid: 25595 (default app)
*** uWSGI is running in multiple interpreter mode ***
spawned uWSGI master process (pid: 25595)
spawned uWSGI worker 1 (pid: 25598, cores: 2)
spawned uWSGI worker 2 (pid: 25599, cores: 2)
spawned uWSGI worker 3 (pid: 25600, cores: 2)
spawned uWSGI worker 4 (pid: 25601, cores: 2)
spawned uWSGI http 1 (pid: 25602)
访问6.6.6.6:5000,页面正常显示hello world,至此uwsgi配置与测试成功。
这里我给出一个比较方便的,可以和后来的nginx关闭命令一起记忆:
(py37env) ubuntu@VM-0-6-ubuntu:~/test$ pkill -9 uwsgi
关闭nginx就是把uwsgi换成nginx。
本文安装nginx采用的也是源码安装,参考的链接如下:
ubuntu16.04源码编译安装nginx1.14.2
教程中给出的nginx版本较低,我们进入nginx.org官网,进行新版本的下载链接获取,我目前获取到的最新版本是1.20.2,下载链接为https://nginx.org/download/nginx-1.20.2.tar.gz。与安装uwsgi类似,我们在/usr/local目录下,新建nginx目录,进入nginx目录,通过wget进行安装包下载,下载后进行解压:
(py37env) ubuntu@VM-0-6-ubuntu:/usr/local$ sudo mkdir nginx
(py37env) ubuntu@VM-0-6-ubuntu:/usr/local$ ls
bin etc games include lib man nginx qcloud sa sbin share src yd.socket.server
(py37env) ubuntu@VM-0-6-ubuntu:/usr/local$ cd nginx
(py37env) ubuntu@VM-0-6-ubuntu:/usr/local/nginx$ sudo wget https://nginx.org/download/nginx-1.20.2.tar.gz
--2022-01-16 22:19:22-- https://nginx.org/download/nginx-1.20.2.tar.gz
Resolving nginx.org (nginx.org)... 3.125.197.172, 52.58.199.22, 2a05:d014:edb:5704::6, ...
Connecting to nginx.org (nginx.org)|3.125.197.172|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 1062124 (1.0M) [application/octet-stream]
Saving to: ‘nginx-1.20.2.tar.gz’
nginx-1.20.2.tar.gz 100%[====================================>] 1.01M 17.6KB/s in 55s
2022-01-16 22:20:19 (18.9 KB/s) - ‘nginx-1.20.2.tar.gz’ saved [1062124/1062124]
(py37env) ubuntu@VM-0-6-ubuntu:/usr/local/nginx$ sudo tar -zxvf nginx-1.20.2.tar.gz
进入解压好的nginx-1.20.2文件夹中,在编译源代码前,运行下列命令来安装依赖包:
(py37env) ubuntu@VM-0-6-ubuntu:/usr/local/nginx/nginx-1.20.2$ sudo apt-get update
Hit:1 http://mirrors.tencentyun.com/ubuntu bionic InRelease
Hit:2 http://mirrors.tencentyun.com/ubuntu bionic-security InRelease
Hit:3 http://mirrors.tencentyun.com/ubuntu bionic-updates InRelease
Traceback (most recent call last):
File "/usr/lib/cnf-update-db", line 8, in
from CommandNotFound.db.creator import DbCreator
File "/usr/lib/python3/dist-packages/CommandNotFound/db/creator.py", line 11, in
import apt_pkg
ModuleNotFoundError: No module named 'apt_pkg'
Reading package lists... Done
E: Problem executing scripts APT::Update::Post-Invoke-Success 'if /usr/bin/test -w /var/lib/command-not-found/ -a -e /usr/lib/cnf-update-db; then /usr/lib/cnf-update-db > /dev/null; fi'
E: Sub-process returned an error code
可以看到此处apt-get update出错,根据错误信息,我参考了如下链接的解决方式:
【问题解决】Linux下python报错:ModuleNotFoundError: No module named ‘apt_pkg‘
该问题是我们前文进行python升级导致,我们先退出虚拟环境,然后按照教程中的指令进行错误修复(教程中的python3.8都换成我们对应的python3.7版本):
(py37env) ubuntu@VM-0-6-ubuntu:/usr/local/nginx/nginx-1.20.2$ deactivate
ubuntu@VM-0-6-ubuntu:/usr/local/nginx/nginx-1.20.2$ sudo apt-get remove --purge python-apt
Reading package lists... Done
Building dependency tree
Reading state information... Done
Package 'python-apt' is not installed, so not removed
The following packages were automatically installed and are no longer required:
amd64-microcode intel-microcode iucode-tool
Use 'sudo apt autoremove' to remove them.
0 upgraded, 0 newly installed, 0 to remove and 65 not upgraded.
ubuntu@VM-0-6-ubuntu:/usr/local/nginx/nginx-1.20.2$ sudo apt-get install -f -y python3-apt
Reading package lists... Done
Building dependency tree
Reading state information... Done
python3-apt is already the newest version (1.6.5ubuntu0.7).
The following packages were automatically installed and are no longer required:
amd64-microcode intel-microcode iucode-tool
Use 'sudo apt autoremove' to remove them.
0 upgraded, 0 newly installed, 0 to remove and 65 not upgraded.
ubuntu@VM-0-6-ubuntu:/usr/local/nginx/nginx-1.20.2$ cd /usr/lib/python3/dist-packages/
ubuntu@VM-0-6-ubuntu:/usr/lib/python3/dist-packages$ sudo cp apt_pkg.cpython-36m-x86_64-linux-gnu.so apt_pkg.cpython-37m-x86_64-linux-gnu.so
ubuntu@VM-0-6-ubuntu:/usr/lib/python3/dist-packages$ sudo ln -s apt_pkg.cpython-37m-x86_64-linux-gnu.so apt_pkg.so
回到/usr/local/nginx/nginx-1.20.2目录,再次尝试update:
ubuntu@VM-0-6-ubuntu:/usr/local/nginx/nginx-1.20.2$ sudo apt-get update
Hit:1 http://mirrors.tencentyun.com/ubuntu bionic InRelease
Hit:2 http://mirrors.tencentyun.com/ubuntu bionic-security InRelease
Hit:3 http://mirrors.tencentyun.com/ubuntu bionic-updates InRelease
Reading package lists... Done
此时已恢复正常,我们继续相关依赖的安装和nginx的编译:
ubuntu@VM-0-6-ubuntu:/usr/local/nginx/nginx-1.20.2$ sudo apt-get install libpcre3 libpcre3-dev zlib1g-dev build-essential
ubuntu@VM-0-6-ubuntu:/usr/local/nginx/nginx-1.20.2$ sudo ./configure
Configuration summary
+ using system PCRE library
+ OpenSSL library is not used
+ using system zlib library
nginx path prefix: "/usr/local/nginx"
nginx binary file: "/usr/local/nginx/sbin/nginx"
nginx modules path: "/usr/local/nginx/modules"
nginx configuration prefix: "/usr/local/nginx/conf"
nginx configuration file: "/usr/local/nginx/conf/nginx.conf"
nginx pid file: "/usr/local/nginx/logs/nginx.pid"
nginx error log file: "/usr/local/nginx/logs/error.log"
nginx http access log file: "/usr/local/nginx/logs/access.log"
nginx http client request body temporary files: "client_body_temp"
nginx http proxy temporary files: "proxy_temp"
nginx http fastcgi temporary files: "fastcgi_temp"
nginx http uwsgi temporary files: "uwsgi_temp"
nginx http scgi temporary files: "scgi_temp"
当然,这里埋了一个伏笔,我们在后续要进行https的配置时,会出现一个报错(具体见后文),原因就出在我们在configure时,没有预先设置支持https,但是不急,我们可以先把这个问题放在这里,继续nginx的安装:
ubuntu@VM-0-6-ubuntu:/usr/local/nginx/nginx-1.20.2$ sudo make
ubuntu@VM-0-6-ubuntu:/usr/local/nginx/nginx-1.20.2$ sudo make install
切到路径:/usr/local/nginx/sbin,执行nginx启动命令,测试nginx是否安装成功:
ubuntu@VM-0-6-ubuntu:/usr/local/nginx/sbin$ sudo ./nginx
ubuntu@VM-0-6-ubuntu:/usr/local/nginx/sbin$ ps -ef | grep nginx
root 2505 1 0 22:38 ? 00:00:00 nginx: master process ./nginx
nobody 2506 2505 0 22:38 ? 00:00:00 nginx: worker process
ubuntu 2554 12702 0 22:38 pts/0 00:00:00 grep --color=auto nginx
nginx安装成功,并设置可以全局启动的nginx命令的软链接:
sudo ln -s /usr/local/nginx/sbin/nginx /usr/bin/nginx
我们回到项目目录/home/ubuntu下,先关闭已启动的nginx,测试nginx命令是否已经全局生效:
ubuntu@VM-0-6-ubuntu:~$ sudo pkill -9 nginx
ubuntu@VM-0-6-ubuntu:~$ sudo nginx
ubuntu@VM-0-6-ubuntu:~$ ps -ef | grep nginx
root 3075 1 0 22:41 ? 00:00:00 nginx: master process nginx
nobody 3076 3075 0 22:41 ? 00:00:00 nginx: worker process
ubuntu 3084 12702 0 22:41 pts/0 00:00:00 grep --color=auto nginx
至此,nginx安装成功。
nginx安装成功后,我们进入/usr/local/nginx/conf目录中查看并修改nginx.conf,nginx启动时会默认加载这个配置文件:
ubuntu@VM-0-6-ubuntu:~$ cd /usr/local/nginx/conf
ubuntu@VM-0-6-ubuntu:/usr/local/nginx/conf$ ls
fastcgi.conf koi-utf nginx.conf uwsgi_params
fastcgi.conf.default koi-win nginx.conf.default uwsgi_params.default
fastcgi_params mime.types scgi_params win-utf
fastcgi_params.default mime.types.default scgi_params.default
ubuntu@VM-0-6-ubuntu:/usr/local/nginx/conf$ sudo vim nginx.conf
user ubuntu;
worker_processes 1;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
server {
listen 80;
server_name localhost;
location / {
include uwsgi_params;
uwsgi_pass 127.0.0.1:5000;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
# HTTPS Server
#server {
# listen 443 ssl;
# server_name localhost;
# ssl_certificate cert.pem;
# ssl_certificate_key cert.key;
# ssl_session_cache shared:SSL:1m;
# ssl_session_timeout 5m;
# ssl_ciphers HIGH:!aNULL:!MD5;
# ssl_prefer_server_ciphers on;
# location / {
# root html;
# index index.html index.htm;
# }
#}
}
上述配置文件中值得注意的几个点:
配置好后,我们还要记得把uwsgi配置文件中连接方法改为socket,这样才会把uwsgi和nginx连通:
[uwsgi]
master = true
socket=:5000
chdir = /home/ubuntu/test
wsgi-file=/home/ubuntu/test/run.py
callable=app
processes=4
threads=2
buffer-size = 65536
vacuum=true
pidfile =/home/ubuntu/test/uwsgi.pid
virtualenv=/home/ubuntu/env/py37env
启动uwsgi和nginx,访问浏览器6.6.6.6:5000:
ubuntu@VM-0-6-ubuntu:~/test$ sudo nginx
ubuntu@VM-0-6-ubuntu:~/test$ uwsgi --ini uwsgi.ini
我们发现此时无法正常访问,这是因为配置nginx后,nginx会监听5000端口的内容,并把5000端口收到的信息转交到80端口,我们此时直接在浏览器中输入6.6.6.6,就可以正常访问到hello world页面。
至此,flask+uwsgi+nginx初始配置完成。
我们看到上述配置文件中有一部分被注释掉的部分,那一部分正是对https的配置。本项目由于在腾讯云服务器上构建,因此下述流程适用于腾讯云用户。
我参考了腾讯云官方给出的SSL证书安装部署方法,链接如下:
Nginx 服务器 SSL 证书安装部署
我们把从腾讯云服务器上下载的证书上传到服务器上后,在nginx配置文件中增加https配置:
user ubuntu;
worker_processes 1;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
server {
listen 80;
server_name localhost;
location / {
include uwsgi_params;
uwsgi_pass 127.0.0.1:5000;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
# HTTPS Server
server {
listen 443 ssl;
server_name localhost;
ssl_certificate cert.pem; # 注意修改成自己的xxx_bundle.crt路径地址
ssl_certificate_key cert.key; # 注意修改成自己的xxx.key路径地址
ssl_session_cache shared:SSL:1m;
ssl_session_timeout 5m;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
location / {
include uwsgi_params;
uwsgi_pass 127.0.0.1:5000;
}
}
}
启动nginx,我们会发现有报错:
ubuntu@VM-0-6-ubuntu:/usr/local/nginx/conf$ sudo nginx
nginx: [emerg] the "ssl" parameter requires ngx_http_ssl_module in /usr/local/nginx/conf/nginx.conf:33
如前文所述,这是因为我们一开始编译nginx时,并没有将https配置功能安装到nginx中,解决方法我参考了下述链接:
nginx: [emerg] the “ssl” parameter requires ngx_http_ssl_module in /usr/local/nginx/conf/nginx.conf:37
我们回到nginx源码安装地址中,查看nginx安装信息:
ubuntu@VM-0-6-ubuntu:/usr/local/nginx/conf$ cd /usr/local/nginx/nginx-1.20.2/
ubuntu@VM-0-6-ubuntu:/usr/local/nginx/nginx-1.20.2$ nginx -V
nginx version: nginx/1.20.2
built by gcc 7.5.0 (Ubuntu 7.5.0-3ubuntu1~18.04)
configure arguments:
可以看到,起初我们编译时并没有设置configure arguments,因此我们需要重新编译,将https模块加进去:
sudo ./configure --prefix=/usr/local/nginx --with-http_stub_status_module --with-http_ssl_module
./configure: error: SSL modules require the OpenSSL library.
You can either do not enable the modules, or install the OpenSSL library
into the system, or build the OpenSSL library statically from the source
with nginx by using --with-openssl= option.
出现报错,缺少OpenSSL库,这个简单,我们用apt安装之后再次尝试编译:
ubuntu@VM-0-6-ubuntu:/usr/local/nginx/nginx-1.20.2$ sudo apt-get install OpenSSL
Reading package lists... Done
Building dependency tree
Reading state information... Done
E: Unable to locate package OpenSSL
ubuntu@VM-0-6-ubuntu:/usr/local/nginx/nginx-1.20.2$ sudo apt-get install openssl
Reading package lists... Done
Building dependency tree
Reading state information... Done
The following packages were automatically installed and are no longer required:
amd64-microcode intel-microcode iucode-tool
Use 'sudo apt autoremove' to remove them.
The following packages will be upgraded:
openssl
1 upgraded, 0 newly installed, 0 to remove and 64 not upgraded.
Need to get 613 kB of archives.
After this operation, 1,024 B disk space will be freed.
Get:1 http://mirrors.tencentyun.com/ubuntu bionic-updates/main amd64 openssl amd64 1.1.1-1ubuntu2.1~18.04.14 [613 kB]
Fetched 613 kB in 1s (999 kB/s)
(Reading database ... 81640 files and directories currently installed.)
Preparing to unpack .../openssl_1.1.1-1ubuntu2.1~18.04.14_amd64.deb ...
Unpacking openssl (1.1.1-1ubuntu2.1~18.04.14) over (1.1.1-1ubuntu2.1~18.04.13) ...
Setting up openssl (1.1.1-1ubuntu2.1~18.04.14) ...
Processing triggers for man-db (2.8.3-2ubuntu0.1) ...
这里需要注意一点,openssl一定要小写,否则会报错,再次尝试编译:
./configure: error: SSL modules require the OpenSSL library.
You can either do not enable the modules, or install the OpenSSL library
into the system, or build the OpenSSL library statically from the source
with nginx by using --with-openssl= option.
仍然报错,查询资料后,发现ubuntu系统还要安装libssl-dev:
sudo apt-get install libssl-dev
sudo ./configure --prefix=/usr/local/nginx --with-http_stub_status_module --with-http_ssl_module
Configuration summary
+ using system PCRE library
+ using system OpenSSL library
+ using system zlib library
nginx path prefix: "/usr/local/nginx"
nginx binary file: "/usr/local/nginx/sbin/nginx"
nginx modules path: "/usr/local/nginx/modules"
nginx configuration prefix: "/usr/local/nginx/conf"
nginx configuration file: "/usr/local/nginx/conf/nginx.conf"
nginx pid file: "/usr/local/nginx/logs/nginx.pid"
nginx error log file: "/usr/local/nginx/logs/error.log"
nginx http access log file: "/usr/local/nginx/logs/access.log"
nginx http client request body temporary files: "client_body_temp"
nginx http proxy temporary files: "proxy_temp"
nginx http fastcgi temporary files: "fastcgi_temp"
nginx http uwsgi temporary files: "uwsgi_temp"
nginx http scgi temporary files: "scgi_temp"
这回终于成功了,我们继续执行make命令(注意make install不要执行):
ubuntu@VM-0-6-ubuntu:/usr/local/nginx/nginx-1.20.2$ sudo make
接着备份已安装好的nginx:
ubuntu@VM-0-6-ubuntu:/usr/local/nginx/nginx-1.20.2$ sudo cp /usr/local/nginx/sbin/nginx /usr/local/nginx/sbin/nginx.bak
如果nginx正在运行,停止nginx后,运行下列命令:
ubuntu@VM-0-6-ubuntu:/usr/local/nginx/nginx-1.20.2$ sudo cp ./objs/nginx /usr/local/nginx/sbin/
再次查看nginx安装信息:
ubuntu@VM-0-6-ubuntu:/usr/local/nginx/nginx-1.20.2$ nginx -V
nginx version: nginx/1.20.2
built by gcc 7.5.0 (Ubuntu 7.5.0-3ubuntu1~18.04)
built with OpenSSL 1.1.1 11 Sep 2018
TLS SNI support enabled
configure arguments: --prefix=/usr/local/nginx --with-http_stub_status_module --with-http_ssl_module
可以看到nginx的https模块已配置成功!我们重新启动nginx和uwsgi,访问浏览器https://6.6.6.6/,看看页面能否正常访问:
ubuntu@VM-0-6-ubuntu:~/test$ sudo nginx
ubuntu@VM-0-6-ubuntu:~/test$ uwsgi --ini uwsgi.ini
可以看到页面正常显示hello world,且此时通过https访问,至此nginx+uwsgi+flask+https的配置成功,后续读者根据自身项目需求调整其中的uwsgi.ini和nginx.conf即可。
这部分本文不作为重点,因此只给出亲测有效的安装配置链接:
Ubuntu18.04 安装MySQL
按照这篇文章给出的步骤安装配置,基本不会出现任何问题。
另附mysql数据文件迁移的教程链接,亲测有效:
在ubuntu上将mysql数据库数据迁移到另一台服务器上