Searching google gives you plenty of tutorials for setting up a Flask application behind nginx with uwsgi; however it has been my experience over the past two days that almost none of those tutorials work or are severely outdated.
So this weekend while updating my docker-compose file I went ahead and converted my development docker environment from using the standard web server that comes from flask to being behind nginx and uwsgi.
Below are the files necessary for doing the same in your environment:
Dockerfile
FROM ubuntu:14.04
MAINTAINER Marie H.
# Nginx + UWSGI Plugin
RUN apt-get update && \
apt-get -y install \
curl \
python-dev \
libmysqlclient-dev \
nginx \
supervisor \
uwsgi
# Install pip
ENV PYTHON_PIP_VERSION 8.1.2
RUN curl -SL 'https://bootstrap.pypa.io/get-pip.py' | python \
&& pip install --upgrade pip==$PYTHON_PIP_VERSION
# Setup Nginx
RUN rm /etc/nginx/sites-enabled/default
COPY config-files/flask.conf /etc/nginx/sites-available/
RUN ln -s /etc/nginx/sites-available/flask.conf /etc/nginx/sites-enabled/flask.conf
COPY config-files/uwsgi.ini /var/www/app/
RUN echo "daemon off;" >> /etc/nginx/nginx.conf
# install uwsgi
RUN pip install uwsgi
# Setup Supervisor
RUN mkdir -p /var/log/supervisor
COPY config-files/supervisord.conf /etc/supervisor/conf.d/supervisord.conf
# Copy Requirements and Install
# This ensures that after initial build modules will be cached
COPY requirements.txt /var/www/app
RUN pip install -r /var/www/app/requirements.txt
# Copy Application
COPY . /var/www/app
CMD ["/usr/bin/supervisord"]
flask.conf
server {
listen 80;
server_name localhost;
charset utf-8;
client_max_body_size 75M;
location / {
include uwsgi_params;
uwsgi_pass unix:/var/www/app/uwsgi.sock;
}
location /static {
root /var/www/app/;
}
}
supervisord.conf
[supervisord]
nodaemon=true
[program:nginx]
command=/usr/sbin/nginx
[program:uwsgi]
command=/usr/local/bin/uwsgi --ini /var/www/app/uwsgi.ini
uwsgi.ini
[uwsgi]
socket = /var/www/app/uwsgi.sock
chmod-socket = 666
logto = /var/log/uwsgi/app/app.log
chdir = /var/www/app
wsgi-file = application.py
processes = 4
threads = 2
vacuum = true
Build
[mharris@mori app]$ docker build -t test .
Sending build context to Docker daemon 44.92 MB
Step 1 : FROM ubuntu:14.04
---> 38c759202e30
Step 2 : MAINTAINER Marie H.
---> Using cache
---> b75d9d211918
Step 3 : RUN apt-get update && apt-get -y install curl python-dev libmysqlclient-dev nginx supervisor uwsgi
---> Using cache
---> 97588705bae8
Step 4 : ENV PYTHON_PIP_VERSION 8.1.2
---> Using cache
---> b90120dbf0bc
Step 5 : RUN curl -SL 'https://bootstrap.pypa.io/get-pip.py' | python && pip install --upgrade pip==$PYTHON_PIP_VERSION
---> Using cache
---> 795edfec5535
Step 6 : RUN rm /etc/nginx/sites-enabled/default
---> Using cache
---> 41ee92a02b1c
Step 7 : COPY config-files/flask.conf /etc/nginx/sites-available/
---> Using cache
---> b4e9c3c03a24
Step 8 : RUN ln -s /etc/nginx/sites-available/flask.conf /etc/nginx/sites-enabled/flask.conf
---> Using cache
---> cdb05cfeb66c
Step 9 : COPY config-files/uwsgi.ini /var/www/app/
---> Using cache
---> 2550bbb493f0
Step 10 : RUN echo "daemon off;" >> /etc/nginx/nginx.conf
---> Using cache
---> 5741bfaa98b8
Step 11 : RUN pip install uwsgi
---> Using cache
---> de11cc6da147
Step 12 : RUN mkdir -p /var/log/supervisor
---> Using cache
---> 2d42d67927de
Step 13 : COPY config-files/supervisord.conf /etc/supervisor/conf.d/supervisord.conf
---> Using cache
---> ce5d6973de70
Step 14 : COPY requirements.txt /var/www/app
---> Using cache
---> 9d7c1abaaf3e
Step 15 : RUN pip install -r /var/www/app/requirements.txt
---> Using cache
---> 3f09459333ee
Step 16 : COPY . /var/www/app
---> 7682748a34c6
Removing intermediate container bb7f93e0c878
Step 17 : CMD /usr/bin/supervisord
---> Running in b58186e8db90
---> c5542adc2bc9
Removing intermediate container b58186e8db90
Successfully built c5542adc2bc9
Run
[mharris@mori app]$ docker run -d -p 8080:80 test
ee5da4503dc36844ba7f37f269dfeb4bc86ae25ac11ddc5f48981acb61ae0562
Test
[mharris@mori app]$ curl localhost:8080
{
"status": "alive"
}
Additional content from archive:
Searching google gives you plenty of tutorials for setting up a Flask application behind nginx with uwsgi; however it has been my experience over the past two days that almost none of those tutorials work or are severely outdated.
So this weekend while updating our docker-compose file for work I went ahead and converted our development docker environment from using the standard web server that comes from flask to being behind nginx and uwsgi.
Below are the files necessary for doing the same in your environment:
The Dockerfile
FROM ubuntu:14.04
MAINTAINER Marie H. <[email protected]/* <![CDATA[ */!function(t,e,r,n,c,a,p){try{t=document.currentScript||function(){for(t=document.getElementsByTagName('script'),e=t.length;e--;)if(t[e].getAttribute('data-cfhash'))return t[e]}();if(t&&(c=t.previousSibling)){p=t.parentNode;if(a=c.getAttribute('data-cfemail')){for(e='',r='0x'+a.substr(0,2)|0,n=2;a.length-n;n+=2)e+='%'+('0'+('0x'+a.substr(n,2)^r).toString(16)).slice(-2);p.replaceChild(document.createTextNode(decodeURIComponent(e)),c)}p.removeChild(t)}}catch(u){}}()/* ]]> */>
# Nginx + UWSGI Plugin
RUN apt-get update && \
apt-get -y install \
curl \
python-dev \
libmysqlclient-dev \
nginx \
supervisor \
uwsgi
# Install pip
ENV PYTHON_PIP_VERSION 8.1.2
RUN curl -SL 'https://bootstrap.pypa.io/get-pip.py' | python \
&& pip install --upgrade pip==$PYTHON_PIP_VERSION
# Setup Nginx
RUN rm /etc/nginx/sites-enabled/default
COPY config-files/flask.conf /etc/nginx/sites-available/
RUN ln -s /etc/nginx/sites-available/flask.conf /etc/nginx/sites-enabled/flask.conf
COPY config-files/uwsgi.ini /var/www/app/
RUN echo "daemon off;" >> /etc/nginx/nginx.conf
# install uwsgi
RUN pip install uwsgi
# Setup Supervisor
RUN mkdir -p /var/log/supervisor
COPY config-files/supervisord.conf /etc/supervisor/conf.d/supervisord.conf
# Copy Requirements and Install
# This ensures that after initial build modules will be cached
COPY requirements.txt /var/www/app
RUN pip install -r /var/www/app/requirements.txt
# Copy Application
COPY . /var/www/app
CMD ["/usr/bin/supervisord"]
The Config Files
flask.conf
server {
listen 80;
server_name localhost;
charset utf-8;
client_max_body_size 75M;
location / {
include uwsgi_params;
uwsgi_pass unix:/var/www/app/uwsgi.sock;
}
location /static {
root /var/www/app/;
}
}
supervisord.conf
[supervisord]
nodaemon=true
[program:nginx]
command=/usr/sbin/nginx
[program:uwsgi]
command=/usr/local/bin/uwsgi --ini /var/www/app/uwsgi.ini
uwsgi.ini
[uwsgi]
socket = /var/www/app/uwsgi.sock
chmod-socket = 666
logto = /var/log/uwsgi/app/app.log
chdir = /var/www/app
wsgi-file = application.py
processes = 4
threads = 2
vacuum = true
Build and Run
Now all you should need to do is build and run your app.
Build
[[email protected]/* <![CDATA[ */!function(t,e,r,n,c,a,p){try{t=document.currentScript||function(){for(t=document.getElementsByTagName('script'),e=t.length;e--;)if(t[e].getAttribute('data-cfhash'))return t[e]}();if(t&&(c=t.previousSibling)){p=t.parentNode;if(a=c.getAttribute('data-cfemail')){for(e='',r='0x'+a.substr(0,2)|0,n=2;a.length-n;n+=2)e+='%'+('0'+('0x'+a.substr(n,2)^r).toString(16)).slice(-2);p.replaceChild(document.createTextNode(decodeURIComponent(e)),c)}p.removeChild(t)}}catch(u){}}()/* ]]> */ mydh-backend]$ docker build -t test .
Sending build context to Docker daemon 44.92 MB
Step 1 : FROM ubuntu:14.04
---> 38c759202e30
Step 2 : MAINTAINER Marie H. <[email protected]/* <![CDATA[ */!function(t,e,r,n,c,a,p){try{t=document.currentScript||function(){for(t=document.getElementsByTagName('script'),e=t.length;e--;)if(t[e].getAttribute('data-cfhash'))return t[e]}();if(t&&(c=t.previousSibling)){p=t.parentNode;if(a=c.getAttribute('data-cfemail')){for(e='',r='0x'+a.substr(0,2)|0,n=2;a.length-n;n+=2)e+='%'+('0'+('0x'+a.substr(n,2)^r).toString(16)).slice(-2);p.replaceChild(document.createTextNode(decodeURIComponent(e)),c)}p.removeChild(t)}}catch(u){}}()/* ]]> */>
---> Using cache
---> b75d9d211918
Step 3 : RUN apt-get update && apt-get -y install curl python-dev libmysqlclient-dev nginx supervisor uwsgi
---> Using cache
---> 97588705bae8
Step 4 : ENV PYTHON_PIP_VERSION 8.1.2
---> Using cache
---> b90120dbf0bc
Step 5 : RUN curl -SL 'https://bootstrap.pypa.io/get-pip.py' | python && pip install --upgrade pip==$PYTHON_PIP_VERSION
---> Using cache
---> 795edfec5535
Step 6 : RUN rm /etc/nginx/sites-enabled/default
---> Using cache
---> 41ee92a02b1c
Step 7 : COPY config-files/flask.conf /etc/nginx/sites-available/
---> Using cache
---> b4e9c3c03a24
Step 8 : RUN ln -s /etc/nginx/sites-available/flask.conf /etc/nginx/sites-enabled/flask.conf
---> Using cache
---> cdb05cfeb66c
Step 9 : COPY config-files/uwsgi.ini /var/www/app/
---> Using cache
---> 2550bbb493f0
Step 10 : RUN echo "daemon off;" >> /etc/nginx/nginx.conf
---> Using cache
---> 5741bfaa98b8
Step 11 : RUN pip install uwsgi
---> Using cache
---> de11cc6da147
Step 12 : RUN mkdir -p /var/log/supervisor
---> Using cache
---> 2d42d67927de
Step 13 : COPY config-files/supervisord.conf /etc/supervisor/conf.d/supervisord.conf
---> Using cache
---> ce5d6973de70
Step 14 : COPY requirements.txt /var/www/app
---> Using cache
---> 9d7c1abaaf3e
Step 15 : RUN pip install -r /var/www/app/requirements.txt
---> Using cache
---> 3f09459333ee
Step 16 : COPY . /var/www/app
---> 7682748a34c6
Removing intermediate container bb7f93e0c878
Step 17 : CMD /usr/bin/supervisord
---> Running in b58186e8db90
---> c5542adc2bc9
Removing intermediate container b58186e8db90
Successfully built c5542adc2bc9
Run
[[email protected]/* <![CDATA[ */!function(t,e,r,n,c,a,p){try{t=document.currentScript||function(){for(t=document.getElementsByTagName('script'),e=t.length;e--;)if(t[e].getAttribute('data-cfhash'))return t[e]}();if(t&&(c=t.previousSibling)){p=t.parentNode;if(a=c.getAttribute('data-cfemail')){for(e='',r='0x'+a.substr(0,2)|0,n=2;a.length-n;n+=2)e+='%'+('0'+('0x'+a.substr(n,2)^r).toString(16)).slice(-2);p.replaceChild(document.createTextNode(decodeURIComponent(e)),c)}p.removeChild(t)}}catch(u){}}()/* ]]> */ mydh-backend]$ docker run -d -p 8080:80 test
ee5da4503dc36844ba7f37f269dfeb4bc86ae25ac11ddc5f48981acb61ae0562
Test
[[email protected]/* <![CDATA[ */!function(t,e,r,n,c,a,p){try{t=document.currentScript||function(){for(t=document.getElementsByTagName('script'),e=t.length;e--;)if(t[e].getAttribute('data-cfhash'))return t[e]}();if(t&&(c=t.previousSibling)){p=t.parentNode;if(a=c.getAttribute('data-cfemail')){for(e='',r='0x'+a.substr(0,2)|0,n=2;a.length-n;n+=2)e+='%'+('0'+('0x'+a.substr(n,2)^r).toString(16)).slice(-2);p.replaceChild(document.createTextNode(decodeURIComponent(e)),c)}p.removeChild(t)}}catch(u){}}()/* ]]> */ mydh-backend]$ curl localhost:8080
{
"version": "0.1.0"
}
Tell your friends...