Docker entrypoint and cmd together
Asked Answered
M

5

30

I try to setup a Docker with both entrypoint and cmd.

FROM debian:stretch
RUN apt-get update && \
apt install gnupg ca-certificates -y 
RUN echo "deb http://repo.aptly.info/ squeeze main" > /etc/apt/sources.list.d/aptly.list
RUN apt-key adv --keyserver keys.gnupg.net --recv-keys 9E3E53F19C7DE460
RUN apt update && apt install aptly -y
ADD aptly.conf /etc/aptly.conf
ADD start.sh .
VOLUME ["/aptly"]
ENTRYPOINT ["/start.sh"]
CMD ["aptly", "api", "serve"]

But entrypoint script is not stopping... The cmd command is not launching

Here my script :

#!/bin/bash
set -e 
init_aptly() {  
  #import pgp key
  #create nginx root folder in /aptly
  su -c "mkdir -p /aptly/.aptly/public"
  echo "12"
  #initialize repository
  #aptly create repo doze-server -   distribution="stable"
}
#check for first run
if [ ! -e /aptly/.aptly/public ]; then
  init_aptly
  echo "13"
fi
echo "14"

The script always echo 14, I would like only one and then, execute the cmd command from dockerfile

Matlick answered 5/12, 2017 at 8:6 Comment(0)
R
1

If your image has an ENTRYPOINT, as other answers here have noted, that is the only command the container runs, and the CMD is passed to it as additional arguments. Also see the section Understand how CMD and ENTRYPOINT interact in the Dockerfile documentation.

This means, in the entrypoint wrapper script, you need to actually run the command you're passed. The usual approach here is to end your script with the shell construct exec "$@", like

#!/bin/sh
# ... do startup-time setup ...
# ...then run the main container command
exec "$@"

Note that this works however the command part is provided. If for example you docker run your-image some-other-command, then it will run the entrypoint wrapper script from the image, but at the end it will run some-other-command instead of the CMD from the Dockerfile.

Richter answered 19/3 at 18:12 Comment(0)
R
70

When you use both entrypoint and command, the command section will be appended to entrypoint executable as arguments. Thus in your case:

ENTRYPOINT ["/start.sh"]
CMD ["aptly", "api", "serve"]

Is equivalent to running:

ENTRYPOINT["/start.sh", "aptly", "api", "serve"]
Razzia answered 5/12, 2017 at 9:19 Comment(7)
You can combine executable like bash scripts CMD ./start.sh && aptly api serveRazzia
This is so intuitive of course.... Strong negative feelings for whoever dev implemented it like so!Condemnation
This ans saved me even in 2019Postage
Weird... behavior?Philis
I must be blind but I couldn't seem to see where in the documentation it explains this. Can someone please put a link to the docs showing this?Violoncello
Is there any reason to prefer the first syntax over the second? E.g. could it affect how command overwrite (while running the container) applies?Enchase
@Violoncello Entrypoint example in docker reference (docs.docker.com/engine/reference/builder/…)Quincuncial
C
28

One important note, since nobody else has mentioned it: in order to use ENTRYPOINT and CMD together, you need to specify both in the array format. Doing something like this WILL NOT WORK:

ENTRYPOINT ./my_script.sh
CMD echo "hello world"

In the code above, ./my_script.sh will be called, but CMD will not be passed in.

Capeskin answered 11/3, 2021 at 23:34 Comment(1)
Thanks, you saved me from hours of debugging!Halo
P
6

Can't tell much without knowing what the entrypoint does, but essentially this is what you are doing with this combination of entrypoint and cmd:

/start.sh aptly api serve

If you are after simply starting your server you can simply do something like this (valid path to the aptly executable may be neccessary):

ENTRYPOINT ["aptly"]
CMD ["api", "serve"]

Unless you are doing much more than just running an executable there's no need for an entrypoint.

Protomartyr answered 5/12, 2017 at 8:19 Comment(2)
No need cmd, just ENTRYPOINT [/start.sh aptly api serve]?Matlick
Sorry I don't understand your question.Protomartyr
E
1

The following will allow the default arguments of entrypoint (provided in CMD) to be replaced by the arguments provided in docker run.

ENTRYPOINT ["/start.sh"]
CMD ["aptly", "api", "serve"]

The following will append the arguments provided in docker run to the entrypoint after the last argument. In order to override the entrypoint and its arguments at once you will need to explicitly use the --entrypoint flag:

ENTRYPOINT["/start.sh", "aptly", "api", "serve"]
Enchase answered 15/11, 2022 at 14:28 Comment(0)
R
1

If your image has an ENTRYPOINT, as other answers here have noted, that is the only command the container runs, and the CMD is passed to it as additional arguments. Also see the section Understand how CMD and ENTRYPOINT interact in the Dockerfile documentation.

This means, in the entrypoint wrapper script, you need to actually run the command you're passed. The usual approach here is to end your script with the shell construct exec "$@", like

#!/bin/sh
# ... do startup-time setup ...
# ...then run the main container command
exec "$@"

Note that this works however the command part is provided. If for example you docker run your-image some-other-command, then it will run the entrypoint wrapper script from the image, but at the end it will run some-other-command instead of the CMD from the Dockerfile.

Richter answered 19/3 at 18:12 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.