简体   繁体   中英

Gunicorn does not run in docker container when using ENTRYPOINT or CMD

I have the following Dockerfile and entrypoint.sh script. I do as below, but when I run the container it looks like gunicorn never starts because nothing gets written to log files. The container remains running because I type "docker ps" and I can see it.

I then start a bash process by doing "docker exec -it /bin/bash" and I can run the gunicorn process from there and then it works.

So basically, it works if I run the container and then log into a bash session and paste the gunicorn command, but it doesn't work otherwise.

Dockerfile:

FROM ubuntu:18.04
MAINTAINER peter griffin "some@email.com"
RUN apt-get update -y && apt-get install -y python-pip python-dev

WORKDIR /deploy

COPY ./requirements.txt ./
RUN pip install -r requirements.txt
RUN pip install gunicorn

COPY ./app ./app

COPY [\
    "run.py", \
    "app.db", \
    "entrypoint.sh", \
    "config.py", \
    "gunicorn.conf.py", \
    "./"]

#RUN mkdir ./logs
RUN chmod +x ./entrypoint.sh

ENTRYPOINT ["sh", "entrypoint.sh"]

entrypoint.sh:

#!/bin/bash

mkdir -p /deploy/logs
touch /deploy/logs/error.log
touch /deploy/logs/access.log
tail -n 0 -f /deploy/logs/*.log

exec gunicorn run:app \
    --name greg_docker \
    --bind 0.0.0.0:8080 \
    --workers 2 \
    --log-level=info \
    --log-file=/deploy/logs/error.log \
    --access-logfile=/deploy/logs/access.log \

To build:

docker build -t greg:latest .

To run:

docker run -d -p 8080:8080 greg:latest

If I'm inside the container in a /bin/bash session, I can paste:

exec gunicorn run:app \
    --name greg_docker \
    --bind 0.0.0.0:8080 \
    --workers 2 \
    --log-level=info \
    --log-file=/deploy/logs/error.log \
    --access-logfile=/deploy/logs/access.log

And then it does work when I go to http://0.0.0.0:8080 on the docker host.

What is the difference? Why does gunicorn not work on entrypoint.sh?

update I've made a new file, entrypoint2.sh:

#!/bin/bash
mkdir -p /deploy/logs
touch /deploy/logs/error.log
exec gunicorn run:app \
    --name greg_docker \
    --bind 0.0.0.0:8080 \
    --log-level=debug \
    --log-file=/deploy/logs/error.log \
    --workers 2
"$@"

And I've updated my Dockerfile with the line:

ENTRYPOINT ["sh","-x","entrypoint2.sh"]

When I run the container I get this:

+ mkdir -p /deploy/logs
+ touch /deploy/logs/error.log
+ exec gunicorn run:app --name greg_docker --bind 0.0.0.0:8080 --log-level=debug --log-file=/deploy/logs/error.log --workers 2

But then the container doesn't do anything, it doesn't stay running.

When you docker run a container, it starts the ENTRYPOINT (if any), passing the CMD to it as command-line arguments. When that program or script finishes, the container exits.

In your first iteration, your ENTRYPOINT said:

#!/bin/bash

# Read all of the log files, blocking forever, printing out new
# content as it appears
tail -n 0 -f /deploy/logs/*.log

# Only then, once that "blocking forever" has finished...
exec gunicorn run:app

So the tail command was preventing the gunicorn from actually starting. You should have been able to see this by using the shell -x option (as in your edit, or by adding a set -x line to the script): it will get up to the tail , and then just stop.

In a comment you say you set the daemon = True gunicorn option in a config file. If gunicorn finds this, then it will fork itself into the background and exit. From Docker's point of view, it sees the process that it launched as the container entrypoint exit, so the container is done, and it shuts down. I'm not totally sure what is or isn't causing that config file to get read, but that would cause an early exit.

You need to make sure you're running the server as a foreground process . If you docker exec to get a shell in a running container, start the server, and get a command prompt back, then you're invoking it in a way that won't keep the container alive.

Turns out when running gunicorn, you absolutely need to specify a configuration file.

entrypoint2.sh:

#!/bin/bash
mkdir -p /deploy/logs
touch /deploy/logs/error.log
touch /deploy/logs/access.log
cd /deploy
exec gunicorn --bind 0.0.0.0:8080 -c docker-gunicorn.conf.py run:app

docker-gunicorn.conf.py:

accesslog = "/deploy/logs/access.log"
errorlog = "/deploy/logs/error.log"

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM