This tutorial is out of date and no longer maintained.
This article is no longer being maintained. It uses a One-Click app that has been deprecated.
See Instead: An updated version of this article is available here: How To Use the Django One-Click Install Image for Ubuntu 16.04. It uses the Django 1.8.7 on Ubuntu 16.04 One-Click app instead.
Django is a high-level Python framework for developing web applications rapidly. DigitalOcean’s Django One-Click app quickly deploys a preconfigured development environment to your VPS employing Django, Nginx, Gunicorn, and Postgres.
To use the image, select Django on Ubuntu 14.04 from the Applications menu during droplet creation:
Once you create the droplet, navigate to your droplet’s IP address (http://your.ip.address) in a browser, and verify that Django is running:
You can now login to your droplet as root and read the Message of the Day, which contains important information about your installation:
This information includes the username and password for both the Django user and the Postgres database. If you need to refer back to this latter, the information can be found in the file /etc/motd.tail
The Django project is served by Gunicorn which listens on port 9000 and is proxied by Nginx which listens on port 80.
The Nginx configuration is located at /etc/nginx/sites-enabled/django
:
upstream app_server {
server 127.0.0.1:9000 fail_timeout=0;
}
server {
listen 80 default_server;
listen [::]:80 default_server ipv6only=on;
root /usr/share/nginx/html;
index index.html index.htm;
client_max_body_size 4G;
server_name _;
keepalive_timeout 5;
# Your Django project's media files - amend as required
location /media {
alias /home/django/django_project/django_project/media;
}
# your Django project's static files - amend as required
location /static {
alias /home/django/django_project/django_project/static;
}
location / {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_redirect off;
proxy_pass http://app_server;
}
}
If you rename the project folder, remember to change the path to your static files.
Gunicorn is started on boot by an Upstart script located at /etc/init/gunicorn.conf
which looks like:
description "Gunicorn daemon for Django project"
start on (local-filesystems and net-device-up IFACE=eth0)
stop on runlevel [!12345]
# If the process quits unexpectedly trigger a respawn
respawn
setuid django
setgid django
chdir /home/django
exec gunicorn \
--name=django_project \
--pythonpath=django_project \
--bind=0.0.0.0:9000 \
--config /etc/gunicorn.d/gunicorn.py \
django_project.wsgi:application
Again, if you rename the project folder, remember to update the name
and pythonpath
in this file as well.
The Upstart script also sources a configuration file located in /etc/gunicorn.d/gunicorn.py
that sets the number of worker processes:
"""gunicorn WSGI server configuration."""
from multiprocessing import cpu_count
from os import environ
def max_workers():
return cpu_count() * 2 + 1
max_requests = 1000
worker_class = 'gevent'
workers = max_workers()
More information on configuring Gunicorn can be found in the project’s documentation.
The Django project itself is located at /home/django/django_project
It can be started, restarted, or stopped using the Gunicorn service. For instance, to restart the project after having made changes run:
service gunicorn restart
While developing, it can be annoying to restart the server every time you make a change. So you might want to use Django’s built in development server which automatically detects changes:
service gunicorn stop
python manage.py runserver localhost:9000
While convenient, the built in server does not offer the best performance. So use the Gunicorn service for production.
There are many resources that can provide you with an in-depth introduction to writing Django applications, but for now let’s just quickly demonstrate how to get started. Log into your server and switch to the django user. Now let’s create a new app in the project:
cd /home/django/django_project
python manage.py startapp hello
Your directory structure should now look like:
.
├── django_project
│ ├── __init__.py
│ ├── settings.py
│ ├── urls.py
│ └── wsgi.py
├── hello
│ ├── admin.py
│ ├── __init__.py
│ ├── models.py
│ ├── tests.py
│ └── views.py
└── manage.py
Next, we’ll create our first view. Edit the file hello/views.py
to look like:
from django.shortcuts import render
from django.http import HttpResponse
def index(request):
return HttpResponse("Hello, world! This is our first view.")
Then, we can connect that view to a URL by editing django_project/urls.py
from django.conf.urls import patterns, include, url
from hello import views
from django.contrib import admin
admin.autodiscover()
urlpatterns = patterns('',
url(r'^$', views.index, name='index'),
url(r'^admin/', include(admin.site.urls)),
)
After that, we can restart the project as root: service gunicorn restart
If you reload the page, you’ll now see:
sudo
privileges to your user, lock down root login, and take other steps to make your VPS ready for production.<div class=“author”>By Andrew Starr-Bochicchio</div>
Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.
This series links all of the DigitalOcean 1-Click Application images into a cohesive list. Articles are listed in the order that the images are shown on the create droplet screen. New articles are added as more application images are published.
This textbox defaults to using Markdown to format your answer.
You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!
Andrew Starr-Bochicchio thank you. Nginx and Gunicorn have been so hard for me to get working. I’ve spent far more time being a server admin rather than a developer it seems like. (I’m a developer) I’ve actually just gave up on projects and shut down droplets for weeks at a time cause I couldn’t get Nginx and Gunicorn to work. It made me give up on python and go back to PHP. Hours and hours and hours plugging away trying to figure out what was wrong and seeing that dreaded 502 bad gateway page so many times I could hardly stand the thought of refreshing my browser. And after a solid 2 months of going to work for 8 hrs a day writing PHP hurrying home to login and spend all my evenings working on it trying everything in the world. It finally worked when I changed the Django projects owner to www-data! A simple but key piece that it seemed no one had mentioned. Again I’m a developer not a linux admin. When it finally worked I was all out of steam and it would be another 2 months before I could go back to working on this app. In the last week I’ve finally gathered the willpower to get back to working on it. And then today I get the email that this is now a droplet image preconfigured. So I guess the next step is to destroy my droplet and redeploy with yours haha! But any who. Thanks this made me happy today.
Hi! I use this image but I get the 502 error.
In the Gunicorn Upstart script what does the parameter ‘name’ stands for?
@genofongenofon: The <code>–name</code> flag adjusts the name of Gunicorn process. It’s often used so that the name of the process appears as the Django app rather than just gunicorn. We use <code>–name=django_project</code> because the default project we made is just called “django_project”
@Andrew SB thanks!
If I can ask another thing: how can I log the errors (in gunicorn and/or Nginx)?
I tried to add --log-level=error --log-file=$LOGFILE \ in gunicorn specifying LOGFILE=errors.log but it doesn’t work.
@genofongenofon: Upstart logs the Gunicorn job at <code>/var/log/upstart/gunicorn.log</code> while the Nginx logs are in their standard location: <code>/var/log/nginx/error.log</code>
What is the suggested droplet size for this application?
@burlingk: It depends on the size of your application. You can start off with 512MB and upgrade later on if need be.
for anyone else having issues with static files, try this: sudo service nginx restart
Hi, I got this image working out-of-the-box but I am trying to run my own django app on the server now and I’m getting a 502 Bad Gateway error.
I created a virtualenv in the django folder and cloned my git repository into the root of the virtualenv (/django/myenv/myapp/).
I’ve altered my gunicorn.conf as follows: <pre> chdir = /home/django/myenv exec gunicorn
–name=myapp/app –pythonpath=myapp … myapp/app.wsgi:application </pre> I’ve been restarting both nginx and gunicorn after every change.
I’m thinking somewhere in there my syntax is a little off, if you could help me get in the right direction that would be greatly appreciated, thanks.
What the simplest way to set environmental variables such that they will be seen by django when running under this nginx/gunicorn/upstart environment? I have all my database config in the environmental variables and pull them into the django config via e.g. <pre> ‘USER’: os.environ[‘DJ_DB_USER’], ‘PASSWORD’: os.environ[‘DJ_DB_PASSWORD’], </pre> This runs fine if I source the config file that sets these environmental variable then run the django development server (runserver) but I can’t work out how to set them using nginx/gunicorn. I tried sourcing within the configs for these but can’t guess the correct syntax (if this is even possible).
How should I go about maintaining the separation between the app code and these deployment settings?