Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Deploying Flask (WSGI) Applications
Search
Matt Wright
June 26, 2014
Technology
3
1.7k
Deploying Flask (WSGI) Applications
Supporting files:
https://github.com/mattupstate/flask-nyc-deploying
Matt Wright
June 26, 2014
Tweet
Share
More Decks by Matt Wright
See All by Matt Wright
Python Apps and Docker
mattupstate
1
1.3k
Testing Flask Applications
mattupstate
5
1.6k
Other Decks in Technology
See All in Technology
Digitization部 紹介資料
sansan33
PRO
1
6.8k
マーケットプレイス版Oracle WebCenter Content For OCI
oracle4engineer
PRO
5
1.6k
Introduction to Sansan for Engineers / エンジニア向け会社紹介
sansan33
PRO
6
68k
Bedrock PolicyでAmazon Bedrock Guardrails利用を強制してみた
yuu551
0
230
AI駆動PjMの理想像 と現在地 -実践例を添えて-
masahiro_okamura
1
110
Claude_CodeでSEOを最適化する_AI_Ops_Community_Vol.2__マーケティングx_AIはここまで進化した.pdf
riku_423
2
560
ブロックテーマでサイトをリニューアルした話 / 2026-01-31 Kansai WordPress Meetup
torounit
0
470
Context Engineeringが企業で不可欠になる理由
hirosatogamo
PRO
3
580
CDKで始めるTypeScript開発のススメ
tsukuboshi
1
400
20260208_第66回 コンピュータビジョン勉強会
keiichiito1978
0
130
コスト削減から「セキュリティと利便性」を担うプラットフォームへ
sansantech
PRO
3
1.5k
Ruby版 JSXのRuxが気になる
sansantech
PRO
0
150
Featured
See All Featured
Git: the NoSQL Database
bkeepers
PRO
432
66k
For a Future-Friendly Web
brad_frost
182
10k
Pawsitive SEO: Lessons from My Dog (and Many Mistakes) on Thriving as a Consultant in the Age of AI
davidcarrasco
0
64
The Anti-SEO Checklist Checklist. Pubcon Cyber Week
ryanjones
0
62
コードの90%をAIが書く世界で何が待っているのか / What awaits us in a world where 90% of the code is written by AI
rkaga
60
42k
Odyssey Design
rkendrick25
PRO
1
490
Everyday Curiosity
cassininazir
0
130
Designing Powerful Visuals for Engaging Learning
tmiket
0
230
How People are Using Generative and Agentic AI to Supercharge Their Products, Projects, Services and Value Streams Today
helenjbeal
1
120
HU Berlin: Industrial-Strength Natural Language Processing with spaCy and Prodigy
inesmontani
PRO
0
210
Let's Do A Bunch of Simple Stuff to Make Websites Faster
chriscoyier
508
140k
The Spectacular Lies of Maps
axbom
PRO
1
520
Transcript
Deploying Flask (WSGI) Applications
Matt Wright @mattupstate Engineer @ChatID • Python, Ruby, CoffeeScript •
Flask, Chef, AngularJS Open Source • Flask-Security • Flask-Social • Flask-Mail + a few others
WSGI (Web Server Gateway Interface)
PEP 333 http://legacy.python.org/dev/peps/pep-0333/
# ~/hello.py def application(environ, start_response): start_response('200 OK', [('Content-Type','text/html')]) return ["Hello
World"]
# ~/app.py from flask import Flask app = Flask(__name__) @app.route('/')
@app.route('/<path:path>') def catch_all(path=''): return 'Hello World'
Browser WSGI Gateway WSGI App 1 2 4 3 Request
Flow
Browser WSGI Gateway WSGI App 1 1. Browser sends an
HTTP request to the gateway server Request Flow
Browser WSGI Gateway WSGI App 2 2. Gateway server prepares
and sends the request to the WSGI compatible application 1 Request Flow
Browser WSGI Gateway WSGI App 1 2 3 3. Application
processes the request and returns a response Request Flow
Browser WSGI Gateway WSGI App 1 2 4 3 4.
The gateway server returns the response to the browser Request Flow
Browser WSGI Gateway WSGI Middle- ware WSGI App Middleware
Browser WSGI Gateway WSGI Middle- ware WSGI App WSGI Middle-
ware WSGI Middle- ware WSGI Middle- ware WSGI Middle- ware MOAR MIDDLEWARE!
Gateway Servers (sometimes called “containers”)
http://www.tornadoweb.org/ Tornado
1. Written in Python! 2. Web application framework 3. Asynchronous
networking library 4. WSGI support Tornado
# ~/tor.py from tornado.wsgi import WSGIContainer from tornado.httpserver import HTTPServer
from tornado.ioloop import IOLoop from app import app http_server = HTTPServer(WSGIContainer(app)) http_server.listen(8000) IOLoop.instance().start()
matt @ pc in ~/ $ mkvirtualenv wsgi matt @
pc in ~/ workon:wsgi $ pip install flask tornado matt @ pc in ~/ workon:wsgi $ python tor.py
matt @ pc in ~/ $ curl localhost:8000 Hello World
matt @ pc in ~/ workon:wsgi $ pip install tornado matt @ pc in ~/ workon:wsgi $ python tor.py
http://www.gevent.org/ gevent
1. Written in Python! 2. Coroutine networking library 3. 3rd
party module support gevent
# ~/ge.py from gevent.wsgi import WSGIServer from app import app
server = WSGIServer(('', 8000), app) server.serve_forever()
matt @ pc in ~/ workon:wsgi $ pip install gevent
matt @ pc in ~/ workon:wsgi $ python ge.py
matt @ pc in ~/ $ curl localhost:8000 Hello World
matt @ pc in ~/ workon:wsgi $ pip install gevent matt @ pc in ~/ workon:wsgi $ python ge.py 127.0.0.1 - - [2014-06-24...
http://gunicorn.org/ Gunicorn
Gunicorn 1. Written in Python! 2. Easy configuration 3. Broadly
compatible 4. Extensible 5. Fairly speedy
matt @ pc in ~/ workon:wsgi $ pip install gunicorn
matt @ pc in ~/ workon:wsgi $ gunicorn app:app
matt @ pc in ~/ $ curl localhost:8000 Hello World
matt @ pc in ~/ $ mkvirtualenv wsgi matt @ pc in ~/ workon:wsgi $ pip install gunicorn flask matt @ pc in ~/ workon:wsgi $ gunicorn app:app
https://uwsgi-docs.readthedocs.org/ uWSGI
uWSGI 1. Support for many platforms and languages 2. Multiple
configuration formats 3. Flexible logging 4. Extensible 5. Speaks HTTP and uwsgi
matt @ pc in ~/ workon:wsgi $ pip install uwsgi
matt @ pc in ~/ workon:wsgi $ uwsgi --http :8000 -w app:app ... spawned uWSGI worker 1 ...
matt @ pc in ~/ $ curl localhost:8000 Hello World
matt @ pc in ~/ workon:wsgi $ pip install uwsgi matt @ pc in ~/ workon:wsgi $ uwsgi --http :8000 -w app:app ... spawned uWSGI worker 1 ... [pid: 42176|app: 0|req: ...
(how to start your app) Process Management
http://upstart.ubuntu.com/ upstart
# /etc/init/hello-world.conf description "Hello World app" start on runlevel [2345]
stop on runlevel [06] chdir /srv/hello-world exec /usr/local/bin/uwsgi \ --die-on-term \ --http :8000 \ -w app:app
http://www.freedesktop.org/wiki/Software/systemd/ systemd
# /etc/systemd/system/hello-world.service [Unit] Description=Hello World app [Service] ExecStart=/usr/local/bin/uwsgi \ --die-on-term
\ --http :8000 \ -w app:app [Install] WantedBy=multi-user.target
http://supervisord.org/ supervisord
# /etc/supervisor.d/hello-world.conf [program:hello-world] directory=/srv/hello-world command=/usr/local/bin/uwsgi \ --die-on-term \ --http :8000
\ -w app:app
(some things are better than others) Reverse Proxies
Why? • Static files • URL rewrites • Routing •
Header mods • App aggregation • and many more! • Network security • Authentication • Load balancing • SSL termination • Compression • Caching
http://www.nginx.org/ Apache
# /etc/apache2/sites-enabled/hello-world.conf <VirtualHost *:80> ServerName hello-world.com ProxyPreserveHost On ProxyPass /static
! Alias /static "/srv/hello-world/static" ProxyPass / http://127.0.0.1:8000/ ProxyPassReverse / http://127.0.0.1:8000/ </VirtualHost>
http://www.nginx.org/ Nginx
# /etc/nginx/sites-enabled/hello-world.conf server { listen 80; server_name hello-world.com; location /
{ proxy_pass http://127.0.0.1:8000; } location ^~ /static/ { root /srv/hello-world/static; } }
(is hard) Concurrency
Concurrency Models callback/generator (auto) lightweight threads (auto) processor/thread (config) processor/thread
(config) Tornado gevent Gunicorn uWSGI
Increasing Concurrency processes processes workers + processes workers + processes
Tornado gevent Gunicorn uWSGI
Increasing Workers Gunicorn uWSGI --workers <integer> --workers <integer>
DISCLAIMER!
(when one server isn’t enough) Load Balancing
Machine Level App Server 192.168.1.101 App Server 192.168.1.102 App Server
192.168.1.102 Primary Load Balancer 192.168.1.100
# /etc/nginx/sites-enabled/load-balancer.conf upstream app_upstream { least_conn; server 192.168.1.101:8000 server 192.168.1.102:8000
server 192.168.1.103:8000 } server { listen 80; server_name hello-world.com; location / { proxy_pass http://app_upstream; } }
Machine + Process Level App Server 192.168.1.101 App Server 192.168.1.102
App Server 192.168.1.102 Primary Load Balancer 192.168.1.100 t 127.0.0.1:8001 127.0.0.1:8002 127.0.0.1:8000 127.0.0.1:8000 127.0.0.1:8001 127.0.0.1:8002 127.0.0.1:8000 127.0.0.1:8001 127.0.0.1:8002
# /etc/supervisor.d/hello-world.conf [program:hello-world] numprocs=3 process_name=hello-world%(process_num) directory=/srv/hello-world command=/usr/local/bin/uwsgi \ --die-on-term \
--http :80%(process_num)02d \ -w app:app
# /etc/nginx/sites-enabled/hello-world.conf upstream local_upstream { least_conn; server 127.0.0.1:8000 server 127.0.0.1:8001
server 127.0.0.1:8002 } server { listen 80; server_name hello-world.com; location / { proxy_pass http://local_upstream; } }
(I’ve failed at this a lot) Recommendations
1. Use virtualenv and pip 2. Don’t use virtualenvwrapper 3.
Use a `requirements.txt` file Python
1. Provide default settings 2. Enable settings to be overridden
a. Environment Variable(s) b. Default file locations 3. Raise an error at startup when required settings are missing 4. Generate a `SECRET_KEY` with `os. urandom(16)` Configuration
1. Prefer the uwsgi protocol over HTTP 2. Prefer TCP
sockets over Unix sockets 3. Lots of useful options a. virtualenv + pythonpath b. enable-threads + lazy-apps c. need-app d. stats Use uWSGI
1. Pass custom headers 2. Lots of useful modules a.
ngx_http_geoip_module b. ngx_http_gzip_module c. ngx_http_memcached_module d. ngx_http_status_module Use Nginx
(putting it all together) Automation
http://www.ansible.com/ Ansible
(because what could go wrong?) Demo
Thank You! mattupstate.com gittip.com/mattupstate github.com/mattupstate twitter.com/mattupstate