问题
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