Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Deploying Flask (WSGI) Applications

Deploying Flask (WSGI) Applications

Avatar for Matt Wright

Matt Wright

June 26, 2014
Tweet

More Decks by Matt Wright

Other Decks in Technology

Transcript

  1. Matt Wright @mattupstate Engineer @ChatID • Python, Ruby, CoffeeScript •

    Flask, Chef, AngularJS Open Source • Flask-Security • Flask-Social • Flask-Mail + a few others
  2. # ~/app.py from flask import Flask app = Flask(__name__) @app.route('/')

    @app.route('/<path:path>') def catch_all(path=''): return 'Hello World'
  3. Browser WSGI Gateway WSGI App 1 1. Browser sends an

    HTTP request to the gateway server Request Flow
  4. Browser WSGI Gateway WSGI App 2 2. Gateway server prepares

    and sends the request to the WSGI compatible application 1 Request Flow
  5. Browser WSGI Gateway WSGI App 1 2 3 3. Application

    processes the request and returns a response Request Flow
  6. Browser WSGI Gateway WSGI App 1 2 4 3 4.

    The gateway server returns the response to the browser Request Flow
  7. Browser WSGI Gateway WSGI Middle- ware WSGI App WSGI Middle-

    ware WSGI Middle- ware WSGI Middle- ware WSGI Middle- ware MOAR MIDDLEWARE!
  8. 1. Written in Python! 2. Web application framework 3. Asynchronous

    networking library 4. WSGI support Tornado
  9. # ~/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()
  10. matt @ pc in ~/ $ mkvirtualenv wsgi matt @

    pc in ~/ workon:wsgi $ pip install flask tornado matt @ pc in ~/ workon:wsgi $ python tor.py
  11. matt @ pc in ~/ $ curl localhost:8000 Hello World

    matt @ pc in ~/ workon:wsgi $ pip install tornado matt @ pc in ~/ workon:wsgi $ python tor.py
  12. # ~/ge.py from gevent.wsgi import WSGIServer from app import app

    server = WSGIServer(('', 8000), app) server.serve_forever()
  13. matt @ pc in ~/ workon:wsgi $ pip install gevent

    matt @ pc in ~/ workon:wsgi $ python ge.py
  14. 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...
  15. Gunicorn 1. Written in Python! 2. Easy configuration 3. Broadly

    compatible 4. Extensible 5. Fairly speedy
  16. matt @ pc in ~/ workon:wsgi $ pip install gunicorn

    matt @ pc in ~/ workon:wsgi $ gunicorn app:app
  17. 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
  18. uWSGI 1. Support for many platforms and languages 2. Multiple

    configuration formats 3. Flexible logging 4. Extensible 5. Speaks HTTP and uwsgi
  19. matt @ pc in ~/ workon:wsgi $ pip install uwsgi

    matt @ pc in ~/ workon:wsgi $ uwsgi --http :8000 -w app:app ... spawned uWSGI worker 1 ...
  20. 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: ...
  21. # /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
  22. Why? • Static files • URL rewrites • Routing •

    Header mods • App aggregation • and many more! • Network security • Authentication • Load balancing • SSL termination • Compression • Caching
  23. # /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>
  24. # /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; } }
  25. 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
  26. # /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; } }
  27. 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
  28. # /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; } }
  29. 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
  30. 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
  31. 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