Issue
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.
Answered By - David Maze Answer Checked By - Marilyn (WPSolving Volunteer)