Skip to main content

uWSGI Basic Django Setup

Here are two basic examples of almost the same uWSGI configuration to run a Django project; one is configured via an ini configuration file and the other is configured via a command line argument.

This does not represent a production-ready example, but can be used as a starting point for the configuration.

Setup for this example:
# create dir for virtualenv and activate
mkdir envs/
virtualenv envs/runrun/
. ./envs/runrun/bin/activate

# create dir for project codebase
mkdir proj/

# install some django deps
pip install django uwsgi whitenose

# create a new django project
cd proj/
django-admin startproject runrun
cd runrun/

# Add to or modify django settings.py to setup static file serving with Whitenoise.
# Note: for prod environments, staticfiles can be served via Nginx.
# settings.py 
MIDDLEWARE_CLASSES = [
    ....
    'whitenoise.middleware.WhiteNoiseMiddleware',

]
STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles')
STATICFILES_STORAGE = 'whitenoise.storage.CompressedManifestStaticFilesStorage'

Create the config file
$ cat run.ini 
[uwsgi]
module = runrun.wsgi:application
virtualenv = ../../envs/runrun/
env = DJANGO_SETTINGS_MODULE=runrun.settings 
env = PYTHONPATH="$PYTHONPATH:./runrun/" 
master = true
processes = 5
enable-threads = true
max-requests = 5000
harakiri = 20
vacuum = true
http = :7777
stats = 127.0.0.1:9191

Execute config
uwsgi --ini run.ini

Or create a shell script
$ cat run.sh
 uwsgi --module=runrun.wsgi:application \
      -H ../../envs/runrun/ \
      --env DJANGO_SETTINGS_MODULE=runrun.settings \
      --env PYTHONPATH="$PYTHONPATH:./runrun/" \
      --master \
      --processes=5 \
      --max-requests=5000 \
      --harakiri=20 \
      --vacuum \
      --http=127.0.0.1:7777 \
      --stats 127.0.0.1:9191 

Execute the shell script:
./run.sh

Command line reference
--env = set environment variable
--max-requests = reload workers after the specified amount of managed requests
--https2 = http2.0
--http = run in http mode
--socket = use in place of http if using an Nginx reverse proxy
--vacuum = clear environment on exit; try to remove all of the generated file/sockets
--uid = setuid to the specified user/uid
--gid = setgid to the specified group/gid
--stats = run a stats server
--H, --virtualenv = virtualenv dir
--processes = num of worker processes
--module = python module entry point

Comments

Popular posts from this blog

Django: Using Caching to Track Online Users

Recently I wanted a simple solution to track whether a user is online on a given Django site.  The definition of "online" on a site is kind of ambiguous, so I'll define that a user is considered to be online if they have made any request to the site in the last five minutes. I found that one approach is to use Django's caching framework to track when a user last accessed the site.  For example, upon each request, I can have a middleware set the current time as a cache value associated with a given user.  This allows us to store some basic information about logged-in user's online state without having to hit the database on each request and easily retrieve it by accessing the cache. My approach below.  Comments welcome. In settings.py: # add the middleware that you are about to create to settings MIDDLEWARE_CLASSES = ( .... 'middleware.activeuser_middleware.ActiveUserMiddleware' , .... ) # Setup caching per Django docs. In actuality, you

Docker: Run as non root user

It's good practice to run processes within a container as a non-root user with restricted permissions.  Even though containers are isolated from the host operating system, they do share the same kernel as the host. Also, processes within a container should be prevented from writing to where they shouldn't be allowed to as extra protection against exploitation. Running a Docker process as a non-root user has been a Docker feature as of version 1.10. To run a Docker process as a non-root user, permissions need to be accounted for meticulously.  This permission adjustment needs to be done when building a Dockerfile. You need to be aware of where in the filesystem your app might write to, and adjust the permissions accordingly.  Since everything in a container is considered disposable, the container process really shouldn't be writing to too many locations once build. Here is an annotated example of how you might create a Dockerfile where the process that runs within runs a

Django Models Mixins

One thing I've been experimenting with is model Mixins.  For example, the aim is to create small abstract classes that are each focused around a particular function.  These abstract classes can then be added to arbitrary models to apply those functions to models as desired. For example, say I define a RatingsFields abstract class and a TrackingFields abstract class.  These abstract classes can be mixed into any other model that we wish to add rating or tracking functionality to. core/mixins.py from djangoratings.fields import RatingField # 3rd party module class RatingFields(models.Model): rating = RatingField( range =5) # 5 possible rating values, 1-5 class Meta: abstract = True class TrackingFields(models.Model): deleted_on = models.DateTimeField(blank= True , null= True ) created = models.DateTimeField(auto_now_add= True ) modified = models.DateTimeField(auto_now= True ) class Meta: abstract = True