Home > Back-end >  Creating an entrypoint.sh during docker build that takes variable on docker run
Creating an entrypoint.sh during docker build that takes variable on docker run

Time:11-18

I am trying to avoid using docker compose if possible, and so I'm building a Dockerfile that creates the entrypoint.sh within the Dockerfile. This works flawlessly with one issue - I need to accept an environment variable in the entrypoint.sh file

Here's the end of my Dockerfile:

FROM kalilinux/kali-rolling

RUN echo "\n##### Provision openvas user #####\n" >> /opt/entrypoint.sh && \
    echo "useradd -rm -d /home/openvas -s /bin/bash -g _gvm openvas" >> /opt/entrypoint.sh && \
    echo "chown -R openvas:_gvm /home/openvas" >> /opt/entrypoint.sh && \
    echo "gvmd --user=admin --new-password=${OV_PASSWORD}" >> /opt/entrypoint.sh && \
    chmod  x /opt/entrypoint.sh

ENTRYPOINT ["/opt/entrypoint.sh"]
CMD ["tail", "-f","/dev/null"]

However, when I try to start the container with docker run and passing an environment variable to it, it doesn't seem to work because of some format error. Here's an example of what I'm running and its output:

ubuntu@ip-10-20-32-116:~/openvas$ docker run -e OV_PASSWORD=password -ti 05190b668480 /bin/bash
standard_init_linux.go:228: exec user process caused: exec format error

Any thoughts as to what may be happening here? I believe the error started as soon as I added the ${OV_PASSWORD} into the echo statement. I also tried with just OV_PASSWORD and got a similar error, so not quite sure what I'm doing wrong in terms of formatting.

CodePudding user response:

At a mechanical level, you may find it easier to create the entrypoint script as a separate file on your host, then simply COPY it into the image. This avoids the quoting problem that @DannyB highlights in their answer.

FROM kalilinux/kali-rolling
COPY entrypoint.sh /opt/entrypoint.sh
# RUN chmod  x /opt/entrypoint.sh  # if not already executable
ENTRYPOINT ["/opt/entrypoint.sh"]
CMD ["tail", "-f","/dev/null"]

Make sure that script ends with the line exec "$@" to run the CMD, and that the ENTRYPOINT line in the Dockerfile uses JSON-array syntax. (Comments suggest your setup already has this correctly.)

There are a couple of things in the setup you show that will always be done exactly the same way every time you start the container, and these could be refactored to run only once when you build the image. So I might have instead:

FROM kalilinux/kali-rolling
... do the other things to install the application ...

# Create a non-root user
RUN useradd -rM -g _gvm openvas

# Change file ownership so the non-root user can modify the application
# at runtime (not usually recommended)
# RUN chown -R openvas:_gvm /home/openvas

# Copy in the entrypoint script
COPY entrypoint.sh /opt/entrypoint.sh
# RUN chmod  x /opt/entrypoint.sh  # if not already executable

# Specify how to run the container
USER openvas
ENTRYPOINT ["/opt/entrypoint.sh"]
CMD ["openvas", "-u"]

Where the entrypoint just contains

#!/bin/sh
# /opt/entrypoint.sh

# Configure the application password
if [ -n "$OV_PASSWORD" ]; then
  gvmd --user=admin "--new-password=${OV_PASSWORD}"
fi

# Run the main container command
exec "$@"

CodePudding user response:

when both CMD and ENTRYPOINT are given, the CMD is treated as default input to entrypoint.

I suggest, you remove CMD and use docker logs <container-id> instead

CodePudding user response:

You have a couple of issues with your Dockerfile.

  1. CMD is used as arguments to ENTRYPOINT, therefore not behaving as you expect.
  2. When you echo with variables, and you wish the variables to NOT be evaluated during the echo, use single quotes.
  3. Your ENTRYPOINT does not need to use the [...] syntax.

To achieve what you want, put the tail -f command inside your entrypoint.

Here is a working sample

FROM alpine
RUN echo 'echo got password $PASS' > /opt/entrypoint.sh && \
    echo "tail -f /dev/null" >> /opt/entrypoint.sh && \
    chmod  x /opt/entrypoint.sh
ENTRYPOINT "/opt/entrypoint.sh"

Run with:

$ docker run --rm -it -e PASS=123 your_image_name

CodePudding user response:

RUN echo "\n##### Provision openvas user #####\n" >> /opt/entrypoint.sh && \
    echo "useradd -rm -d /home/openvas -s /bin/bash -g _gvm openvas" >> /opt/entrypoint.sh && \
    echo "chown -R openvas:_gvm /home/openvas" >> /opt/entrypoint.sh && \
    echo "gvmd --user=admin --new-password=${OV_PASSWORD}" >> /opt/entrypoint.sh && \
    chmod  x /opt/entrypoint.sh

Your shell script doesn't have an interpreter defined, e.g. the first line that's normally #!/bin/sh. And then you try to execute that script from the kernel with an exec rather than from within a shell that would default to using itself to interpret the script since you've used the json/exec format for your entrypoint:

ENTRYPOINT ["/opt/entrypoint.sh"]

That is what is triggering the:

standard_init_linux.go:228: exec user process caused: exec format error

Which is saying your executable/binary isn't properly formatted for the kernel to run. To fix, make the first line a shell that exists in your image:

RUN echo '#!/bin/sh\n' > /opt/entrypoint.sh && \
    echo '\n##### Provision openvas user #####\n' >> /opt/entrypoint.sh && \
    echo 'useradd -rm -d /home/openvas -s /bin/bash -g _gvm openvas' >> /opt/entrypoint.sh && \
    echo 'chown -R openvas:_gvm /home/openvas' >> /opt/entrypoint.sh && \
    echo 'gvmd --user=admin --new-password=${OV_PASSWORD}' >> /opt/entrypoint.sh && \
    chmod  x /opt/entrypoint.sh
  • Related