Docker entrypoint and cmd together - docker

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

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"]

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.

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.

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"]

Related

Shebang in JavaScript ignored when executed as command in Docker with "/bin/bash" as entrypoint

When I try to execute a JavaScript file with a shebang such as #!/usr/bin/env node through the command argument of docker run ... it seems to "ignore" the shebang.
$ docker run --rm foobar/hello-world /hello-world.js
/hello-world.js: line 2: syntax error near unexpected token `'Hello, World!''
/hello-world.js: line 2: `console.log('Hello, World!');'
Dockerfile
FROM node:13.12-alpine
COPY hello-world.js /hello-world.js
RUN chmod +x /hello-world.js
RUN apk update && apk update && apk add bash
ENTRYPOINT ["/bin/bash"]
hello-world.js
#!/usr/bin/env node
console.log('Hello, World!');
When I use /hello-world.js as the entrypoint directly (ENTRYPOINT ["/hello-world.js"]) it works correctly.
Add -c to the entrypoint so bash will expect a command. Without -c it interprets its argument as the name of a bash script to execute.
ENTRYPOINT ["/bin/bash", "-c"]
I'd recommend just setting the default CMD to the program you're installing in your container, and generally preferring CMD to ENTRYPOINT if you only need one of them.
FROM node:13.12-alpine
COPY hello-world.js /hello-world.js
RUN chmod +x /hello-world.js
CMD ["/hello-world.js"]
When you provide a command at the docker run command line, it overrides the Dockerfile CMD (if any), and it's appended to the ENTRYPOINT. In your original example the ENTRYPOINT from the Dockerfile is combined with the docker run command and you're getting a combined command bash /hello-world.js.
If you do need an interactive shell to debug the container, you can launch that with
docker run --rm -it foobar/hello-world /bin/sh

Docker: Cannot execute binary file

