Docker Community Forums

Share and learn in the Docker community.

Help with ENTRYPOINT

I’m having difficulty running a container, which is probably the result of not understanding ENTRYPOINT. Here’s what’s happening in really simple terms.

I have at the end of my Dockerfile:

ENTRYPOINT ["/abc/entrypoint.sh"]

/abc/entrypoint.sh looks like:

#!/bin/bash
/etc/init.d/mysql start
(cd /abc/solr; ./start_tomcat.sh)
(cd /abc/foobar; ./start_tomcat.sh)
/usr/sbin/apachectl start
# tail -f /abc/foobar/logs/catalina.out

That ‘tail’ at the end of the script seems to be key. If it’s commented out, the container starts but exits immediately with the following:

docker run -d -P <image>

If ‘tail’ is NOT commented out then that run command works just fine. Looking at the process table of the container I can see ‘tail -f …’ running. If I kill it, the container exits.

Can someone explain this in pedestrian terms (ELI5). I’ve read the ‘Dockerfile Reference’ page but it’s not making sense to me.

Docker will run your ENTRYPOINT script with the CMD as its arguments as the pid1 of the container. Once the pid1 exits, the container is considered to be stopped.

This ENTRYPOINT script appears to ignore any arguments it gets, which is fine.

It looks like you are running the /etc/init.d/mysql script, which does its thing end then exits. The same goes for all the rest of the commands too. They do their thing and then exit.

When you have the tail in place, that becomes the thing that keeps your entrypoint script from completing. If you don’t run the tail, the entrypoint script reaches its end, exits, and the container is considered stopped at that point.

Normally, you will want to directly run the command of the thing that will be running in the container.

I would actually break this up into four containers:

  • mysql container
  • tomcat for solr
  • tomcat for foobar
  • apache

Each of these containers would run each item in the foreground rather than run commands to start them in the background.

If for whatever reason, you really can’t split them all up, you could use something like supervisord or runit to run in the foreground as the pid1 of the container. They would be configured to run the other services.

Thank you! We are working to split these up. What is the recommended means of ‘directly running the command?’

For example, instead of calling the apachectl command, which is a command that tells apache to launch in the background and then exits, you would run httpd -DFOREGROUND, or apache -DFOREGROUND instead (depending on the name of your apache binary in your image since it can vary between distros)

If you use exec on that, then it will be the pid1 of your container. Many entrypoint scripts will use the following as the last line:

exec "$@"

That will tell the ENTRYPOINT to execute whatever command is passed in, or the default CMD in the Dockerfile if no command is specified. That way I can do things like docker run --rm -it <myimage> bash, and get a shell while my entrypoint still does all its stuff. The bash part would be the thing that the exec line calls.

1 Like

thanks for the insight, well explained. Is there a way to force the ENTRYPOINT script to be run as non-pid1 of the container? This way, we won’t have to use the trick like using a tail -f whatever file to keep the container from stopping after the script is run?

In my case, the script starts a service inside the container, making it a CaaS. So the container has to stay running for the service to be available to applications.

Also, my experiments show the same command won’t start with CMD, only ENTRYPOINT works.

Don’t daemonize the service you mention. It should block in the foreground and output to stdout / stderr (this requires a bit of configuration work in some cases).