Getting your Gunicorn server proxy behind Nginx on a Docker container

01-docker-containerIf you have been web-developing on Linux platforms it is less likely that you have not used Docker at all. LXCs ( Linux containers) have been around for some time now, but Docker certainly made it the “cool” thing to use. Now I can sleep peacefully thinking that if it works on my development machine, it is certainly to work fine on any environment.  All what I need a tried image and then we are all set. No more anxiety of making it run on various environments.

I prefer to have Django for the WebApis, as I have yet to find anything cooler and neater than that on Linux. While Django as a complete package is undoubtedly useful, HTTP REST framework of it is what keeps me stuck to it. Easy to setup and get started , whats even cool is that despite I coming from a MVC C# background , getting a API running on Django driven framework is all about you knowing your python pretty well.

django-dockerDjango gels very well with Gunicorn (It would be rather honest to say  that for wsgi applications behind Nginx you would need something like Gunicorn to get it running.), while Gunicorn is easy to proxy behind Nginx as a server. If you have used Gunicorn you already know that we never ever let Gunicorn face the client requests directly , instead Nginx takes the load and redirects it to upstream servers like Gunicorn.

Not all is changed when you get such a setup on a container.

Questions then arise whether or not you need any more ports to be exposed than what is required for Nginx alone. ?

If you manage to bind Gunicorn to a UNIX socket file , you would need just one port mapping from the container to the host- and that would be the NGINX client facing port

dockerblog

Lets just go ahead to see whats inside my Dockerfile , also I open up what my Nginx server configuration looks like.

FROM ubuntu:14.04 #this where I pull the image from docker , base image i need
MAINTAINER kneerunjun

#————Essentials and installations———————-
RUN apt-get update
RUN apt-get install -y nano
RUN apt-get install -y python-pip
RUN apt-get install -y nginx
RUN apt-get install -y mongodb
RUN apt-get update

RUN pip install django

RUN pip install pymongo
RUN pip install gunicorn

#————————————————————-
ARG webcontentdir=/var/www/content
ARG webdir=/var/www/pifarm
ARG httpdir=/var/http/pifarm
ARG httphelpdir=/var/http/pifarm/help
ARG storedir=/var/store/pifarm

ARG sitesavailable=/etc/nginx/sites-available
ARG sitesenabled=/etc/nginx/sites-enabled

#principle web directory, all the web content static and dynamic is all here
RUN mkdir -p $webcontentdir
RUN mkdir -p $webdir
RUN mkdir -p $httpdir
RUN mkdir -p $httphelpdir
RUN mkdir -p $storedir

RUN touch $webdir/index.html

#settin up mongodb and the configuration
#we need the dbpath as per our configuration
RUN awk ‘!/dbpath=/{print $0}’ /etc/mongodb.conf > /etc/mongodb.conf.temp
RUN echo “dbpath=$storedir” >> /etc/mongodb.conf.temp
RUN cat /etc/mongodb.conf.temp > /etc/mongodb.conf
RUN chown -R mongodb /var/store
RUN rm /etc/mongodb.conf.temp

#instead of changing the mongodb conf file, you could also run mongod –dbpath on the run of the container. Here are not leaving that to chance , just making sure the configuration files knows it has to pick up data in indicated folder.

#this is just the test html that we are using to know if nginx is working
RUN echo “This is the pifarm application” > /var/www/pifarm/index.html
#download from the git repo and get the code ready

#setting up nginx and the requisite configuration
RUN echo “daemon off;”>>/etc/nginx/nginx.conf
RUN touch $sitesavailable/pifarm
ADD ./pifarm $sitesavailable/pifarm
RUN ln -s $sitesavailable/pifarm $sitesenabled/pifarm
RUN chown -R www-data:www-data $webdir

#since nginx runs with the user name www-data

#setting up the access rights on the container
EXPOSE 8080

#and then before the container is started

ADD ./cmd-pifarm /usr/local/bin/cmd-pifarm
RUN chmod a+x /usr/local/bin/cmd-pifarm

upstream api_server {
server unix:/var/http/pifarm/pifarm.sock fail_timeout=10s;
}
server{
listen 8080;
server_name 127.0.0.1;
root /var/www/pifarm;
index index.html;
location = /favicon.ico { access_log off; log_not_found off; }

location /api-help {
alias /var/www/pifarm/api-help;
autoindex on;
}
location /api {
include proxy_params;
proxy_pass http://api_server;
}
location /libs {
alias /var/www/content;
autoindex on;
}
location / {
autoindex on;
}
}

Now from the Nginx configuration it may appear to be clear that Nginx treats Gunicorn as an upstream server and redirects all traffic to this via a Unix socket. If you are averse to socket files ( I can find a reason why I should not be using them , but nevertheless ..) you can still expose Gunicorn on from within the container and get this working.

I’m not saying this is the only way of getting things done here. But certainly I could wrap my head around this one more conveniently.

Advertisements

One thought on “Getting your Gunicorn server proxy behind Nginx on a Docker container

Add yours

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Blog at WordPress.com.

Up ↑

%d bloggers like this: