dockerdocker-entrypoint

Dockerfile: ENTRYPOINT doesn't expand ARG/ENV variable


I'm using CentOS.7 in a container (because I have to) and need to install some RedHat Software Collection packages to up-version a couple of tools. This involves running source scl_source enable <package> to set up the environment, which I'm doing using an ENTRYPOINT script. Here's what I have in my Dockerfile, and it works...

ENV ENTRYPOINT="/usr/bin/entrypoint.sh"
RUN echo "#!/bin/bash" > ${ENTRYPOINT}; \
    chmod +x ${ENTRYPOINT}

# we need later Git for Visual Studio Code
RUN yum -y install rh-git227; \
    echo "source scl_source enable rh-git227" >> ${ENTRYPOINT}

# we need later python for Visual Studio Code
RUN yum -y install rh-python38-python-devel; \
    echo "source scl_source enable rh-python38" >> ${ENTRYPOINT}

# finish off the extrypoint script to run whatever needs running
RUN echo 'env|sort' >> ${ENTRYPOINT}; \
    echo 'echo ARGV="$@"' >> ${ENTRYPOINT}; \
    echo 'exec "$@"' >> ${ENTRYPOINT}
ENTRYPOINT [ "/usr/bin/entrypoint.sh" ]

When I start the container using docker run -it container /bin/bash --login then the entrypoint.sh script is run and is passed the original command line (/bin/bash --login). All good.

However, it bugs me having to repeat the script name in the ENTRYPOINT command, but doing something "obvious" like ENTRYPOINT [ ${ENTRYPOINT} ] doesn't work, even if I change ENV to ARG in the definition. It appears to me that Docker requires a literal string in ENTRYPOINT [...].

I also tried ENTRYPOINT [ "/bin/sh", "-c", ${ENTRYPOINT} ] using ENV but using this form doesn't pass the command line through from docker run. Any suggestions?


Solution

  • The answer is to use "shell" form

    ENTRYPOINT ${ENTRYPOINT} "$0" "$@"
    

    which Docker converts to "array" form

    ENTRYPOINT [ "/bin/sh", "-c", "${ENTRYPOINT} \"$0\" \"$@\"" ]
    

    The shell substitutes $0 and $@ for the parameters appearing after the command_string, which are the contents of the Dockerfile CMD array (or the parameters passed to docker run, which override this).

    See https://stackoverflow.com/a/75063327/232452 for a full explanation.