How to keep a container running?

When you use

docker run ... raspbx bash

then bash will have PID 1 and the container is alive as long as bash is running. When you exit bash, then bash stops, so the container does not have any process and stops too even if you run another process with docker exec.

With your second solution

docker run ... -itd --entrypoint=/bin/bash raspbx

Bash should have run indefinitely because of the interactive (-i) and detached (-d) mode without executing the startup script. So my question is how did you execute the startup script in this case? What do you mean by “as soon as the container finishes the script”? What script?

Changing the entrypoint won’t help if the final command resulted by the SHELL, ENTRYPOINT and CMD directives does not keep the container running. In your case it is “/run/startup.sh”. If I am not mistaken startup.sh runs some process in the background and then as a final step runs process status checking in a loop in every minute. It terminates only if one of the background processes exited so grep returnes an error code. Since one terminated process is enough to stop the loop if not all of the background processes run forever, the startup script will not be able to run forever. This means the process with PID 1 will disappear and the container stops.

Using “sleep inf” as a command can help but then you won’t be able to handle signals with the “trap” command to terminate the container properly since signals would be cought only when sleep inf terminates. Which will not happen. Adding “–init” to the docker run command might help. Then “tini” will function as the init process with PID 1 and executes the startup script and forwards the stop signal (SIGTERM) to the sleep command.

Although, it will not solve your original problem if you run sleep as a docker command. You would have to use docker exec to exeute the startup script and that process would not be under “tini”. Stopping the container could damage your database.

I have a demo script to show how you can handle signals and waiting for a process in the background, but It is only for one process.

#!/bin/bash

set -m

echo "HELLO" > "/usr/local/apache2/htdocs/index.html"

httpd -D FOREGROUND & pid=$!

for signal in TERM USR1 HUP INT; do
  trap "echo SIGNAL: $signal; kill -s $signal $pid" $signal
done

# USR2 converted to WINCH
trap "kill -s WINCH $pid" USR2

status=999
while true; do
  if (( $status <= 128 )); then
    # Status codes larger than 128 indicates a trapped signal terminated the wait command (128 + SIGNAL).
    # In any other case we can stop the loop. 
    break
  fi
  wait -f
  status=$?
  echo exit status: $status
done

The key is the wait command running in a loop.

You could modify it to handle multiple processes but I recommend using supervisor instead. You can read about it in the documentation:
Run multiple services in a container

You could also use systemd if that is absolutely necessary but It is not recommended and much more difficult to do it right. I use that only for testing installations in containers instead of using virtual machines.

So my final advise is to use supervisor and you don’t have to deal with catching and forwarding signals, which is important if you don’t like loosing data :slight_smile: