2

Taken from Docker's documentation that if you want to run a standalone NodeJS script you are supposed to use the following command:

docker run -it --rm --name my-running-script -v "$PWD":/usr/src/app -w /usr/src/app node:8 node your-daemon-or-script.js

This works except that it's not possible to stop the script using Ctrl-C. How can I achieve that?

Here is my script.js:

console.log('Started - now try to kill me...');

setTimeout(function () {
   console.log('End of life.');
}, 10000);
halfer
  • 19,824
  • 17
  • 99
  • 186
adamsfamily
  • 1,746
  • 19
  • 37

1 Answers1

2

This note is hidden in the extended docker run documentation:

Note: A process running as PID 1 inside a container is treated specially by Linux: it ignores any signal with the default action. So, the process will not terminate on SIGINT or SIGTERM unless it is coded to do so.

The main Docker container process (your container's ENTRYPOINT or CMD or the equivalent specified on the command line) runs as process ID 1 inside the container. This is normally reserved for a special init process and is special in a couple of ways.

Possibly the simplest answer is to let Docker inject an init process for you as PID 1 by adding --init to your docker run command.

Alternatively, on Node you can register a signal event to explicitly handle SIGINT. For example, if I extend your script to have

process.on('SIGINT', function() {
    process.exit();
});

and then rebuild the image and re-run it, it responds to ^C.

David Maze
  • 130,717
  • 29
  • 175
  • 215
  • Thanks, accepted as an answer since both suggestions work! Is there any disadvantage of using the --init parameter in the docker run command as this seems the most elegant way since it doesn't require injecting any code into the NodeJS sources? – adamsfamily May 25 '19 at 11:50
  • If having the absolute tiniest runtime profile is important to you, `--init` adds another process, but the particular init Docker injects here (tini) is pretty small. There's a matching Docker Compose option, but if you step out of plain-Docker land, I'm pretty sure there's no corresponding option in a Kubernetes Pod, for example. – David Maze May 25 '19 at 12:07