I would love to be able to use Python and Django for web applications at the company I work for. We currently use PHP because everyone is familiar with it and easy to deploy for a large number of clients. We can host anywhere between 10 to 100 websites on a single virtual server.
Is it possible to serve a number of websites from a single Apache and Python installation? Each website must have their own domain among other things, such as email accounts.
I wouldn't use Apache, the current best practice is an Nginx frontend proxying requests to uWSGI servers. Read about the uWSGI Emperor mode. It's very versatile. http://uwsgi-docs.readthedocs.org/en/latest/Emperor.html. Each individual app can be modified, removed added to dynamically. We use it at PythonAnywhere to serve thousands of web applications
There are other WSGI servers that you can use as well. uWSGI just seems the most scalable in my experience.
Yes, It is definitely possible. In our setup, typically we have django behind mod_wsgi, Apache and nginx
You can configure apache's Virtualhost, to point to a specific mod_wsgi which in turn points to specific code.
Quoting from here - Refer to the SO post for further information.
There are at least two methods you can try to serve from a single
instance:
Use apache + mod_wsgi and use the WSGIApplicationGroup and/or
WSGIProcessGroup directives. I've never needed these before so can't
be completely sure these will work the way you want, but regardless
you can definitely use mod_wsgi in daemon mode to greatly improve
your memory footprint.
You can play with Django middleware to deny/allow URLs based on the
request hostname (see HttpRequest.get_host() in the Django docs).
For that matter, even though it would be a slight performance hit,
you can put a decorator on all your views that checks the incoming
host.
Yes, you can easily serve up many sites using a single Apache / mod_wsgi installation. Typically you would do that with a separate virtualhost section for each website. See the virtualhost docs. You want to use a different servername directive in each virtual host config to specify what hostnames get routed to which config. See more detailed documentation in name based virtual hosts
Related
Is it possible to set two different django projects on the same IP address/server (Linode in this case)? For exmaple, django1_project running on www.example.com and django2_project on django2.example.com. This is preferable, but if this is not possible then how to make two djangos, i.e. one running on www.example.com/django1 and the second on www.example.com/django2? Do I need to adapt the settings.py, wsgi.py files or apache files (at /etc/apache2/sites-available) or something else?
Thank you in advance for your help!
Yes that's possible to host several Python powered sites with Apache + mod_wsgi from one host / Apache instance. The only constraint : all apps / sites must be powered by the same Python version, though each app may have (or not) its own virtualenv (which is strongly recommended). It is also recommended to use mod_wsgi daemon mode and have each Django site run in separate daemon process group.
I'm not familiar with Linode restrictions, but if you have control over your Apache files then you could certainly do it with name-based virtual hosting. Set up two VirtualHost containers with the same IP address and port (and this assumes that both www.example.com and django2.example.com resolve to that IP address) and then differentiate requests using the ServerName setting in the container. In Apache 2.4 name-based virtual hosting is automatic. In Apache 2.2 you need the NameVirtualHost directive.
I'm looking at the WSGI specification and I'm trying to figure out how servers like uWSGI fit into the picture. I understand the point of the WSGI spec is to separate web servers like nginx from web applications like something you'd write using Flask. What I don't understand is what uWSGI is for. Why can't nginx directly call my Flask application? Can't flask speak WSGI directly to it? Why does uWSGI need to get in between them?
There are two sides in the WSGI spec: the server and the web app. Which side is uWSGI on?
Okay, I think I get this now.
Why can't nginx directly call my Flask application?
Because nginx doesn't support the WSGI spec. Technically nginx could implement the WSGI spec if they wanted, they just haven't.
That being the case, we need a web server that does implement the spec, which is what the uWSGI server is for.
Note that uWSGI is a full fledged http server that can and does work well on its own. I've used it in this capacity several times and it works great. If you need super high throughput for static content, then you have the option of sticking nginx in front of your uWSGI server. When you do, they will communicate over a low level protocol known as uwsgi.
"What the what?! Another thing called uwsgi?!" you ask. Yeah, it's confusing. When you reference uWSGI you are talking about an http server. When you talk about uwsgi (all lowercase) you are talking about a binary protocol that the uWSGI server uses to talk to other servers like nginx. They picked a bad name on this one.
For anyone who is interested, I wrote a blog article about it with more specifics, a bit of history, and some examples.
NGINX in this case only works as a reverse proxy and render static files not the dynamic files, it receives the requests and proxies them to the application server, that would be UWSGI.
The UWSGI server is responsible for loading your Flask application using the WSGI interface. You can actually make UWSGI listen directly to requests from the internet and remove NGINX if you like, although it's mostly used behind a reverse proxy.
From the docs:
uWSGI supports several methods of integrating with web servers. It is also capable of serving HTTP requests by itself.
WSGI is just an interface specification, in simple terms, it tells you what methods should be implemented for passing requests and responses between the server and the application. When using frameworks such as Flask or Django, this is handled by the framework itself.
In other words, WSGI is basically a contract between python applications (Flask, Django, etc) and web servers (UWSGI, Gunicorn, etc). The benefit is that you can change web servers with little effort because you know they comply with the WSGI specification, which is actually one of the goals, as stated in PEP-333.
Python currently boasts a wide variety of web application frameworks, such as Zope, Quixote, Webware, SkunkWeb, PSO, and Twisted Web -- to name just a few 1. This wide variety of choices can be a problem for new Python users, because generally speaking, their choice of web framework will limit their choice of usable web servers, and vice versa.
A traditional web server does not understand or have any way to run Python applications. That's why WSGI server come in. On the other hand Nginx supports reverse proxy to handle requests and pass back responses for Python WSGI servers.
This link might help you: https://www.fullstackpython.com/wsgi-servers.html
There is an important aspect which we are missing . Flask and Django are web frameworks and we build web applications out of them . uWSGI or Gunicorn process the framework files . Consider it as a software application sitting in between the Django app and Nginx . uWSGI and Nginx communicate using WSGI but there is no communication interface between Django and uWSGI . Check out this video https://www.youtube.com/watch?v=WqrCnVAkLIo
In simple terms, just think of an analogy where you are running a CGI or PHP application with Nginx web server. You will use the respective handlers like php-fpm to run these files since the webserver, in its native form doesn't render these formats.
Do i need to use NginX or am i able to host it without it?
I am developing my first django project and am at the point where i can run the app project using the command:
./manage.py run_gunicorn -c config/gunicorn
I can then view it going to:
http://127.0.0.1:8000/resources/
I would now like to try hosting it so that other PCs can access this.
Gunicorn is wsgi http server. It is best to use Gunicorn behind HTTP proxy server. We strongly advise you to use nginx.
# http://gunicorn.org/#deployment
Although there are many HTTP proxies available, we strongly advise that you use Nginx. If you choose another proxy server you need to make sure that it buffers slow clients when you use default Gunicorn workers. Without this buffering Gunicorn will be easily susceptible to denial-of-service attacks.
# http://docs.gunicorn.org/en/latest/deploy.html
Of course not. You can use lighttpd or any other web server that supports WSGI, SCGI, FastCGI or AJP. You may refer to this python documentation and django documentation, and these two questions on stackoverflow: Cleanest & Fastest server setup for Django, Differences and uses between WSGI, CGI, FastCGI, and mod_python in regards to Python? might be also helpful.
You don't need a frontend proxy; you can put a standalone webserver like gunicorn directly in production. But there are various reasons why you probably want to use a frontend webserver anyway.
I'm running ubuntu with nginx with fastcgi, is that all I need to serve python apps also?
You'll probably also need flup to bridge wsgi and fcgi. You obviously need Python, and whatever libraries your app depends upon. Likely need a database and the appropriate connectors as well, but that should all be in the documentation of whatever project you're trying to host (or framework you're using to write with).
Short answer: almost.
Or should I be using a totally different server?
Nginx with mod_wsgi requires the use of a non-blocking asynchronous framework and setup and isn't likely to work out of box with Pylons.
I usually go with the proxy route to a stand-alone Pylons process using the PasteScript#cherrypy WSGI server (as its higher performing than the Paste#http one, though it won't recycle threads if you have leaks...).
If you're set on using Apache and its your server (so you can compile and run Apache mod_wsgi), I'd suggest using that setup as its less maintenance to effectively utilize multiple cores. With a proxy setup, you'd have to use the mod_proxy_balancer with multiple paste processes to effectively utilize multiple cores/cpus.
If you're deploying to someone else's Apache (shared hosting), mod_proxy is generally the easier solution as its stock in Apache 2.2 and above.
Personally, I usually deploy with nginx + proxy to multiple paster processes.
I've also used mod_fastcgi + flup to great success several times now. There are a couple of recipes floating around for setting this up, but unfortunately it will probably still require some tweaking on your part to get everything working:
http://wiki.pylonshq.com/display/pylonscookbook/Production+Deployment+Using+Apache,+FastCGI+and+mod_rewrite