I can't run any binary in my docker container.
Dockerfile:
FROM ubuntu:eoan AS compiler-build
RUN apt-get update && \
dpkg --add-architecture i386 && \
apt-get install -y gcc \
gcc-multilib \
make \
cmake \
git \
python3.8 \
bash
WORKDIR /home
ADD . /home/pawn
RUN mkdir build
WORKDIR /home/build
ENTRYPOINT ["/bin/bash"]
CMD ["/bin/bash"]
I can't even use file builtin:
[root#LAPTOP-EJ5BH6DJ compiler]:~/dev/private/SAMP/compiler (v13.11.0) (master) dc run compiler file bash
/usr/bin/file: /usr/bin/file: cannot execute binary file
From this forum thread:
This error occurs when you use a shell in your entrypoint without the "-c" argument
So, if you change your Dockerfile to end with
ENTRYPOINT [ "/bin/bash", "-l", "-c" ]
then you can run binary files.
Note the purpose of the options for /bin/bash, from the manpage:
-l: Make bash act as if it had been invoked as a login shell
-c: If the -c option is present, then commands are read from the first non-option argument command_string. If there are arguments after the command_string, the first argument is assigned to $0 and any remaining arguments are assigned to the positional parameters. The assignment to $0 sets the name of the shell, which is used in warning and error messages.
Additionally, this article is a worthwhile read on how to use both ENTRYPOINT and CMD together, and what their differences are.
EDIT: Here's another article that goes into a trivial (but clearer than the first article) example using the echo shell builtin.
EDIT: Here's an adaptation of the trivial example from the second article I linked:
FROM ubuntu
ENTRYPOINT [ "/bin/bash", "-l", "-c" ]
CMD [ "ls" ]
$ docker build -t test .
$ docker run --rm test
bin
boot
...
var
$ docker run --rm test "ls etc"
adduser.conf
alternatives
apt
...
update-motd.d
xattr.conf
Note the " around ls /etc. Without the quotes, the argument /etc doesn't seem to be passed to the ls command as I might expect.
Entrypoint can't point to /bin/bash it seems. Removing
ENTRYPOINT ["/bin/bash"] is enough to make it work.
I hit the same error. Unlike the other answers, my error was related to my docker run parameters:
# failed
docker run -it $(pwd | xargs basename):latest bash
# worked
docker run -it $(pwd | xargs basename):latest
I didn't need to add bash as I already had this in my Dockerfile:
ENTRYPOINT ["/bin/bash"]
There are times when we don't have control over the image's Dockerfile but it's original entrypoint has an issue.
We could overwrite it's entrypoint to debug issues:
# example
docker run --rm \
--entrypoint /bin/bash \
-it apache/spark-py:v3.3.0

Why I am bounced from the Docker container?

FROM docker.elastic.co/elasticsearch/elasticsearch:5.5.2
USER root
WORKDIR /usr/share/elasticsearch/
ENV ES_HOSTNAME elasticsearch
ENV ES_PORT 9200
RUN chown elasticsearch:elasticsearch config/elasticsearch.yml
RUN chown -R elasticsearch:elasticsearch data
# install security plugin
RUN bin/elasticsearch-plugin install -b com.floragunn:search-guard-5:5.5.2-16
COPY ./safe-guard/install_demo_configuration.sh plugins/search-guard-5/tools/
COPY ./safe-guard/init-sgadmin.sh plugins/search-guard-5/tools/
RUN chmod +x plugins/search-guard-5/tools/init-sgadmin.sh
ADD ./run.sh .
RUN chmod +x run.sh
RUN chmod +x plugins/search-guard-5/tools/install_demo_configuration.sh
RUN ./plugins/search-guard-5/tools/install_demo_configuration.sh -y
RUN chmod +x sgadmin_demo.sh
RUN yum install tree -y
#RUN curl -k -u admin:admin https://localhost:9200/_searchguard/authinfo
RUN usermod -aG wheel elasticsearch
USER elasticsearch
EXPOSE 9200
#ENTRYPOINT ["nohup", "./run.sh", "&"]
ENTRYPOINT ["/usr/share/elasticsearch/run.sh"]
#CMD ["echo", "hello"]
Once I add either CMD or Entrypoint - "Container is exited with code 0"
#!/bin/bash
exec $#
If I comment ENTRYPOINT or CMD - all is great.
What I am doing wrong???
If you take a look at official 5.6.9 elasticsearch Dockerfile, you will see the following at the bottom:
ENTRYPOINT ["/docker-entrypoint.sh"]
CMD ["elasticsearch"]
If you do not know the difference between CMD and ENTRYPOINT, read this answer.
What you're doing is you're overwriting those two instructions with something else. What you really need is to extend CMD. What I usually do in my images, I create an sh script and combine different things I need and then indicate the script for CMD. So, you need to run sgadmin_demo.sh, but you need to wait for elasticsearch first. Create a start.sh script:
#!/bin/bash
elasticsearch
sleep 15
sgadmin_demo.sh
Now, add your script to your image and run it on CMD:
FROM: ...
...
COPY start.sh /tmp/start.sh
CMD ["/tmp/start.sh"]
Now it should be executed once you start a container. Don't forget to build :)

Modifying a Docker container's ENTRYPOINT to run a script before the CMD

I'd like to run a script to attach a network drive every time I create a container in Docker. From what I've read this should be possible by setting a custom entrypoint. Here's what I have so far:
FROM ubuntu
COPY *.py /opt/package/my_code
RUN mkdir /efs && \
apt-get install nfs-common -y && \
echo "#!/bin/sh" > /root/startup.sh && \
echo "mount -t nfs4 -o net.nfs.com:/ /nfs" >> /root/startup.sh && \
echo "/bin/sh -c '$1'" >> /root/startup.sh && \
chmod +x /root/startup.sh
WORKDIR /opt/package
ENV PYTHONPATH /opt/package
ENTRYPOINT ["/root/startup.sh"]
At the moment my CMD is not getting passed through properly to my /bin/sh line, but I'm wondering if there isn't an easier way to accomplish this?
Unfortunately I don't have control over how my containers will be created. This means I can't simply prepend the network mounting command to the original docker command.
From documentation:
CMD should be used as a way of defining default arguments for an ENTRYPOINT command or for executing an ad-hoc command in a container
So if you have an ENTRYPOINT specified, the CMD will be passed as additional arguments for it. It means that your entrypoint script should explicitly handle these arguments.
In your case, when you run :
docker run yourimage yourcommand
What is executed in your container is :
/root/startup.sh yourcommand
The solution is to add exec "$#" at the end of your /root/startup.sh script. This way, it will execute any command given as its arguments.
You might want to read about the ENTRYPOINT mechanisms and its interaction with CMD.

Compose not working with Dockerfile using FROM

Right now, I am using a docker-compose file that contains, amongst other stuff, a few lines like this. This executes without any sort of problem. It deploys perfectly and I'm able to access the web server inside through the browser.
container:
command: bash -c "cd /code; chmod +x ./deploy/start_dev.sh; ./deploy/start_dev.sh;"
image: python:3.6
As I needed to be able to connect to the container through SSH I created a Dockerfile that installs it and modifies the config file so it allows unsafe root connections:
FROM python:3.6
RUN apt-get update && apt-get install openssh-server -y
RUN sed -i "s/PermitRootLogin without-password/PermitRootLogin yes/g" /etc/ssh/sshd_config
RUN sed -i "s/PermitEmptyPasswords no/PermitEmptyPasswords yes/g" /etc/ssh/sshd_config
RUN service ssh restart
RUN echo "root:sshpassword" | chpasswd
ENTRYPOINT ["/bin/sh", "-c"]
CMD ["/bin/bash"]
After that I changed the docker-compose file to:
container:
command: bash -c "cd /code; chmod +x ./deploy/start_dev.sh; ./deploy/start_dev.sh;"
build:
context: .
From this moment on, whenever I run docker-compose up I get the following output:
container exited with code 0
Is there something I am missing?
In your docker-compose.yaml file, add the following parameter (under the 'container' section):
tty: true
Solved it switching the last two lines of the Dockerfile
ENTRYPOINT ["/bin/sh", "-c"]
CMD ["/bin/bash"]
to
CMD ["/bin/bash", "-c", "/bin/bash"]

Resources