Search code examples
dockerubuntudockerfile

Why won't my docker container start when I have an ENTRYPOINT in the Dockerfile?


I am trying to include an ENTRYPOINT in my Dockerfile. It seems simply having this line in my Dockerfile causes the container not to start.

Here is my Dockerfile

# syntax=docker/dockerfile:1

FROM python:3.8

RUN apt-get update && apt-get install -y g++ unixodbc-dev # pyodbc build dependencies
RUN apt-get install -y build-essential libssl-dev libffi-dev python3-dev
RUN apt-get update && \
    apt-get install -y apt-transport-https && \
    curl https://packages.microsoft.com/keys/microsoft.asc | apt-key add - && \
    curl https://packages.microsoft.com/config/debian/9/prod.list > /etc/apt/sources.list.d/mssql-release.list && \
    apt-get update && \
    ACCEPT_EULA=Y apt-get install msodbcsql17 unixodbc-dev -y


WORKDIR /test

COPY requirements.txt requirements.txt
RUN pip3 install -r requirements.txt

COPY *.py ./
COPY *.txt ./
COPY Dockerfile ./
COPY vars.sh /etc/profile.d/
COPY entrypoint.sh ./

RUN ["chmod", "+x", "/test/entrypoint.sh"]

ENTRYPOINT ["echo", "Hello World"]  # <---- Container starts when this line is commented out. Will not start when this command is executed. 

CMD [ "python3", "app.py" ]

I run the following command to build.

sudo docker run --network host -d -p 8080:8080 test

Output

Sending build context to Docker daemon  28.67kB
Step 1/15 : FROM python:3.8
 ---> 415775fb4b1f
Step 2/15 : RUN apt-get update && apt-get install -y g++ unixodbc-dev # pyodbc build dependencies
 ---> Using cache
 ---> 20615c0701e8
Step 3/15 : RUN apt-get install -y build-essential libssl-dev libffi-dev python3-dev
 ---> Using cache
 ---> a5dacb381b06
Step 4/15 : RUN apt-get update &&     apt-get install -y apt-transport-https &&     curl https://packages.microsoft.com/keys/microsoft.asc | apt-key add - &&     curl https://packages.microsoft.com/config/debian/9/prod.list > /etc/apt/sources.list.d/mssql-release.list &&     apt-get update &&     ACCEPT_EULA=Y apt-get install msodbcsql17 unixodbc-dev -y
 ---> Using cache
 ---> 876d4ef82bf8
Step 5/15 : WORKDIR /test
 ---> Using cache
 ---> 6d714c96591e
Step 6/15 : COPY requirements.txt requirements.txt
 ---> Using cache
 ---> 7d82824171e5
Step 7/15 : RUN pip3 install -r requirements.txt
 ---> Using cache
 ---> b41de5e83e64
Step 8/15 : COPY *.py ./
 ---> Using cache
 ---> 9dbe93e3c805
Step 9/15 : COPY *.txt ./
 ---> Using cache
 ---> 30307de43e5d
Step 10/15 : COPY Dockerfile ./
 ---> Using cache
 ---> e2124fd93147
Step 11/15 : COPY vars.sh /etc/profile.d/
 ---> Using cache
 ---> d739f473c579
Step 12/15 : COPY entrypoint.sh ./
 ---> Using cache
 ---> be484c119b6a
Step 13/15 : RUN ["chmod", "+x", "/test/entrypoint.sh"]
 ---> Using cache
 ---> ea6a12927a70
Step 14/15 : ENTRYPOINT ["echo", "Hello World"]
 ---> Using cache
 ---> c6e7fc7acc12
Step 15/15 : CMD [ "python3", "app.py" ]
 ---> Using cache
 ---> ad685c22eee9
Successfully built ad685c22eee9
Successfully tagged test:latest

Then running the command to start the container

sudo docker run --network host -d -p 8080:8080 test

Then to see what containers are running

sudo docker container list

Output:

CONTAINER ID   IMAGE     COMMAND   CREATED   STATUS    PORTS     NAMES

Nothing is running!

If I comment out the ENTRYPOINT in my Dockerfile and build, the container will run. It also doesn't matter what I put in the ENTRYPOINT. In my example above, I tried just a "Hello World". My intention is to have the ENTRYPOINT run a script that will set some environmental variables (see below). I am aware I could set them directly in the Dockerfile, but I would like to avoid doing that.

#!/bin/bash
source /etc/profile.d/vars.sh

If someone knows why including ENTRYPOINT in my Dockerfile won't let a container run, or what I can do to investigate further, please let me know. Alternatively, if someone knows a better way to set environment variables from a file using Dockerfile (not docker-compose.yml), please let me know as well.


Solution

  • A container only runs a single process, and then exits. If the image contains both an ENTRYPOINT and a CMD, the command is passed as additional arguments to the entrypoint. If you run your image without a -d option, so it runs in the foreground, I expect you will see the output

    Hello World python3 app.py
    

    as the result of combining these two sets of options.

    ... run a script that will set some [environment] variables ...

    Since the command is passed to the entrypoint as parameters, the usual thing to do is to end your entrypoint script with exec "$@", which replaces the entrypoint with whatever command is in those positional parameters. So I'd write your example as

    #!/bin/sh
    
    . /etc/profile.d/vars.sh
    exec "$@"
    

    using the standard . shell builtin to read the file, rather than the non-standard source.

    Since a container doesn't usually use shell dotfiles at all, depending on your setup, you could also put export commands directly in the entrypoint wrapper script, and they will survive through switching to the command.