linuxdockersignals

signal trap in Docker


I have a script that need to run in a loop an other program. But I would like to capture signals to stop the loop gracefully.

Here is my reproducible code:

loop.sh:

#!/bin/bash
COMMAND="logic.sh"
terminate=false

trap 'terminate=true' SIGTERM SIGINT

while true; do
    if $terminate; then
        echo "Termination signal received, waiting for the current process to finish..."
        wait
        echo "Process finished. Exiting..."
        exit 0
    fi
    $COMMAND &
    wait $!
done

logic.sh:

#!/bin/bash
sleep 5
date +%s

Dockerfile:

# FROM debian
FROM php:8.3-fpm
ADD loop.sh logic.sh /usr/local/bin/
CMD ["loop.sh"]

compose.yml:

services:
  app:
    build: .
    entrypoint: ''
    init: true

To test it, I run docker compose up --build; and in an other terminal docker compose stop. If you see Termination signal received, waiting for the current process to finish... then a timestamp, it was working. When using FROM php:8.3-fpm it does not work as expected... but when using FROM debian yes.

Why it doesn't behave the same way? How can I make it works with FROM php:...?
Thanks


Solution

  • If you check the image history with

    docker history php:8.3-fpm
    

    You will see that this image uses the QUIT signal to notify processes it's time to clean up and leave:

    <missing>      11 days ago   STOPSIGNAL SIGQUIT                              0B        buildkit.dockerfile.v0
    

    This means you ought to add the QUIT signal in your trap if you want to gracefully quit the contained process.