Using gunicorn with ubuntu:latest Docker image

十年热恋 提交于 2020-08-08 05:16:07

问题


I'm trying to setup a Gunicorn server inside an Ubuntu:latest Docker image.

When launching on Docker, I have the following output

[2020-08-01 14:12:38 +0000] [6] [INFO] Starting gunicorn 20.0.4
[2020-08-01 14:12:38 +0000] [6] [DEBUG] Arbiter booted
[2020-08-01 14:12:38 +0000] [6] [INFO] Listening at: http://0.0.0.0:5000 (6)
[2020-08-01 14:12:38 +0000] [6] [INFO] Using worker: sync
[2020-08-01 14:12:38 +0000] [8] [INFO] Booting worker with pid: 8
[2020-08-01 14:12:38 +0000] [6] [DEBUG] 1 workers

After that, I can't see any output on terminal. I checked the ports using sudo netstat -tunlp opened on my computer and Gunicorn isn't running.

It works fine if I use the same setup using gunicorn --bind 0.0.0.0:5000 app:app --log-level debug inside a virtualenv... Is there anything I am missing up ?

# ------------------------------------------------------------------------------
# Production image based on ubuntu:latest with nginx & python3
# ------------------------------------------------------------------------------
FROM ubuntu:latest as prod-react

WORKDIR /usr/src/app

# update, upgrade and install packages
RUN apt-get update && apt-get install -y --no-install-recommends apt-utils
RUN apt-get upgrade -y
RUN apt-get install -y nginx curl python3 python3-distutils python3-apt

# install pip
RUN curl https://bootstrap.pypa.io/get-pip.py -o get-pip.py
RUN python3 get-pip.py

# copy flask-api requirements file and install modules
COPY ./flask-api/requirements.txt ./
RUN pip install -r requirements.txt
RUN pip install gunicorn

# copy flask code
COPY ./flask-api/app.py .

# ------------------------------------------------------------------------------
# Serve flask-api with gunicorn
# ------------------------------------------------------------------------------
EXPOSE 5000
CMD gunicorn --bind 0.0.0.0:5000 app:app --log-level debug

Flask python code

from flask import Flask, request
from flask_cors import CORS
from flask_restful import Api, Resource
import time

# ------------------------------------------------------------------------------
# Flask app config + CORS
# ------------------------------------------------------------------------------
app = Flask(__name__)
app.config.from_object(__name__)
app.config['DEBUG'] = True

# accept CORS from frontend app
CORS(app, origins=['*'], supports_credentials=True)

# ------------------------------------------------------------------------------
# RESTFUL API
# ------------------------------------------------------------------------------
API_PREFIX = '/api'
api = Api(prefix=API_PREFIX)


class AuthenticationAPI(Resource):
    def get(self):
        print('auth get', flush=True)
        return {'res': 'get'}, 200

    def post(self):
        print('auth post', flush=True)
        print(request.get_json())
        return {'res': 'post'}, 200


class TimeAPI(Resource):
    def get(self):
        print('time get', flush=True)
        return {'res': time.time()}, 200


api.add_resource(AuthenticationAPI, '/auth')
api.add_resource(TimeAPI, '/time')

api.init_app(app)

回答1:


From the docker documentation for the EXPOSE directive:

The EXPOSE instruction does not actually publish the port. It functions as a type of documentation between the person who builds the image and the person who runs the container, about which ports are intended to be published. To actually publish the port when running the container, use the -p flag on docker run to publish and map one or more ports, or the -P flag to publish all exposed ports and map them to high-order ports.

So since gunicorn is listening on port 500, you'll want to run your container like this:

docker run -p 5000:5000 your_image

passing along any other options you're already passing when running your container.




回答2:


I managed to make it works on local dev. The following Dockerfile contains all the modifications, I commented commands to make it work properly.

# ------------------------------------------------------------------------------
# Temporary image for react.js app using a multi-stage build
# ref : https://docs.docker.com/develop/develop-images/multistage-build/
# ------------------------------------------------------------------------------
FROM node:latest as build-react

# create a shared folder and define it as current dir
WORKDIR /usr/src/app
ENV PATH /usr/src/app/node_modules/.bin:$PATH

# copy the files required for node packages installation
COPY ./react-client/package.json ./
COPY ./react-client/yarn.lock ./

# install dependencies, copy code and build bundles
RUN yarn install
COPY ./react-client .
RUN yarn build

# ------------------------------------------------------------------------------
# Production image based on ubuntu:latest with nginx & python3
# ------------------------------------------------------------------------------
FROM ubuntu:latest as prod-react

WORKDIR /usr/src/app

# update, upgrade and install packages
RUN apt-get update && apt-get install -y --no-install-recommends apt-utils
RUN apt-get upgrade -y
RUN apt-get install -y nginx curl python3 python3-distutils python3-apt

# install pip
RUN curl https://bootstrap.pypa.io/get-pip.py -o get-pip.py
RUN python3 get-pip.py

# copy flask-api requirements file and install modules
COPY ./flask-api/requirements.txt ./
RUN pip install -r requirements.txt
RUN pip install gunicorn

# copy flask code
COPY ./flask-api/app.py .

# copy built image and config onto nginx directory
COPY --from=build-react /usr/src/app/build /usr/share/nginx/html
COPY ./conf.nginx /etc/nginx/conf.d/default.conf

# ------------------------------------------------------------------------------
# Serve flask-api with gunicorn and react-client with nginx
# Ports :
#   - 5000 is used for flask-api
#   - 8080 is used by nginx to serve react-client
# You can change them but you'll have to change :
#   - for flask-api    : conf.nginx, axios calls (5000 -> @newApiPort)
#   - for react-client : CORS origins (8080 -> @newClientPort)
#
# To build and run this :
#   docker build -t @imageName .
#   docker run -d --name @containerName -e "PORT=8080" -p 8080:8080 -p 5000:5000 @imageName
# ------------------------------------------------------------------------------
CMD gunicorn --bind 0.0.0.0:5000 app:app --daemon && \
sed -i -e 's/$PORT/'"$PORT"'/g' /etc/nginx/conf.d/default.conf && \
nginx -g 'daemon off;'


来源:https://stackoverflow.com/questions/63206239/using-gunicorn-with-ubuntulatest-docker-image

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!