Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

how to run gunicorn on docker

I have 2 files that depend on each other when docker is start up. 1 is a flask file and one is a file with a few functions. When docker starts, only the functions file will be executed but it imports flask variables from the flask file. Example:

Flaskfile

import flask
from flask import Flask, request
import json

_flask = Flask(__name__)

@_flask.route('/', methods = ['POST'])
def flask_main():
    s = str(request.form['abc'])
    ind = global_fn_main(param1,param2,param3)
    return ind

def run(fn_main):
    global global_fn_main
    global_fn_main = fn_main
    _flask.run(debug = False, port = 8080, host = '0.0.0.0', threaded = True)

Main File

import flaskfile
#a few functions then
if__name__ == '__main__':
    flaskfile.run(main_fn)

The script runs fine without need a gunicorn.

Dockerfile

  FROM python-flask
  ADD *.py *.pyc /code/
  ADD requirements.txt /code/
  WORKDIR /code
  EXPOSE 8080
  CMD ["python","main_file.py"]

In the Command line: i usally do: docker run -it -p 8080:8080 my_image_name and then docker will start and listen.

Now to use gunicorn: I tried to modify my CMD parameter in the dockerfile to

["gunicorn", "-w", "20", "-b", "127.0.0.1:8083", "main_file:flaskfile"]

but it just keeps exiting. Am i not writing the docker gunicorn command right?

like image 413
jxn Avatar asked May 11 '17 21:05

jxn


People also ask

Do I need Gunicorn with docker?

The script runs fine without need a gunicorn. In the Command line: i usally do: docker run -it -p 8080:8080 my_image_name and then docker will start and listen.

How do I run Gunicorn as service?

Running sudo -u www-data curl --unix-socket /run/gunicorn. sock http , our Gunicorn service will be automatically started and you should see some HTML from your server in the terminal. systemd employs cgroups to track the processes of a service, so it doesn't need pid files.

Can we run Gunicorn on Windows?

It runs on Windows only under WSL. Create a virtualenv, install your application, then install gunicorn .


3 Answers

I just went through this problem this week and stumbled on your question along the way. Fair to say you either resolved this or changed approaches by now, but for future's sake:

The command in my Dockerfile is:

CMD ["gunicorn"  , "-b", "0.0.0.0:8000", "app:app"]

Where the first "app" is the module and the second "app" is the name of the WSGI callable, in your case, it should be _flask from your code although you've some other stuff going on that makes me less certain.

Gunicorn takes the place of all the run statements in your code, if Flask's development web server and Gunicorn try to take the same port it can conflict and crash Gunicorn.

Note that when run by Gunicorn, __name__ is not "main". In my example it is equal to "app".

At my admittedly junior level of both Python, Docker, and Gunicorn the fastest way to debug is to comment out the "CMD" in the Dockerfile, get the container up and running:

docker run -it -d -p 8080:8080 my_image_name

Hop onto the running container:

 docker exec -it container_name /bin/bash

And start Gunicorn from the command line until you've got it working, then test with curl - I keep a basic route in my app.py file that just prints out "Hi" and has no dependencies for validating the server is up before worrying about the port binding to the host machine.

like image 174
user7504939 Avatar answered Oct 11 '22 13:10

user7504939


After struggling with this issue over the last 3 days, I found that all you need to do is to bind to the non-routable meta-address 0.0.0.0 rather than the loopback IP 127.0.0.1:

CMD ["gunicorn" , "--bind", "0.0.0.0:8000", "app:app"]

And don't forget to expose the port, one option to do that is to use EXPOSE in your Dockerfile:

EXPOSE 8000

Now:

docker build -t test .

Finally you can run:

docker run -d -p 8000:8000 test
like image 26
Mohamad Al Mdfaa Avatar answered Oct 11 '22 13:10

Mohamad Al Mdfaa


This is my last part of my Dockerfile with Django App

EXPOSE 8002
COPY entrypoint.sh /code/
WORKDIR /code
ENTRYPOINT ["sh", "entrypoint.sh"]

then in entrypoint.sh

#!/bin/bash

# Prepare log files and start outputting logs to stdout
mkdir -p /code/logs
touch /code/logs/gunicorn.log
touch /code/logs/gunicorn-access.log
tail -n 0 -f /code/logs/gunicorn*.log &

export DJANGO_SETTINGS_MODULE=django_docker_azure.settings

exec gunicorn django_docker_azure.wsgi:application \
    --name django_docker_azure \
    --bind 0.0.0.0:8002 \
    --workers 5 \
    --log-level=info \
    --log-file=/code/logs/gunicorn.log \
    --access-logfile=/code/logs/gunicorn-access.log \
"$@"

Hope this could be useful

like image 35
e.arbitrio Avatar answered Oct 11 '22 13:10

e.arbitrio