8

So I have a docker file which does this:

ENV ENV ${ENV}
ENV SERVICE_NAME ${SERVICE_NAME}
USER app
ENV HOME=/home/app
COPY target /home/app/target
COPY entrypoint.sh /home/app
WORKDIR /home/app
ENTRYPOINT /usr/bin/chamber exec ${ENV}_${SERVICE_NAME} -r 1 -- ./entrypoint.sh
CMD java -jar -Dspring.profiles.active=docker target/my.jar

So the ENTRYPOINT runs and pulls down some secrets from AWS Parameter store and populates them in the entrypoint.sh shell as environment variables. The entrypoint.sh then performs some actions with them, creates some files etc and in its last line does "exec $@".

I was then expecting the CMD to run but all it can see is the systemd service file running "ExecStop=/usr/bin/docker stop app".

The systemd service file does this to start the container:

ExecStart=/usr/bin/docker run --name app --memory-reservation=128m --memory=512m -e ENV=dev -e SERVICE_NAME=app 1234567890.dkr.ecr.eu-west-2.amazonaws.com/app:latest

What happened to CMD?

SnazzyBootMan
  • 669
  • 2
  • 15
  • 30
  • I'd recommend reading [What is the difference between CMD and ENTRYPOINT in a Dockerfile?](https://stackoverflow.com/questions/21553353/what-is-the-difference-between-cmd-and-entrypoint-in-a-dockerfile) to help you understand this – Liam Sep 01 '22 at 09:21

1 Answers1

20

As documented in https://docs.docker.com/engine/reference/builder/#understand-how-cmd-and-entrypoint-interact, if you combine the "shell form" of CMD and ENTRYPOINT, the CMD specification is omitted:

Exerpt from docs.docker.com

So you should rather use the "exec form" and write something like this:

…
ENTRYPOINT ["/usr/bin/chamber", "exec", "${ENV}_${SERVICE_NAME}", "-r", "1", "--", "./entrypoint.sh"]
CMD ["java -jar", "-Dspring.profiles.active=docker", "target/my.jar"]

However this won't work as is, because the ${ENV} and ${SERVICE_NAME} won't be expanded (as a shell would be required).

So the simplest, proper solution to apply here is to refactor your entrypoint.sh, or if ever you don't want to change it and still rely on environment variables with an "exec form" ENTRYPOINT, you could write instead:

…
RUN chmod a+x entrypoint1.sh
ENTRYPOINT ["./entrypoint1.sh"]
CMD ["java -jar", "-Dspring.profiles.active=docker", "target/my.jar"]

with a file

entrypoint1.sh

#!/bin/bash
exec /usr/bin/chamber exec ${ENV}_${SERVICE_NAME} -r 1 -- ./entrypoint.sh "$@"
ErikMD
  • 13,377
  • 3
  • 35
  • 71
  • It was actually in the exec form but I really needed those vars that chamber is fetching for me or the entrypoint.sh won't do much. – SnazzyBootMan Jan 30 '19 at 22:42
  • 1
    @SnazzyBootMan I don't see what you mean: your ENTRYPOINT in your question was in shell form. But if you don't want to change your entrypoint.sh, you can just use an extra entrypoint1.sh that will take care of the variable expansion... I will edit my answer to explain this. – ErikMD Jan 30 '19 at 22:49
  • Previously it was written in exec form which worked well with Amazon ECS in a task definition which could over write the CMD and populate the environment with a bunch of vars. Will a new shell be spawned when launching entrypoint.sh? The environment variables need to be maintained throughout. – SnazzyBootMan Jan 30 '19 at 23:17
  • 1
    @SnazzyBootMan Yes, precisely: (1) to be able to use the `CMD` directive it is compulsory to use the form `ENTRYPOINT ["program", "arg1", ...]`, **not** `ENTRYPOINT program arg1 ...`; (2) if you only write `ENTRYPOINT ["./entrypoint.sh"]` **and** `entrypoint.sh` has the executable flag (`RUN chmod a+x entrypoint.sh`) **and** `entrypoint.sh` starts with an appropriate *shebang*, then a shell will be spawned as expected, and the environment variables inside will be expanded; (3) and finally your entrypoint script should include some code to read the `CMD` arguments (cf. the `"$@"` in my answer). – ErikMD Jan 31 '19 at 19:00
  • 1
    great answer, I was trying this out today and had some problems. On reading your last comment I now see why I was using Alpine (which I only just mentioned now) for the container image so copying and pasting your answer wasn't going to work as an "appropriate shebang" hadn't been used. Replacing #!/bin/bash with #!/bin/ash worked and since I only just mentioned this unknown to you. – SnazzyBootMan Jan 31 '19 at 20:41
  • @SnazzyBootMan ok thanks for your feedback! glad that it worked for you. – ErikMD Jan 31 '19 at 20:45