Bottle, uwsgi and nginx are all pretty tools, which are popular for fast deployment. I love using Bottle for small apps due to its simplicity and usability (See also how to use Bottle on GAE). 

Bottle even makes you unaware of writting a web application.  

In this post, I will walk you through how to run Bottle app with uwsgi and nginx step by step. I will also show some pitfalls you might encounter. 

Step 1.  install everything needed: 

 

sudo apt-get install uwsgi uwsgi-plugin-python python-bottle nginx

As you can see, I am assuming you're using ubuntu/debian.

Step 2.  creat a project named 'bottlebasis' with following files/folds: 

bottlebasis
    plugins
    static
    views
    app.py

step 3:  coding with app.py, which pretty much does the main job. See a simple example

 

#!/usr/bin/python
'''
bottle with uwsgi and nginx
'''

import bottle
from bottle import template
import os



app = application = bottle.Bottle()
#bottle.TEMPLATE_PATH.insert(0, os.path.dirname(os.path.abspath(__file__)) +"/views")
#bottle.TEMPLATE_PATH.insert(0, os.path.dirname(os.path.abspath(__file__)))
#bottle.TEMPLATE_PATH.insert(0, '/data/Dropbox/python/web/bottlebasis/views')

@app.route('/static/<filename:path>')
def static(filename):
	'''
	Serve static files
	'''
	try:
		return bottle.static_file(filename, root='{}/static'.format(os.path.dirname(__file__)))
	except:
		return '{}/static'.format(os.path.dirname(os.path.abspath(__file__)))

@app.route('/')
def show_index():
	'''
	serve "index" page
	'''
	return 'Hello, this is the index page'

@app.route('/page/<name>')
def show_page(name):
	'''
	show how to use a simple template for rendering.
	'''
	#return str(bottle.TEMPLATE_PATH) ##+ 
	try:
		return template('page', url_name=name)
	except Exception, e:
		return "<p>Error: %s</p> <p>%s</p>" % (str(e), os.getcwd())


if __name__ == '__main__':
	bottle.run(app=app, host='0.0.0.0', port=8080) ##host='0.0.0.0', which makes visitable outside.

In order to quickly test your code, you can simple run 'python app.py'.

And then you should be able to see something expected at http://localhost:8080. 

Step 4: using uwsgi

create a file '/etc/uwsgi/apps-available/bottlebasis.ini' as follows:

 

[uwsgi]

#master-as-root = true
socket = /run/uwsgi/app/bottlebasis/socket
chdir = /data/Dropbox/python/web/bottlebasis
master = true
plugins = python
file = app.py
uid = www-data
gid = www-data
chmod-socket = 664
chown-socket = www-data:www-data
vacuum=true

chdir is your project directory. 

After that ln -s /etc/uwsgi/apps-available/bottlebasis.ini /etc/uwsgi/apps-enabled/bottlebasis.ini

Start the service

 

sudo service uwsig start

Step 5: start nginx

edit file "/etc/nginx/conf.d/bottle.conf"

 

upstream _bottle {
    server unix:/run/uwsgi/app/bottlebasis/socket;
}

server {
    listen [::]:80;
    listen 80;
    server_name testenglish.info;
    root /data/Dropbox/python/web/bottlebasis;

    location / {
        try_files $uri @uwsgi;
    }

    location @uwsgi {
        include uwsgi_params;
        uwsgi_pass _bottle;
    }
}

Then start the nginx serve: 

sudo service nginx start

Pitfalls:

1) chdir(): Permission denied [core/uwsgi.c line 2468]

2) 2014/04/14 11:32:35 [crit] 32295#0: *1 stat() "/data/Dropbox/python/web/bottlebasis/static/food.jpg" failed (13: Permission denied), client: 127.0.0.1, server: testenglish.info, request: "GET /static/food.jpg HTTP/1.1", host: "testenglish.info" 

    chmod -R +x /data/Dropbox/python/web/bottlebasis/

if there is something with nginx, you can use 'sudo nginx -t' to test the configuration file. 

 

 

The source code can be download from: https://github.com/jeffzhengye/bottle_uwsgi_nginx

 

 

 

 

 

 

 

 

 

 

 

 

 

Tags: bottle

Posted in python |

Leave a Reply