在 Ubuntu 上使用 Nginx 部署 Flask 应用 已翻译 100%

greatghoul 投递于 2013/09/26 09:13 (共 9 段, 翻译完成于 09-26)
阅读 65662
收藏 30
4
加载中

Having spent the majority of my career in the Microsoft stack, lately I’ve decided to step out of my comfort zone and to dive into the world of open source software. The project I’m currently working on at my day job is a RESTful service. The service will be running on a commodity hardware, that should be able to scale horizontally as needed. To do the job I’ve decided to use Flask and Nginx. Flask is a lightweight Python web framework, and nginx is a highly stable web server, that works great on cheap hardware.

In this post I will guide you through the process of installing and configuring nginx server to host Flask based applications. The OS I’ll be using is Ubuntu 13.04.

已有 1 人翻译此段
我来翻译

Prerequisites

Before we install Nginx and other required software, let’s install some prerequisites. First, we will need PIP and Virtualenv:

sudo apt-get install python-setuptools
sudo easy_install pip
sudo pip install virtualenv
To install nginx from apt-get, we have to add Nginx repositories to apt-get sources:
sudo add-apt-repository ppa:nginx/stable

Note: If the “add-apt-repository” command doesn’t exist on your Ubuntu version, you need to install the “software-properties-common” package: sudo apt-get install software-properties-common (Thanks to get_with_it for mentioning it in the comments)

Upgrade existing packages and make sure you have the required compilers and tools for uWSGI:

sudo apt-get update && sudo apt-get upgrade
sudo apt-get install build-essential python python-dev

已有 1 人翻译此段
我来翻译

Nginx

Install and start Nginx:

sudo apt-get install nginx
sudo /etc/init.d/nginx start
Nginx is a web server. It serves static files, however it cannot execute and host Python application. uWSGI fills that gap. Let’s install it first, and later we’ll configure nginx and uWSGI to talk to each other.
sudo pip install uwsgi

Milestone #1

Browse to your server and you should get the Nginx greeting page:

nginx

已有 1 人翻译此段
我来翻译

Sample application

The application we will host is literally a “Hello, world!” application. It will serve only one page, and guess what text it will contain. All the application related files will be stored at the /var/www/demoapp folder. Let’s create this folder, and initialize a virtual environment in it:

sudo mkdir /var/www
sudo mkdir /var/www/demoapp
Since we created the folder under root privileges, it is currently owned by the root user. Let’s change the ownership to the user you are logged in to (“ubuntu” in my case):
sudo chown -R ubuntu:ubuntu /var/www/demoapp/
Create and activate a virtual environment, and install Flask into it:
cd /var/www/demoapp
virtualenv venv
. venv/bin/activate
pip install flask
Create the hello.py file, with the following code:
from flask import Flask
app = Flask(__name__)

@app.route("/")
def hello():
    return "Hello World!"

if __name__ == "__main__":
    app.run(host='0.0.0.0', port=8080)

Milestone #2

Let’s execute the script we’ve just created:

python hello.py

Now you can browse to your server’s port 8080 and see the app in action:

flask

Note: I’ve used port 8080 because port 80 is already in use by nginx

Currently the app is served by Flask’s built in web server. It is a great tool for development and debugging needs, but it is not recommended in production environment. Let’s configure nginx to do the heavy lifting.

已有 1 人翻译此段
我来翻译

Configuring Nginx

Let’s start by removing the Nginx’s default site configuration:

sudo rm /etc/nginx/sites-enabled/default

Note: If you installed a version of nginx from other repository, the default configuration file may be located at the /etc/nginx/conf.d folder.

Instead create a new configuration file for our application /var/www/demoapp/demoapp_nginx.conf:

server {
    listen      80;
    server_name localhost;
    charset     utf-8;
    client_max_body_size 75M;

    location / { try_files $uri @yourapplication; }
    location @yourapplication {
        include uwsgi_params;
        uwsgi_pass unix:/var/www/demoapp/demoapp_uwsgi.sock;
    }
}
And symlink the new file to nginx’s configuration files directory and restart nginx:
sudo ln -s /var/www/demoapp/demoapp_nginx.conf /etc/nginx/conf.d/
sudo /etc/init.d/nginx restart

Milestone #3

Browser to server’s public ip address, and you will be greeted by an error:

502 No need to worry, this is a “good” error. It says that nginx uses the configuration file we just created, but it has a trouble connecting to our Python application host, uWSGI. The connection to uWSGI is defined in the configuration file at line #10:

uwsgi_pass unix:/var/www/demoapp/demoapp_uwsgi.sock;

It says that the communication between nginx and uWSGI is done via a socket file, that should be located at /var/www/demoapp/demoapp_uwsgi.sock. Since we still haven’t configured uWSGI yet, the file doesn’t exist, and Nginx returns the “bad gateway” error. Let’s fix this now.

已有 1 人翻译此段
我来翻译

Configuring uWSGI

Create a new uWSGI configuration file /var/www/demoapp/demoapp_uwsgi.ini:

[uwsgi]
#application's base folder
base = /var/www/demoapp

#python module to import
app = hello
module = %(app)

home = %(base)/venv
pythonpath = %(base)

#socket file's location
socket = /var/www/demoapp/%n.sock

#permissions for the socket file
chmod-socket    = 666

#the variable that holds a flask application inside the module imported at line #6
callable = app

#location of log files
logto = /var/log/uwsgi/%n.log
Let’s create a new directory for uwsgi log files, and change its owner to your user:
sudo mkdir -p /var/log/uwsgi
sudo chown -R ubuntu:ubuntu /var/log/uwsgi

Milestone #4

