Docker-compose service exited with code 0

Viewed 8160

I'm quite new to Docker. I'm trying to run Django on Docker. Following is my docker-compose file.

version: '2'
services:
    django:
        build:
          context: .
          dockerfile: ./deploy/dev/Dockerfile
        tty: true
        command: python manage.py runserver 0.0.0.0:8000
        ports:
              - "8000:8000"
        volumes:
            - ./app:/src/app
        depends_on:
            - "workflow_db"
            - "rabbitmq"
        env_file:
            - ./deploy/dev/envvar.env
    workflow_db:
        image: postgres:9.6
        volumes:
            - postgres_data:/var/lib/postgresql/data/
        environment:
            - POSTGRES_USER=hello_django
            - POSTGRES_PASSWORD=hello_django
            - POSTGRES_DB=hello_django
    rabbitmq:
        image: "rabbitmq:3-management"
        hostname: "rabbitmq"
        environment:
            RABBITMQ_ERLANG_COOKIE: "SWQOKODSQALRPCLNMEQG"
            RABBITMQ_DEFAULT_USER: "rabbitmq"
            RABBITMQ_DEFAULT_PASS: "rabbitmq"
            RABBITMQ_DEFAULT_VHOST: "/"
        ports:
            - "15672:15672"
            - "5672:5672"
volumes:
  postgres_data:

DockerFile

FROM python:3.7-alpine

RUN apk update && apk add --no-cache gcc libffi-dev g++ python-dev build-base linux-headers postgresql-dev postgresql postgresql-contrib pcre-dev bash alpine-sdk \
  && pip install wheel

#Copy over application files
COPY ./app /src/app

#Copy over, and grant executable permission to the startup script
COPY ./deploy/dev/entrypoint.sh /
RUN chmod +x /entrypoint.sh

WORKDIR /src/app

#Install requirements pre-startup to reduce entrypoint time
RUN pip install -r requirements.txt

ENTRYPOINT [ "/entrypoint.sh" ]

And finally my entrypoint.sh

#! /bin/bash

cd /src/app || exit

echo "PIP INSTALLATION" && pip install -r requirements.txt

echo "UPGRADE" && python manage.py migrate

# echo "uwsgi" && uwsgi "uwsgi.ini"

I do django-compose build, it builds the image. But when I do docker-compose up django_1 exited with code 0.

However, if I uncomment the last line of entrypoint.sh, it runs perfectly well.

Can someone help me understand the reason behind it?

3 Answers

When you have both a command and an entrypoint, Docker runs only the entrypoint, and passes the command to it as arguments. See Understand how CMD and ENTRYPOINT interact in the Dockerfile docs. As soon as the entrypoint exits, the container is over; it can do whatever it likes with the command part, including completely ignoring it.

Typical practice is to end the entrypoint script with

exec "$@"

which causes it to just take its command-line arguments and run them as a command, replacing the entrypoint script as the main container process.

Without this, you get to the end of the entrypoint script, and the container has done everything it's told to do, so it exits successfully (status code 0).

AFAIU, when you uncomment the last line in entrypoint, the container doesn't have a foreground process anymore which can keep it up & running, hence it exits with status 0. Entrypoint must have a foreground process to keep container up & running. Also, you are doing "pip install" multiple times. This step should just be in Dockerfile.

Try moving python manage.py runserver 0.0.0.0:8000 in entrypoint.sh itself.

Update -

In case of port conflict, the container will not exit with status 0 & the port conflict error with come in STDOUT. Also, when he uncomments, there is no chance of port conflict. So, it seems like the foreground process is not getting executed at all.

If you want to container to keep running, you need either to:

  1. run a foreground process
  2. connect to it's terminal by --ti

you need to connect with terminal to see if the python command is failing when the uwsgi is not executed, hence stopping the container

Related