Let’s execute uWSGI and pass it the newly created configuration file:

uwsgi --ini /var/www/demoapp/demoapp_uwsgi.ini

Next, browse to your server. Now nginx should be able to connect to uWSGI process:

uwsgi

We are almost finished. The only thing left to do, is to configure uWSGI to run as a background service. That’s the duty of uWSGI Emperor.

已有 1 人翻译此段
我来翻译

uWSGI Emperor

uWSGI Emperor (quite a name, isn’t it?) is responsible for reading configuration files and spawing uWSGI processes to execute them. Create a new upstart configuration file to execute emperor - /etc/init/uwsgi.conf:

description "uWSGI"
start on runlevel [2345]
stop on runlevel [06]
respawn

env UWSGI=/usr/local/bin/uwsgi
env LOGTO=/var/log/uwsgi/emperor.log

exec $UWSGI --master --emperor /etc/uwsgi/vassals --die-on-term --uid www-data --gid www-data --logto $LOGTO
The last line executes the uWSGI daemon and sets it to look for config files in the /etc/uwsgi/vassals folder. Let’s create this folder and symlink the configuration file we created earlier into it:
sudo mkdir /etc/uwsgi && sudo mkdir /etc/uwsgi/vassals
sudo ln -s /var/www/demoapp/demoapp_uwsgi.ini /etc/uwsgi/vassals
Also, the last line states the the user that will be used to execute the daemon is www-data. For simplicity’s sake, let’s set him as the owner of the application and log folders:
sudo chown -R www-data:www-data /var/www/demoapp/
sudo chown -R www-data:www-data /var/log/uwsgi/

Note: The nginx version we installed earlier uses the “www-data” user for executing nginx. Nginx versions from other repositories may use a user named “nginx” instead.

Since both, nginx and uWSGI, are now being run by the same user, we can make a security improvement to our uWSGI configuration. Open up the uwsgi config file and change the value of chmod-socket from 666 to 644:

...
#permissions for the socket file
chmod-socket    = 644
Now we can start the uWSGI job:
sudo start uwsgi

Finally, both Nginx and uWSGI are configured to correctly serve our application on system start up.

已有 1 人翻译此段
我来翻译

Troubleshooting

If something goes wrong, the first place to check is the log files. By default, nginx writes error message to the file /var/log/nginx/errors.log.

We’ve configured uWSGI emperor to write it’s logs to /var/log/uwsgi/emperor.log. Also this folder contains separate log files for each configured application. In our case - /var/log/uwsgi/demoapp_uwsgi.log.

Static Files

If your application has to serve static files, the following rule should be added to the demoapp_nginx.conf file:

location /static {
    root /var/www/demoapp/;
}

As a result, all static files located at /var/www/demoapp/static will be served by nginx. (Bastianh, thanks for pointing this out)

已有 1 人翻译此段
我来翻译

Hosting Multiple Applications

If you want to host multiple Flask applications on a single server, create a separate folder for each application, as we did earlier, and symlink nginx and uWSGI configuration files to the appropriate folder.

Deploying Applications with Distribute

To deploy Flask apps using distribute, first follow the steps in Flask documentation to convert your application into a package. Next, copy the generated distribute setup package to the server, and use the virtual environment’s Python to install it. E.g.:

python setup.py install
And last but not least, the “app” property of uWSGI configuration’s file should be equal to name of the package that holds the Flask application.

已有 1 人翻译此段
我来翻译
本文中的所有译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接。
我们的翻译工作遵照 CC 协议,如果我们的工作有侵犯到您的权益,请及时联系我们。
加载中

评论(18)

p
panson3001
我补充一下 ,我使用的python3.6 安装uwsgi时报错:
------------------------------------------------------------
Command "/usr/bin/python3.6 -u -c "import setuptools, tokenize;__file__='/tmp/pip-install-3a5z0brf/uwsgi/setup.py';f=getattr(tokenize, 'open', open)(__file__);code=f.read().replace('\r\n', '\n');f.close();exec(compile(code, __file__, 'exec'))" install --record /tmp/pip-record-8hxf2cpm/install-record.txt --single-version-externally-managed --compile" failed with error code 1 in /tmp/pip-install-3a5z0brf/uwsgi/
-----------------------------------------------------------------
解决办法:apt-get install python3.6-dev
p
panson3001
谢谢题主!
c
coderzhu
我用sudo apt-get software-properties-common下载包的时候报错Invalid operation software-properties-common,操作无效?
付_林

引用来自“Nini_Australia”的评论

thunder lock: disabled (you can enable it with --thunder-lock)
The -s/--socket option is missing and stdin is not a socket.
what's this??
i have the same error.......... because you ini config file miss '[uwsgi]' at the beginning
Nini_Australia
Nini_Australia
thunder lock: disabled (you can enable it with --thunder-lock)
The -s/--socket option is missing and stdin is not a socket.
what's this??
b
billyxm
本来想在centos试一下,但是有点啊麻烦,安照楼主的办法一步一步来,达成!
ophui123
ophui123

引用来自“ghosthn2014”的评论

uWSGI Emperor 这一步做了,但是没用。uwsgi并没有启动
各配置必须调整成自己的相关路径,还要讲用户www-data改成自己的用户名,亲测,可行,但好像速度变慢了,不知道是网速问题不,待观察·
g
ghosthn2014
uWSGI Emperor 这一步做了,但是没用。uwsgi并没有启动
kylin5221
kylin5221
怎么不能上传文件到部署的服务上面
JefferyZh
JefferyZh
sudo apt-get software-properties-common
应该是sudo apt-get install software-properties-common吧
返回顶部
顶部