From 1cd9274c801ee98b3e68210551fcbed2a85ec453 Mon Sep 17 00:00:00 2001 From: Costas Papastathis Date: Wed, 21 Sep 2022 19:27:47 +0300 Subject: [PATCH 01/23] fix: adding 14 tested images --- 14/Dockerfile | 1 + 14/Dockerfile.fedora | 1 + 14/Dockerfile.rhel7 | 1 + 14/Dockerfile.rhel8 | 1 + 14/s2i/bin/init-wrapper | 18 ++++++++++++++++++ 14/s2i/bin/run | 3 +++ 6 files changed, 25 insertions(+) create mode 100644 14/s2i/bin/init-wrapper diff --git a/14/Dockerfile b/14/Dockerfile index 2e55cf1e..4a8b6dbd 100644 --- a/14/Dockerfile +++ b/14/Dockerfile @@ -63,6 +63,7 @@ RUN yum install -y centos-release-scl-rh && \ # Copy the S2I scripts from the specific language image to $STI_SCRIPTS_PATH COPY ./s2i/bin/ $STI_SCRIPTS_PATH +RUN chmod +x $STI_SCRIPTS_PATH/init-wrapper # Copy extra files to the image, including help file. COPY ./root/ / diff --git a/14/Dockerfile.fedora b/14/Dockerfile.fedora index 9d6f3598..33928583 100644 --- a/14/Dockerfile.fedora +++ b/14/Dockerfile.fedora @@ -58,6 +58,7 @@ RUN yum -y module enable nodejs:$NODEJS_VERSION && \ # Copy the S2I scripts from the specific language image to $STI_SCRIPTS_PATH COPY ./s2i/bin/ $STI_SCRIPTS_PATH +RUN chmod +x $STI_SCRIPTS_PATH/init-wrapper # Copy extra files to the image, including help file. COPY ./root/ / diff --git a/14/Dockerfile.rhel7 b/14/Dockerfile.rhel7 index 2e9879a2..68736a3f 100644 --- a/14/Dockerfile.rhel7 +++ b/14/Dockerfile.rhel7 @@ -67,6 +67,7 @@ RUN yum install -y yum-utils && \ # Copy the S2I scripts from the specific language image to $STI_SCRIPTS_PATH COPY ./s2i/bin/ $STI_SCRIPTS_PATH +RUN chmod +x $STI_SCRIPTS_PATH/init-wrapper # Copy extra files to the image. COPY ./root/ / diff --git a/14/Dockerfile.rhel8 b/14/Dockerfile.rhel8 index cbf89f4b..c632e56d 100644 --- a/14/Dockerfile.rhel8 +++ b/14/Dockerfile.rhel8 @@ -65,6 +65,7 @@ RUN yum -y module enable nodejs:$NODEJS_VERSION && \ # Copy the S2I scripts from the specific language image to $STI_SCRIPTS_PATH COPY ./s2i/bin/ $STI_SCRIPTS_PATH +RUN chmod +x $STI_SCRIPTS_PATH/init-wrapper # Copy extra files to the image. COPY ./root/ / diff --git a/14/s2i/bin/init-wrapper b/14/s2i/bin/init-wrapper new file mode 100644 index 00000000..24e0d078 --- /dev/null +++ b/14/s2i/bin/init-wrapper @@ -0,0 +1,18 @@ +#!/bin/bash + +# Overview of how this script works: http://veithen.io/2014/11/16/sigterm-propagation.html +# Set a trap to kill the main app process when this +# init script receives SIGTERM or SIGINT +trap 'kill -s TERM $PID' TERM INT +# Execute the main application in the background +"$@" & +PID=$! +# wait command always terminates when trap is caught, even if the process hasn't finished yet +wait $PID +# Remove the trap and wait till the app process finishes completely +trap - TERM INT +# We wait again, since the first wait terminates when trap is caught +wait $PID +# Exit with the exit code of the app process +STATUS=$? +exit $STATUS \ No newline at end of file diff --git a/14/s2i/bin/run b/14/s2i/bin/run index ff566f55..c94ac202 100755 --- a/14/s2i/bin/run +++ b/14/s2i/bin/run @@ -20,6 +20,9 @@ run_node() { if [ "$DEV_MODE" == true ]; then echo "Launching via nodemon..." exec nodemon --inspect="$DEBUG_PORT" + elif [ -v NODE_CMD ]; then + echo "launching via init wrapper..." + exec ${STI_SCRIPTS_PATH}/init-wrapper $NODE_CMD else echo "Launching via npm..." exec npm run -d $NPM_RUN From cb3944933f3fb8da692a391109ac6602b1a26f4c Mon Sep 17 00:00:00 2001 From: Costas Papastathis Date: Wed, 21 Sep 2022 19:28:33 +0300 Subject: [PATCH 02/23] fix: adding 14 minimal tested images --- 14-minimal/Dockerfile.rhel8 | 1 + 14-minimal/s2i/bin/init-wrapper | 18 ++++++++++++++++++ 14-minimal/s2i/bin/run | 3 +++ 3 files changed, 22 insertions(+) create mode 100644 14-minimal/s2i/bin/init-wrapper diff --git a/14-minimal/Dockerfile.rhel8 b/14-minimal/Dockerfile.rhel8 index 081daeef..b75686e9 100644 --- a/14-minimal/Dockerfile.rhel8 +++ b/14-minimal/Dockerfile.rhel8 @@ -58,6 +58,7 @@ RUN INSTALL_PKGS="nodejs nodejs-nodemon npm findutils tar" && \ rm -rf /mnt/rootfs/var/cache/* /mnt/rootfs/var/log/dnf* /mnt/rootfs/var/log/yum.* COPY ./s2i/bin/ /usr/libexec/s2i +RUN chmod +x /usr/libexec/s2i/init-wrapper # Copy extra files to the image. COPY ./root/ / diff --git a/14-minimal/s2i/bin/init-wrapper b/14-minimal/s2i/bin/init-wrapper new file mode 100644 index 00000000..24e0d078 --- /dev/null +++ b/14-minimal/s2i/bin/init-wrapper @@ -0,0 +1,18 @@ +#!/bin/bash + +# Overview of how this script works: http://veithen.io/2014/11/16/sigterm-propagation.html +# Set a trap to kill the main app process when this +# init script receives SIGTERM or SIGINT +trap 'kill -s TERM $PID' TERM INT +# Execute the main application in the background +"$@" & +PID=$! +# wait command always terminates when trap is caught, even if the process hasn't finished yet +wait $PID +# Remove the trap and wait till the app process finishes completely +trap - TERM INT +# We wait again, since the first wait terminates when trap is caught +wait $PID +# Exit with the exit code of the app process +STATUS=$? +exit $STATUS \ No newline at end of file diff --git a/14-minimal/s2i/bin/run b/14-minimal/s2i/bin/run index db076fde..65918fd6 100755 --- a/14-minimal/s2i/bin/run +++ b/14-minimal/s2i/bin/run @@ -16,6 +16,9 @@ run_node() { if [ "$DEV_MODE" == true ]; then echo "Launching via nodemon..." exec nodemon --inspect="$DEBUG_PORT" + elif [ -v NODE_CMD ]; then + echo "launching via init wrapper..." + exec /usr/libexec/s2i/init-wrapper $NODE_CMD else echo "Launching via npm..." exec npm run -d $NPM_RUN From f16a7312b034d5d3b248febb86f05f7c7a5958df Mon Sep 17 00:00:00 2001 From: Costas Papastathis Date: Wed, 21 Sep 2022 19:29:15 +0300 Subject: [PATCH 03/23] fix: adding 16 tested images --- 16/Dockerfile.c9s | 1 + 16/Dockerfile.fedora | 1 + 16/Dockerfile.rhel8 | 1 + 16/Dockerfile.rhel9 | 1 + 16/s2i/bin/init-wrapper | 18 ++++++++++++++++++ 16/s2i/bin/run | 3 +++ 6 files changed, 25 insertions(+) create mode 100644 16/s2i/bin/init-wrapper diff --git a/16/Dockerfile.c9s b/16/Dockerfile.c9s index 8c80589e..af567a4e 100644 --- a/16/Dockerfile.c9s +++ b/16/Dockerfile.c9s @@ -64,6 +64,7 @@ RUN MODULE_DEPS="make gcc gcc-c++ git openssl-devel" && \ # Copy the S2I scripts from the specific language image to $STI_SCRIPTS_PATH COPY ./s2i/bin/ $STI_SCRIPTS_PATH +RUN chmod +x $STI_SCRIPTS_PATH/init-wrapper # Copy extra files to the image. COPY ./root/ / diff --git a/16/Dockerfile.fedora b/16/Dockerfile.fedora index bac27ef7..7bb76d46 100644 --- a/16/Dockerfile.fedora +++ b/16/Dockerfile.fedora @@ -63,6 +63,7 @@ RUN MODULE_DEPS="make gcc gcc-c++ libatomic_ops git openssl-devel" && \ # Copy the S2I scripts from the specific language image to $STI_SCRIPTS_PATH COPY ./s2i/bin/ $STI_SCRIPTS_PATH +RUN chmod +x $STI_SCRIPTS_PATH/init-wrapper # Copy extra files to the image, including help file. COPY ./root/ / diff --git a/16/Dockerfile.rhel8 b/16/Dockerfile.rhel8 index 83adf78e..081cf4b1 100644 --- a/16/Dockerfile.rhel8 +++ b/16/Dockerfile.rhel8 @@ -65,6 +65,7 @@ RUN yum -y module enable nodejs:$NODEJS_VERSION && \ # Copy the S2I scripts from the specific language image to $STI_SCRIPTS_PATH COPY ./s2i/bin/ $STI_SCRIPTS_PATH +RUN chmod +x $STI_SCRIPTS_PATH/init-wrapper # Copy extra files to the image. COPY ./root/ / diff --git a/16/Dockerfile.rhel9 b/16/Dockerfile.rhel9 index 5ca6686c..72957b65 100644 --- a/16/Dockerfile.rhel9 +++ b/16/Dockerfile.rhel9 @@ -63,6 +63,7 @@ RUN MODULE_DEPS="make gcc gcc-c++ git openssl-devel" && \ # Copy the S2I scripts from the specific language image to $STI_SCRIPTS_PATH COPY ./s2i/bin/ $STI_SCRIPTS_PATH +RUN chmod +x $STI_SCRIPTS_PATH/init-wrapper # Copy extra files to the image. COPY ./root/ / diff --git a/16/s2i/bin/init-wrapper b/16/s2i/bin/init-wrapper new file mode 100644 index 00000000..24e0d078 --- /dev/null +++ b/16/s2i/bin/init-wrapper @@ -0,0 +1,18 @@ +#!/bin/bash + +# Overview of how this script works: http://veithen.io/2014/11/16/sigterm-propagation.html +# Set a trap to kill the main app process when this +# init script receives SIGTERM or SIGINT +trap 'kill -s TERM $PID' TERM INT +# Execute the main application in the background +"$@" & +PID=$! +# wait command always terminates when trap is caught, even if the process hasn't finished yet +wait $PID +# Remove the trap and wait till the app process finishes completely +trap - TERM INT +# We wait again, since the first wait terminates when trap is caught +wait $PID +# Exit with the exit code of the app process +STATUS=$? +exit $STATUS \ No newline at end of file diff --git a/16/s2i/bin/run b/16/s2i/bin/run index ff566f55..c94ac202 100755 --- a/16/s2i/bin/run +++ b/16/s2i/bin/run @@ -20,6 +20,9 @@ run_node() { if [ "$DEV_MODE" == true ]; then echo "Launching via nodemon..." exec nodemon --inspect="$DEBUG_PORT" + elif [ -v NODE_CMD ]; then + echo "launching via init wrapper..." + exec ${STI_SCRIPTS_PATH}/init-wrapper $NODE_CMD else echo "Launching via npm..." exec npm run -d $NPM_RUN From 60fafae98ef8fb9451c573ce2327ddde963ec74d Mon Sep 17 00:00:00 2001 From: Costas Papastathis Date: Wed, 21 Sep 2022 19:29:53 +0300 Subject: [PATCH 04/23] fix: adding 16 minimal tested images --- 16-minimal/Dockerfile.rhel8 | 1 + 16-minimal/Dockerfile.rhel9 | 1 + 16-minimal/s2i/bin/init-wrapper | 18 ++++++++++++++++++ 16-minimal/s2i/bin/run | 3 +++ 4 files changed, 23 insertions(+) create mode 100644 16-minimal/s2i/bin/init-wrapper diff --git a/16-minimal/Dockerfile.rhel8 b/16-minimal/Dockerfile.rhel8 index 6c3da074..486d0ab2 100644 --- a/16-minimal/Dockerfile.rhel8 +++ b/16-minimal/Dockerfile.rhel8 @@ -59,6 +59,7 @@ RUN INSTALL_PKGS="nodejs nodejs-nodemon nodejs-full-i18n npm findutils tar which rm -rf /mnt/rootfs/var/cache/* /mnt/rootfs/var/log/dnf* /mnt/rootfs/var/log/yum.* COPY ./s2i/bin/ /usr/libexec/s2i +RUN chmod +x /usr/libexec/s2i/init-wrapper # Copy extra files to the image. COPY ./root/ / diff --git a/16-minimal/Dockerfile.rhel9 b/16-minimal/Dockerfile.rhel9 index 098adb6f..c60f586b 100644 --- a/16-minimal/Dockerfile.rhel9 +++ b/16-minimal/Dockerfile.rhel9 @@ -57,6 +57,7 @@ RUN INSTALL_PKGS="nodejs nodejs-nodemon nodejs-full-i18n npm findutils tar which rm -rf /mnt/rootfs/var/cache/* /mnt/rootfs/var/log/dnf* /mnt/rootfs/var/log/yum.* COPY ./s2i/bin/ /usr/libexec/s2i +RUN chmod +x /usr/libexec/s2i/init-wrapper # Copy extra files to the image. COPY ./root/ / diff --git a/16-minimal/s2i/bin/init-wrapper b/16-minimal/s2i/bin/init-wrapper new file mode 100644 index 00000000..24e0d078 --- /dev/null +++ b/16-minimal/s2i/bin/init-wrapper @@ -0,0 +1,18 @@ +#!/bin/bash + +# Overview of how this script works: http://veithen.io/2014/11/16/sigterm-propagation.html +# Set a trap to kill the main app process when this +# init script receives SIGTERM or SIGINT +trap 'kill -s TERM $PID' TERM INT +# Execute the main application in the background +"$@" & +PID=$! +# wait command always terminates when trap is caught, even if the process hasn't finished yet +wait $PID +# Remove the trap and wait till the app process finishes completely +trap - TERM INT +# We wait again, since the first wait terminates when trap is caught +wait $PID +# Exit with the exit code of the app process +STATUS=$? +exit $STATUS \ No newline at end of file diff --git a/16-minimal/s2i/bin/run b/16-minimal/s2i/bin/run index 7894f47f..2f24bee2 100755 --- a/16-minimal/s2i/bin/run +++ b/16-minimal/s2i/bin/run @@ -16,6 +16,9 @@ run_node() { if [ "$DEV_MODE" == true ]; then echo "Launching via nodemon..." exec nodemon --inspect="$DEBUG_PORT" + elif [ -v NODE_CMD ]; then + echo "launching via init wrapper..." + exec /usr/libexec/s2i/init-wrapper $NODE_CMD else echo "Launching via npm..." exec npm run -d $NPM_RUN From a0662c83c65918e0fa61f4d0b4b949f63c6ba708 Mon Sep 17 00:00:00 2001 From: Costas Papastathis Date: Wed, 14 Sep 2022 17:55:56 +0300 Subject: [PATCH 05/23] fix: adding 18 tested images --- 18/Dockerfile.c8s | 1 + 18/Dockerfile.fedora | 1 + 18/s2i/bin/init-wrapper | 18 ++++++++++++++++++ 18/s2i/bin/run | 3 +++ 4 files changed, 23 insertions(+) create mode 100644 18/s2i/bin/init-wrapper diff --git a/18/Dockerfile.c8s b/18/Dockerfile.c8s index de2cb60d..745ea48b 100644 --- a/18/Dockerfile.c8s +++ b/18/Dockerfile.c8s @@ -65,6 +65,7 @@ RUN yum -y module enable nodejs:$NODEJS_VERSION && \ # Copy the S2I scripts from the specific language image to $STI_SCRIPTS_PATH COPY ./s2i/bin/ $STI_SCRIPTS_PATH +RUN chmod +x $STI_SCRIPTS_PATH/init-wrapper # Copy extra files to the image. COPY ./root/ / diff --git a/18/Dockerfile.fedora b/18/Dockerfile.fedora index 6ca74b63..8052e6b7 100644 --- a/18/Dockerfile.fedora +++ b/18/Dockerfile.fedora @@ -57,6 +57,7 @@ RUN MODULE_DEPS="make gcc gcc-c++ libatomic_ops git openssl-devel" && \ # Copy the S2I scripts from the specific language image to $STI_SCRIPTS_PATH COPY ./s2i/bin/ $STI_SCRIPTS_PATH +RUN chmod +x $STI_SCRIPTS_PATH/init-wrapper # Copy extra files to the image, including help file. COPY ./root/ / diff --git a/18/s2i/bin/init-wrapper b/18/s2i/bin/init-wrapper new file mode 100644 index 00000000..24e0d078 --- /dev/null +++ b/18/s2i/bin/init-wrapper @@ -0,0 +1,18 @@ +#!/bin/bash + +# Overview of how this script works: http://veithen.io/2014/11/16/sigterm-propagation.html +# Set a trap to kill the main app process when this +# init script receives SIGTERM or SIGINT +trap 'kill -s TERM $PID' TERM INT +# Execute the main application in the background +"$@" & +PID=$! +# wait command always terminates when trap is caught, even if the process hasn't finished yet +wait $PID +# Remove the trap and wait till the app process finishes completely +trap - TERM INT +# We wait again, since the first wait terminates when trap is caught +wait $PID +# Exit with the exit code of the app process +STATUS=$? +exit $STATUS \ No newline at end of file diff --git a/18/s2i/bin/run b/18/s2i/bin/run index ff566f55..c94ac202 100755 --- a/18/s2i/bin/run +++ b/18/s2i/bin/run @@ -20,6 +20,9 @@ run_node() { if [ "$DEV_MODE" == true ]; then echo "Launching via nodemon..." exec nodemon --inspect="$DEBUG_PORT" + elif [ -v NODE_CMD ]; then + echo "launching via init wrapper..." + exec ${STI_SCRIPTS_PATH}/init-wrapper $NODE_CMD else echo "Launching via npm..." exec npm run -d $NPM_RUN From f400f8b0887ee0cab10cd7f888310fd9cba8c9fa Mon Sep 17 00:00:00 2001 From: Costas Papastathis Date: Tue, 18 Oct 2022 17:14:00 +0300 Subject: [PATCH 06/23] adding documentation about NODE_CMD option --- 14-minimal/README.md | 2 +- 14/README.md | 2 +- 16/README.md | 2 +- 18-minimal/README.md | 3 +++ 18/README.md | 3 +++ 5 files changed, 9 insertions(+), 3 deletions(-) diff --git a/14-minimal/README.md b/14-minimal/README.md index 0b71befc..b7154d6a 100644 --- a/14-minimal/README.md +++ b/14-minimal/README.md @@ -1,4 +1,4 @@ NodeJS 14 minimal container image ========================= -**The NodeJS 14 minimal image is deprecated.** \ No newline at end of file +**The NodeJS 14 minimal image is deprecated.** diff --git a/14/README.md b/14/README.md index 3c52f46d..44da925c 100644 --- a/14/README.md +++ b/14/README.md @@ -1,4 +1,4 @@ NodeJS 14 container image ========================= -**The NodeJS 14 image is deprecated.** \ No newline at end of file +**The NodeJS 14 image is deprecated.** diff --git a/16/README.md b/16/README.md index 45d4827a..4c25f28e 100644 --- a/16/README.md +++ b/16/README.md @@ -1,4 +1,4 @@ NodeJS 16 container image ========================= -**The NodeJS 16 image is deprecated.** \ No newline at end of file +**The NodeJS 16 image is deprecated.** diff --git a/18-minimal/README.md b/18-minimal/README.md index 3c5b783b..133334d8 100644 --- a/18-minimal/README.md +++ b/18-minimal/README.md @@ -215,6 +215,9 @@ Application developers can use the following environment variables to configure **`NPM_RUN`** Select an alternate / custom runtime mode, defined in your `package.json` file's [`scripts`](https://docs.npmjs.com/misc/scripts) section (default: npm run "start"). These user-defined run-scripts are unavailable while `DEV_MODE` is in use. +**`NODE_CMD`** + When specified (e.g.Specify `NODE_CMD="node server.js"`) the `NODE_CMD` is executed by the `init-wrapper` script, which handles reaping zombie processes and signal forwarding (SIGINT, SIGTERM) to Node.js application. + #### Additional variables used in the full-sized image **`HTTP_PROXY`** diff --git a/18/README.md b/18/README.md index 405abbd6..2110d714 100644 --- a/18/README.md +++ b/18/README.md @@ -145,6 +145,9 @@ Application developers can use the following environment variables to configure **`NPM_RUN`** Select an alternate / custom runtime mode, defined in your `package.json` file's [`scripts`](https://docs.npmjs.com/misc/scripts) section (default: npm run "start"). These user-defined run-scripts are unavailable while `DEV_MODE` is in use. +**`NODE_CMD`** + When specified (e.g.Specify `NODE_CMD="node server.js"`) the `NODE_CMD` is executed by the `init-wrapper` script, which handles reaping zombie processes and signal forwarding (SIGINT, SIGTERM) to Node.js application. + **`HTTP_PROXY`** Use an npm proxy during assembly From a2c283d76e93014976f48e12508c4118cef7e600 Mon Sep 17 00:00:00 2001 From: Costas Papastathis Date: Mon, 21 Nov 2022 18:10:27 +0200 Subject: [PATCH 07/23] adding INIT_WRAPPER option on node 16 --- 16-minimal/s2i/bin/run | 24 ++++++++++++++++++++++-- 16/Dockerfile.rhel8 | 2 +- 16/s2i/bin/run | 24 ++++++++++++++++++++++-- 3 files changed, 45 insertions(+), 5 deletions(-) diff --git a/16-minimal/s2i/bin/run b/16-minimal/s2i/bin/run index 2f24bee2..1c1a6123 100755 --- a/16-minimal/s2i/bin/run +++ b/16-minimal/s2i/bin/run @@ -17,13 +17,33 @@ run_node() { echo "Launching via nodemon..." exec nodemon --inspect="$DEBUG_PORT" elif [ -v NODE_CMD ]; then + if [ "$INIT_WRAPPER" == true ]; then + echo "launching via init wrapper..." + exec ${STI_SCRIPTS_PATH}/init-wrapper $NODE_CMD + else + echo "Launching via ${NODE_CMD}" + echo "exec $NODE_CMD" + fi + elif [ "$INIT_WRAPPER" == true ]; then + + if [ -f "server.js" ]; then + start_file="server.js" + elif [ -f "index.js" ]; then + start_file="main.js" + elif [ -f "main.js" ]; then + start_file="main.js" + else + echo "Failed to find file for staring the Node.js application" + exit 1 + fi + echo "launching via init wrapper..." - exec /usr/libexec/s2i/init-wrapper $NODE_CMD + exec ${STI_SCRIPTS_PATH}/init-wrapper node $start_file else echo "Launching via npm..." exec npm run -d $NPM_RUN fi -} +} #Set the debug port to 5858 by default. if [ -z "$DEBUG_PORT" ]; then diff --git a/16/Dockerfile.rhel8 b/16/Dockerfile.rhel8 index 081cf4b1..fd291a8e 100644 --- a/16/Dockerfile.rhel8 +++ b/16/Dockerfile.rhel8 @@ -1,4 +1,4 @@ -FROM ubi8/s2i-core:1 +FROM registry.access.redhat.com/ubi8/s2i-core:1 # This image provides a Node.JS environment you can use to run your Node.JS # applications. diff --git a/16/s2i/bin/run b/16/s2i/bin/run index c94ac202..46b095ff 100755 --- a/16/s2i/bin/run +++ b/16/s2i/bin/run @@ -21,13 +21,33 @@ run_node() { echo "Launching via nodemon..." exec nodemon --inspect="$DEBUG_PORT" elif [ -v NODE_CMD ]; then + if [ "$INIT_WRAPPER" == true ]; then + echo "launching via init wrapper..." + exec ${STI_SCRIPTS_PATH}/init-wrapper $NODE_CMD + else + echo "Launching via ${NODE_CMD}" + echo "exec $NODE_CMD" + fi + elif [ "$INIT_WRAPPER" == true ]; then + + if [ -f "server.js" ]; then + start_file="server.js" + elif [ -f "index.js" ]; then + start_file="main.js" + elif [ -f "main.js" ]; then + start_file="main.js" + else + echo "Failed to find file for staring the Node.js application" + exit 1 + fi + echo "launching via init wrapper..." - exec ${STI_SCRIPTS_PATH}/init-wrapper $NODE_CMD + exec ${STI_SCRIPTS_PATH}/init-wrapper node $start_file else echo "Launching via npm..." exec npm run -d $NPM_RUN fi -} +} #Set the debug port to 5858 by default. if [ -z "$DEBUG_PORT" ]; then From 8e9cb2415c86d8c52f5c09c073094154be74b6d5 Mon Sep 17 00:00:00 2001 From: Costas Papastathis Date: Tue, 22 Nov 2022 12:29:01 +0200 Subject: [PATCH 08/23] adding INIT_WRAPPER option on node 14 and 18 --- 14-minimal/s2i/bin/run | 22 +++++++++++++++++++++- 14/s2i/bin/run | 24 ++++++++++++++++++++++-- 18-minimal/s2i/bin/run | 25 ++++++++++++++++++++++++- 18/s2i/bin/run | 24 ++++++++++++++++++++++-- 4 files changed, 89 insertions(+), 6 deletions(-) diff --git a/14-minimal/s2i/bin/run b/14-minimal/s2i/bin/run index 65918fd6..1c1a6123 100755 --- a/14-minimal/s2i/bin/run +++ b/14-minimal/s2i/bin/run @@ -17,8 +17,28 @@ run_node() { echo "Launching via nodemon..." exec nodemon --inspect="$DEBUG_PORT" elif [ -v NODE_CMD ]; then + if [ "$INIT_WRAPPER" == true ]; then + echo "launching via init wrapper..." + exec ${STI_SCRIPTS_PATH}/init-wrapper $NODE_CMD + else + echo "Launching via ${NODE_CMD}" + echo "exec $NODE_CMD" + fi + elif [ "$INIT_WRAPPER" == true ]; then + + if [ -f "server.js" ]; then + start_file="server.js" + elif [ -f "index.js" ]; then + start_file="main.js" + elif [ -f "main.js" ]; then + start_file="main.js" + else + echo "Failed to find file for staring the Node.js application" + exit 1 + fi + echo "launching via init wrapper..." - exec /usr/libexec/s2i/init-wrapper $NODE_CMD + exec ${STI_SCRIPTS_PATH}/init-wrapper node $start_file else echo "Launching via npm..." exec npm run -d $NPM_RUN diff --git a/14/s2i/bin/run b/14/s2i/bin/run index c94ac202..46b095ff 100755 --- a/14/s2i/bin/run +++ b/14/s2i/bin/run @@ -21,13 +21,33 @@ run_node() { echo "Launching via nodemon..." exec nodemon --inspect="$DEBUG_PORT" elif [ -v NODE_CMD ]; then + if [ "$INIT_WRAPPER" == true ]; then + echo "launching via init wrapper..." + exec ${STI_SCRIPTS_PATH}/init-wrapper $NODE_CMD + else + echo "Launching via ${NODE_CMD}" + echo "exec $NODE_CMD" + fi + elif [ "$INIT_WRAPPER" == true ]; then + + if [ -f "server.js" ]; then + start_file="server.js" + elif [ -f "index.js" ]; then + start_file="main.js" + elif [ -f "main.js" ]; then + start_file="main.js" + else + echo "Failed to find file for staring the Node.js application" + exit 1 + fi + echo "launching via init wrapper..." - exec ${STI_SCRIPTS_PATH}/init-wrapper $NODE_CMD + exec ${STI_SCRIPTS_PATH}/init-wrapper node $start_file else echo "Launching via npm..." exec npm run -d $NPM_RUN fi -} +} #Set the debug port to 5858 by default. if [ -z "$DEBUG_PORT" ]; then diff --git a/18-minimal/s2i/bin/run b/18-minimal/s2i/bin/run index 7894f47f..1c1a6123 100755 --- a/18-minimal/s2i/bin/run +++ b/18-minimal/s2i/bin/run @@ -16,11 +16,34 @@ run_node() { if [ "$DEV_MODE" == true ]; then echo "Launching via nodemon..." exec nodemon --inspect="$DEBUG_PORT" + elif [ -v NODE_CMD ]; then + if [ "$INIT_WRAPPER" == true ]; then + echo "launching via init wrapper..." + exec ${STI_SCRIPTS_PATH}/init-wrapper $NODE_CMD + else + echo "Launching via ${NODE_CMD}" + echo "exec $NODE_CMD" + fi + elif [ "$INIT_WRAPPER" == true ]; then + + if [ -f "server.js" ]; then + start_file="server.js" + elif [ -f "index.js" ]; then + start_file="main.js" + elif [ -f "main.js" ]; then + start_file="main.js" + else + echo "Failed to find file for staring the Node.js application" + exit 1 + fi + + echo "launching via init wrapper..." + exec ${STI_SCRIPTS_PATH}/init-wrapper node $start_file else echo "Launching via npm..." exec npm run -d $NPM_RUN fi -} +} #Set the debug port to 5858 by default. if [ -z "$DEBUG_PORT" ]; then diff --git a/18/s2i/bin/run b/18/s2i/bin/run index c94ac202..46b095ff 100755 --- a/18/s2i/bin/run +++ b/18/s2i/bin/run @@ -21,13 +21,33 @@ run_node() { echo "Launching via nodemon..." exec nodemon --inspect="$DEBUG_PORT" elif [ -v NODE_CMD ]; then + if [ "$INIT_WRAPPER" == true ]; then + echo "launching via init wrapper..." + exec ${STI_SCRIPTS_PATH}/init-wrapper $NODE_CMD + else + echo "Launching via ${NODE_CMD}" + echo "exec $NODE_CMD" + fi + elif [ "$INIT_WRAPPER" == true ]; then + + if [ -f "server.js" ]; then + start_file="server.js" + elif [ -f "index.js" ]; then + start_file="main.js" + elif [ -f "main.js" ]; then + start_file="main.js" + else + echo "Failed to find file for staring the Node.js application" + exit 1 + fi + echo "launching via init wrapper..." - exec ${STI_SCRIPTS_PATH}/init-wrapper $NODE_CMD + exec ${STI_SCRIPTS_PATH}/init-wrapper node $start_file else echo "Launching via npm..." exec npm run -d $NPM_RUN fi -} +} #Set the debug port to 5858 by default. if [ -z "$DEBUG_PORT" ]; then From 07b8ff0cfed3b57de3bce7471833d5fd2ae6e3c7 Mon Sep 17 00:00:00 2001 From: Costas Papastathis Date: Tue, 22 Nov 2022 17:55:04 +0200 Subject: [PATCH 09/23] adding docs for init-wrapper script --- 18-minimal/README.md | 41 +++++++++++++++++++++++++++++++++++++++++ 18/README.md | 41 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 82 insertions(+) diff --git a/18-minimal/README.md b/18-minimal/README.md index 133334d8..857e4dd6 100644 --- a/18-minimal/README.md +++ b/18-minimal/README.md @@ -319,6 +319,47 @@ Below is an example _package.json_ file with the _main_ attribute and _start_ sc #### Note: `oc rsync` is only available in versions 3.1+ of OpenShift. +## init-wrapper + +init-wrapper script is located on `/usr/libexec/s2i/init-wrapper` and is used for preventing below circumstances: + +- Proper signal handling and propagation, as Node.js was not designed to run as PID 1. +- Reaping zombie child processes +- Avoiding use of npm, more information on [reference architecture](https://github.com/nodeshift/nodejs-reference-architecture/blob/e4c4dc1fd20c2cac392e862859aaad27f85d504f/docs/development/building-good-containers.md#avoiding-using-npm-to-start-application) + +A detailed explanation on how the init-wrapper script works is avalable on [this url](http://veithen.io/2014/11/16/sigterm-propagation.html). + +Example of using init-wrapper: + +**During image build** +``` +s2i -e INIT_WRAPPER=true build . buildImage node-app +docker run node-app +``` +**During container start** +``` +s2i build . buildImage node-app +docker run -e INIT_WRAPPER=true node-app +``` + +`init-wrapper` script can be disabled by setting the `INIT_WRAPPER` env variable to `false`. + +``` +docker run -e INIT_WRAPPER=false node-app +``` +`NODE_CMD` can be used during the build process or container start, in order to have more control on the command that `init-wrapper` script will wrap. + +For example: + +**during container build** +``` +s2i -e INIT_WRAPPER=true -e NODE_CMD="node index.js" build . buildImage node-app + +``` +**during container start** +``` +docker run -e INIT_WRAPPER=false -e NODE_CMD="node index.js" node-app +``` See also -------- diff --git a/18/README.md b/18/README.md index 2110d714..8c3929c9 100644 --- a/18/README.md +++ b/18/README.md @@ -247,6 +247,47 @@ Below is an example _package.json_ file with the _main_ attribute and _start_ sc #### Note: `oc rsync` is only available in versions 3.1+ of OpenShift. +## init-wrapper + +init-wrapper script is located on `/usr/libexec/s2i/init-wrapper` and is used for preventing below circumstances: + +- Proper signal handling and propagation, as Node.js was not designed to run as PID 1. +- Reaping zombie child processes +- Avoiding use of npm, more information on [reference architecture](https://github.com/nodeshift/nodejs-reference-architecture/blob/e4c4dc1fd20c2cac392e862859aaad27f85d504f/docs/development/building-good-containers.md#avoiding-using-npm-to-start-application) + +A detailed explanation on how the init-wrapper script works is avalable on [this url](http://veithen.io/2014/11/16/sigterm-propagation.html). + +Example of using init-wrapper: + +**During image build** +``` +s2i -e INIT_WRAPPER=true build . buildImage node-app +docker run node-app +``` +**During container start** +``` +s2i build . buildImage node-app +docker run -e INIT_WRAPPER=true node-app +``` + +`init-wrapper` script can be disabled by setting the `INIT_WRAPPER` env variable to `false`. + +``` +docker run -e INIT_WRAPPER=false node-app +``` +`NODE_CMD` can be used during the build process or container start, in order to have more control on the command that `init-wrapper` script will wrap. + +For example: + +**during container build** +``` +s2i -e INIT_WRAPPER=true -e NODE_CMD="node index.js" build . buildImage node-app + +``` +**during container start** +``` +docker run -e INIT_WRAPPER=false -e NODE_CMD="node index.js" node-app +``` See also -------- From 44dc3269092e9e73c3e21e08366d6e60cbe259f5 Mon Sep 17 00:00:00 2001 From: Costas Papastathis Date: Fri, 25 Nov 2022 13:20:03 +0200 Subject: [PATCH 10/23] Apply suggestions from code review Co-authored-by: Michael Dawson --- 18/README.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/18/README.md b/18/README.md index 8c3929c9..f8cab2ce 100644 --- a/18/README.md +++ b/18/README.md @@ -249,13 +249,14 @@ Below is an example _package.json_ file with the _main_ attribute and _start_ sc ## init-wrapper -init-wrapper script is located on `/usr/libexec/s2i/init-wrapper` and is used for preventing below circumstances: +init-wrapper script is located on `/usr/libexec/s2i/init-wrapper` and is used to handle: - Proper signal handling and propagation, as Node.js was not designed to run as PID 1. - Reaping zombie child processes -- Avoiding use of npm, more information on [reference architecture](https://github.com/nodeshift/nodejs-reference-architecture/blob/e4c4dc1fd20c2cac392e862859aaad27f85d504f/docs/development/building-good-containers.md#avoiding-using-npm-to-start-application) +Avoiding use of npm, there is more information on why you want to avoid that in the [Node.js reference architecture](https://github.com/nodeshift/nodejs-reference-architecture/blob/e4c4dc1fd20c2cac392e862859aaad27f85d504f/docs/development/building-good-containers.md#avoiding-using-npm-to-start-application). When the INIT_WRAPPER is set to true the application is started via the init script instead of using npm start. -A detailed explanation on how the init-wrapper script works is avalable on [this url](http://veithen.io/2014/11/16/sigterm-propagation.html). +A detailed explanation on how the init-wrapper script works is avalable in +[this url](http://veithen.io/2014/11/16/sigterm-propagation.html). Example of using init-wrapper: From 15fe7f613d66b1ed13571e563beb75c3c97dad2f Mon Sep 17 00:00:00 2001 From: Costas Papastathis Date: Fri, 25 Nov 2022 13:35:30 +0200 Subject: [PATCH 11/23] Applying suggestions from code review --- 14-minimal/s2i/bin/run | 3 +-- 14/s2i/bin/run | 3 +-- 16-minimal/s2i/bin/run | 3 +-- 16/s2i/bin/run | 3 +-- 18-minimal/README.md | 12 ++++++++---- 18-minimal/s2i/bin/run | 3 +-- 18/README.md | 5 ++++- 18/s2i/bin/run | 3 +-- 8 files changed, 18 insertions(+), 17 deletions(-) diff --git a/14-minimal/s2i/bin/run b/14-minimal/s2i/bin/run index 1c1a6123..0c4d5c9b 100755 --- a/14-minimal/s2i/bin/run +++ b/14-minimal/s2i/bin/run @@ -25,11 +25,10 @@ run_node() { echo "exec $NODE_CMD" fi elif [ "$INIT_WRAPPER" == true ]; then - if [ -f "server.js" ]; then start_file="server.js" elif [ -f "index.js" ]; then - start_file="main.js" + start_file="index.js" elif [ -f "main.js" ]; then start_file="main.js" else diff --git a/14/s2i/bin/run b/14/s2i/bin/run index 46b095ff..9dbceb3f 100755 --- a/14/s2i/bin/run +++ b/14/s2i/bin/run @@ -29,11 +29,10 @@ run_node() { echo "exec $NODE_CMD" fi elif [ "$INIT_WRAPPER" == true ]; then - if [ -f "server.js" ]; then start_file="server.js" elif [ -f "index.js" ]; then - start_file="main.js" + start_file="index.js" elif [ -f "main.js" ]; then start_file="main.js" else diff --git a/16-minimal/s2i/bin/run b/16-minimal/s2i/bin/run index 1c1a6123..0c4d5c9b 100755 --- a/16-minimal/s2i/bin/run +++ b/16-minimal/s2i/bin/run @@ -25,11 +25,10 @@ run_node() { echo "exec $NODE_CMD" fi elif [ "$INIT_WRAPPER" == true ]; then - if [ -f "server.js" ]; then start_file="server.js" elif [ -f "index.js" ]; then - start_file="main.js" + start_file="index.js" elif [ -f "main.js" ]; then start_file="main.js" else diff --git a/16/s2i/bin/run b/16/s2i/bin/run index 46b095ff..9dbceb3f 100755 --- a/16/s2i/bin/run +++ b/16/s2i/bin/run @@ -29,11 +29,10 @@ run_node() { echo "exec $NODE_CMD" fi elif [ "$INIT_WRAPPER" == true ]; then - if [ -f "server.js" ]; then start_file="server.js" elif [ -f "index.js" ]; then - start_file="main.js" + start_file="index.js" elif [ -f "main.js" ]; then start_file="main.js" else diff --git a/18-minimal/README.md b/18-minimal/README.md index 857e4dd6..c5e605fb 100644 --- a/18-minimal/README.md +++ b/18-minimal/README.md @@ -216,7 +216,10 @@ Application developers can use the following environment variables to configure Select an alternate / custom runtime mode, defined in your `package.json` file's [`scripts`](https://docs.npmjs.com/misc/scripts) section (default: npm run "start"). These user-defined run-scripts are unavailable while `DEV_MODE` is in use. **`NODE_CMD`** - When specified (e.g.Specify `NODE_CMD="node server.js"`) the `NODE_CMD` is executed by the `init-wrapper` script, which handles reaping zombie processes and signal forwarding (SIGINT, SIGTERM) to Node.js application. + When specified (e.g.Specify `NODE_CMD="node server.js"`) the value of `NODE_CMD` is used to start the application instead of `npm start`. + +**`INIT_WRAPPER`** + When set to "true", the application is started via the `init-wrapper` script instead of using `npm start`, by looking for the presence of the files `server.js`, `index.js` or `main.js` in the order in which they are listed. In case of `NODE_CMD` environemnt variale is specified, then `init-wrapper` script will use the value of `NODE_CMD` to start your application. #### Additional variables used in the full-sized image @@ -321,13 +324,14 @@ Below is an example _package.json_ file with the _main_ attribute and _start_ sc ## init-wrapper -init-wrapper script is located on `/usr/libexec/s2i/init-wrapper` and is used for preventing below circumstances: +init-wrapper script is located on `/usr/libexec/s2i/init-wrapper` and is used to handle: - Proper signal handling and propagation, as Node.js was not designed to run as PID 1. - Reaping zombie child processes -- Avoiding use of npm, more information on [reference architecture](https://github.com/nodeshift/nodejs-reference-architecture/blob/e4c4dc1fd20c2cac392e862859aaad27f85d504f/docs/development/building-good-containers.md#avoiding-using-npm-to-start-application) +Avoiding use of npm, there is more information on why you want to avoid that in the [Node.js reference architecture](https://github.com/nodeshift/nodejs-reference-architecture/blob/e4c4dc1fd20c2cac392e862859aaad27f85d504f/docs/development/building-good-containers.md#avoiding-using-npm-to-start-application). When the INIT_WRAPPER is set to true the application is started via the init script instead of using npm start. -A detailed explanation on how the init-wrapper script works is avalable on [this url](http://veithen.io/2014/11/16/sigterm-propagation.html). +A detailed explanation on how the init-wrapper script works is avalable in +[this url](http://veithen.io/2014/11/16/sigterm-propagation.html). Example of using init-wrapper: diff --git a/18-minimal/s2i/bin/run b/18-minimal/s2i/bin/run index 1c1a6123..0c4d5c9b 100755 --- a/18-minimal/s2i/bin/run +++ b/18-minimal/s2i/bin/run @@ -25,11 +25,10 @@ run_node() { echo "exec $NODE_CMD" fi elif [ "$INIT_WRAPPER" == true ]; then - if [ -f "server.js" ]; then start_file="server.js" elif [ -f "index.js" ]; then - start_file="main.js" + start_file="index.js" elif [ -f "main.js" ]; then start_file="main.js" else diff --git a/18/README.md b/18/README.md index f8cab2ce..c0f46047 100644 --- a/18/README.md +++ b/18/README.md @@ -146,7 +146,10 @@ Application developers can use the following environment variables to configure Select an alternate / custom runtime mode, defined in your `package.json` file's [`scripts`](https://docs.npmjs.com/misc/scripts) section (default: npm run "start"). These user-defined run-scripts are unavailable while `DEV_MODE` is in use. **`NODE_CMD`** - When specified (e.g.Specify `NODE_CMD="node server.js"`) the `NODE_CMD` is executed by the `init-wrapper` script, which handles reaping zombie processes and signal forwarding (SIGINT, SIGTERM) to Node.js application. + When specified (e.g.Specify `NODE_CMD="node server.js"`) the value of `NODE_CMD` is used to start the application instead of `npm start`. + +**`INIT_WRAPPER`** + When set to "true", the application is started via the `init-wrapper` script instead of using `npm start`, by looking for the presence of the files `server.js`, `index.js` or `main.js` in the order in which they are listed. In case of `NODE_CMD` environemnt variale is specified, then `init-wrapper` script will use the value of `NODE_CMD` to start your application. **`HTTP_PROXY`** Use an npm proxy during assembly diff --git a/18/s2i/bin/run b/18/s2i/bin/run index 46b095ff..9dbceb3f 100755 --- a/18/s2i/bin/run +++ b/18/s2i/bin/run @@ -29,11 +29,10 @@ run_node() { echo "exec $NODE_CMD" fi elif [ "$INIT_WRAPPER" == true ]; then - if [ -f "server.js" ]; then start_file="server.js" elif [ -f "index.js" ]; then - start_file="main.js" + start_file="index.js" elif [ -f "main.js" ]; then start_file="main.js" else From d50fdbde1df709c9101b159c9ae8f18a81b38b08 Mon Sep 17 00:00:00 2001 From: Costas Papastathis Date: Tue, 3 Jan 2023 16:10:53 +0200 Subject: [PATCH 12/23] fix: updating run script --- 14-minimal/s2i/bin/run | 28 ++++++++++++++++------------ 14/s2i/bin/run | 28 ++++++++++++++++------------ 16-minimal/s2i/bin/run | 28 ++++++++++++++++------------ 16/s2i/bin/run | 28 ++++++++++++++++------------ 18-minimal/s2i/bin/init-wrapper | 18 ++++++++++++++++++ 18-minimal/s2i/bin/run | 28 ++++++++++++++++------------ 18/s2i/bin/run | 28 ++++++++++++++++------------ 7 files changed, 114 insertions(+), 72 deletions(-) create mode 100644 18-minimal/s2i/bin/init-wrapper diff --git a/14-minimal/s2i/bin/run b/14-minimal/s2i/bin/run index 0c4d5c9b..1b9a0596 100755 --- a/14-minimal/s2i/bin/run +++ b/14-minimal/s2i/bin/run @@ -25,19 +25,23 @@ run_node() { echo "exec $NODE_CMD" fi elif [ "$INIT_WRAPPER" == true ]; then - if [ -f "server.js" ]; then - start_file="server.js" - elif [ -f "index.js" ]; then - start_file="index.js" - elif [ -f "main.js" ]; then - start_file="main.js" - else - echo "Failed to find file for staring the Node.js application" - exit 1 - fi - echo "launching via init wrapper..." - exec ${STI_SCRIPTS_PATH}/init-wrapper node $start_file + package_json_start=$(cat package.json | grep "start" | sed -r 's/(.*)"start"([^:]*[^"]*")(.*)",/\3/') + package_json_main=$(cat package.json | grep "main" | sed -r 's/(.*)"main"([^:]*[^"]*")(.*)",/\3/') + + if [ -n "$package_json_start" ]; then + start_command=$package_json_start + elif [ -n $package_json_main ]; then + start_command="node ." + elif [ -f "server.js" ]; then + start_command="node server.js" + else + echo "Failed to find file for starting the Node.js application" + exit 1 + fi + + echo "launching via init wrapper..." + exec ${STI_SCRIPTS_PATH}/init-wrapper $start_command else echo "Launching via npm..." exec npm run -d $NPM_RUN diff --git a/14/s2i/bin/run b/14/s2i/bin/run index 9dbceb3f..15698997 100755 --- a/14/s2i/bin/run +++ b/14/s2i/bin/run @@ -29,19 +29,23 @@ run_node() { echo "exec $NODE_CMD" fi elif [ "$INIT_WRAPPER" == true ]; then - if [ -f "server.js" ]; then - start_file="server.js" - elif [ -f "index.js" ]; then - start_file="index.js" - elif [ -f "main.js" ]; then - start_file="main.js" - else - echo "Failed to find file for staring the Node.js application" - exit 1 - fi - echo "launching via init wrapper..." - exec ${STI_SCRIPTS_PATH}/init-wrapper node $start_file + package_json_start=$(cat package.json | grep "start" | sed -r 's/(.*)"start"([^:]*[^"]*")(.*)",/\3/') + package_json_main=$(cat package.json | grep "main" | sed -r 's/(.*)"main"([^:]*[^"]*")(.*)",/\3/') + + if [ -n "$package_json_start" ]; then + start_command=$package_json_start + elif [ -n $package_json_main ]; then + start_command="node ." + elif [ -f "server.js" ]; then + start_command="node server.js" + else + echo "Failed to find file for starting the Node.js application" + exit 1 + fi + + echo "launching via init wrapper..." + exec ${STI_SCRIPTS_PATH}/init-wrapper $start_command else echo "Launching via npm..." exec npm run -d $NPM_RUN diff --git a/16-minimal/s2i/bin/run b/16-minimal/s2i/bin/run index 0c4d5c9b..1b9a0596 100755 --- a/16-minimal/s2i/bin/run +++ b/16-minimal/s2i/bin/run @@ -25,19 +25,23 @@ run_node() { echo "exec $NODE_CMD" fi elif [ "$INIT_WRAPPER" == true ]; then - if [ -f "server.js" ]; then - start_file="server.js" - elif [ -f "index.js" ]; then - start_file="index.js" - elif [ -f "main.js" ]; then - start_file="main.js" - else - echo "Failed to find file for staring the Node.js application" - exit 1 - fi - echo "launching via init wrapper..." - exec ${STI_SCRIPTS_PATH}/init-wrapper node $start_file + package_json_start=$(cat package.json | grep "start" | sed -r 's/(.*)"start"([^:]*[^"]*")(.*)",/\3/') + package_json_main=$(cat package.json | grep "main" | sed -r 's/(.*)"main"([^:]*[^"]*")(.*)",/\3/') + + if [ -n "$package_json_start" ]; then + start_command=$package_json_start + elif [ -n $package_json_main ]; then + start_command="node ." + elif [ -f "server.js" ]; then + start_command="node server.js" + else + echo "Failed to find file for starting the Node.js application" + exit 1 + fi + + echo "launching via init wrapper..." + exec ${STI_SCRIPTS_PATH}/init-wrapper $start_command else echo "Launching via npm..." exec npm run -d $NPM_RUN diff --git a/16/s2i/bin/run b/16/s2i/bin/run index 9dbceb3f..15698997 100755 --- a/16/s2i/bin/run +++ b/16/s2i/bin/run @@ -29,19 +29,23 @@ run_node() { echo "exec $NODE_CMD" fi elif [ "$INIT_WRAPPER" == true ]; then - if [ -f "server.js" ]; then - start_file="server.js" - elif [ -f "index.js" ]; then - start_file="index.js" - elif [ -f "main.js" ]; then - start_file="main.js" - else - echo "Failed to find file for staring the Node.js application" - exit 1 - fi - echo "launching via init wrapper..." - exec ${STI_SCRIPTS_PATH}/init-wrapper node $start_file + package_json_start=$(cat package.json | grep "start" | sed -r 's/(.*)"start"([^:]*[^"]*")(.*)",/\3/') + package_json_main=$(cat package.json | grep "main" | sed -r 's/(.*)"main"([^:]*[^"]*")(.*)",/\3/') + + if [ -n "$package_json_start" ]; then + start_command=$package_json_start + elif [ -n $package_json_main ]; then + start_command="node ." + elif [ -f "server.js" ]; then + start_command="node server.js" + else + echo "Failed to find file for starting the Node.js application" + exit 1 + fi + + echo "launching via init wrapper..." + exec ${STI_SCRIPTS_PATH}/init-wrapper $start_command else echo "Launching via npm..." exec npm run -d $NPM_RUN diff --git a/18-minimal/s2i/bin/init-wrapper b/18-minimal/s2i/bin/init-wrapper new file mode 100644 index 00000000..24e0d078 --- /dev/null +++ b/18-minimal/s2i/bin/init-wrapper @@ -0,0 +1,18 @@ +#!/bin/bash + +# Overview of how this script works: http://veithen.io/2014/11/16/sigterm-propagation.html +# Set a trap to kill the main app process when this +# init script receives SIGTERM or SIGINT +trap 'kill -s TERM $PID' TERM INT +# Execute the main application in the background +"$@" & +PID=$! +# wait command always terminates when trap is caught, even if the process hasn't finished yet +wait $PID +# Remove the trap and wait till the app process finishes completely +trap - TERM INT +# We wait again, since the first wait terminates when trap is caught +wait $PID +# Exit with the exit code of the app process +STATUS=$? +exit $STATUS \ No newline at end of file diff --git a/18-minimal/s2i/bin/run b/18-minimal/s2i/bin/run index 0c4d5c9b..1b9a0596 100755 --- a/18-minimal/s2i/bin/run +++ b/18-minimal/s2i/bin/run @@ -25,19 +25,23 @@ run_node() { echo "exec $NODE_CMD" fi elif [ "$INIT_WRAPPER" == true ]; then - if [ -f "server.js" ]; then - start_file="server.js" - elif [ -f "index.js" ]; then - start_file="index.js" - elif [ -f "main.js" ]; then - start_file="main.js" - else - echo "Failed to find file for staring the Node.js application" - exit 1 - fi - echo "launching via init wrapper..." - exec ${STI_SCRIPTS_PATH}/init-wrapper node $start_file + package_json_start=$(cat package.json | grep "start" | sed -r 's/(.*)"start"([^:]*[^"]*")(.*)",/\3/') + package_json_main=$(cat package.json | grep "main" | sed -r 's/(.*)"main"([^:]*[^"]*")(.*)",/\3/') + + if [ -n "$package_json_start" ]; then + start_command=$package_json_start + elif [ -n $package_json_main ]; then + start_command="node ." + elif [ -f "server.js" ]; then + start_command="node server.js" + else + echo "Failed to find file for starting the Node.js application" + exit 1 + fi + + echo "launching via init wrapper..." + exec ${STI_SCRIPTS_PATH}/init-wrapper $start_command else echo "Launching via npm..." exec npm run -d $NPM_RUN diff --git a/18/s2i/bin/run b/18/s2i/bin/run index 9dbceb3f..15698997 100755 --- a/18/s2i/bin/run +++ b/18/s2i/bin/run @@ -29,19 +29,23 @@ run_node() { echo "exec $NODE_CMD" fi elif [ "$INIT_WRAPPER" == true ]; then - if [ -f "server.js" ]; then - start_file="server.js" - elif [ -f "index.js" ]; then - start_file="index.js" - elif [ -f "main.js" ]; then - start_file="main.js" - else - echo "Failed to find file for staring the Node.js application" - exit 1 - fi - echo "launching via init wrapper..." - exec ${STI_SCRIPTS_PATH}/init-wrapper node $start_file + package_json_start=$(cat package.json | grep "start" | sed -r 's/(.*)"start"([^:]*[^"]*")(.*)",/\3/') + package_json_main=$(cat package.json | grep "main" | sed -r 's/(.*)"main"([^:]*[^"]*")(.*)",/\3/') + + if [ -n "$package_json_start" ]; then + start_command=$package_json_start + elif [ -n $package_json_main ]; then + start_command="node ." + elif [ -f "server.js" ]; then + start_command="node server.js" + else + echo "Failed to find file for starting the Node.js application" + exit 1 + fi + + echo "launching via init wrapper..." + exec ${STI_SCRIPTS_PATH}/init-wrapper $start_command else echo "Launching via npm..." exec npm run -d $NPM_RUN From a5a7fe0a3b44d34ba78660b5c0ad8e78fdbfe81b Mon Sep 17 00:00:00 2001 From: Costas Papastathis Date: Tue, 3 Jan 2023 16:12:09 +0200 Subject: [PATCH 13/23] fix: adding init-wrapper scipt on node 18 --- 18-minimal/Dockerfile.c8s | 4 ++++ 18-minimal/Dockerfile.c9s | 4 ++++ 18-minimal/Dockerfile.rhel8 | 4 ++++ 18-minimal/Dockerfile.rhel9 | 4 ++++ 18/Dockerfile.c9s | 1 + 18/Dockerfile.rhel8 | 1 + 18/Dockerfile.rhel9 | 1 + 7 files changed, 19 insertions(+) diff --git a/18-minimal/Dockerfile.c8s b/18-minimal/Dockerfile.c8s index e21ebf06..c35dfe58 100644 --- a/18-minimal/Dockerfile.c8s +++ b/18-minimal/Dockerfile.c8s @@ -59,6 +59,10 @@ RUN INSTALL_PKGS="nodejs nodejs-nodemon nodejs-full-i18n npm findutils tar which COPY ./s2i/bin/ /usr/libexec/s2i +# Copy the S2I scripts from the specific language image to $STI_SCRIPTS_PATH +COPY ./s2i/bin/ $STI_SCRIPTS_PATH +RUN chmod +x $STI_SCRIPTS_PATH/init-wrapper + # Copy extra files to the image. COPY ./root/ / diff --git a/18-minimal/Dockerfile.c9s b/18-minimal/Dockerfile.c9s index 8a3b1e49..5eab7d2c 100644 --- a/18-minimal/Dockerfile.c9s +++ b/18-minimal/Dockerfile.c9s @@ -59,6 +59,10 @@ RUN INSTALL_PKGS="nodejs nodejs-nodemon nodejs-full-i18n npm findutils tar which COPY ./s2i/bin/ /usr/libexec/s2i +# Copy the S2I scripts from the specific language image to $STI_SCRIPTS_PATH +COPY ./s2i/bin/ $STI_SCRIPTS_PATH +RUN chmod +x $STI_SCRIPTS_PATH/init-wrapper + # Copy extra files to the image. COPY ./root/ / diff --git a/18-minimal/Dockerfile.rhel8 b/18-minimal/Dockerfile.rhel8 index eedac2ad..c0a5fe24 100644 --- a/18-minimal/Dockerfile.rhel8 +++ b/18-minimal/Dockerfile.rhel8 @@ -60,6 +60,10 @@ RUN INSTALL_PKGS="nodejs nodejs-nodemon nodejs-full-i18n npm findutils tar which COPY ./s2i/bin/ /usr/libexec/s2i +# Copy the S2I scripts from the specific language image to $STI_SCRIPTS_PATH +COPY ./s2i/bin/ $STI_SCRIPTS_PATH +RUN chmod +x $STI_SCRIPTS_PATH/init-wrapper + # Copy extra files to the image. COPY ./root/ / diff --git a/18-minimal/Dockerfile.rhel9 b/18-minimal/Dockerfile.rhel9 index f5095ea1..1168757c 100644 --- a/18-minimal/Dockerfile.rhel9 +++ b/18-minimal/Dockerfile.rhel9 @@ -60,6 +60,10 @@ RUN INSTALL_PKGS="nodejs nodejs-nodemon nodejs-full-i18n npm findutils tar which COPY ./s2i/bin/ /usr/libexec/s2i +# Copy the S2I scripts from the specific language image to $STI_SCRIPTS_PATH +COPY ./s2i/bin/ $STI_SCRIPTS_PATH +RUN chmod +x $STI_SCRIPTS_PATH/init-wrapper + # Copy extra files to the image. COPY ./root/ / diff --git a/18/Dockerfile.c9s b/18/Dockerfile.c9s index bd0347e4..6e656d4e 100644 --- a/18/Dockerfile.c9s +++ b/18/Dockerfile.c9s @@ -65,6 +65,7 @@ RUN yum -y module enable nodejs:$NODEJS_VERSION && \ # Copy the S2I scripts from the specific language image to $STI_SCRIPTS_PATH COPY ./s2i/bin/ $STI_SCRIPTS_PATH +RUN chmod +x $STI_SCRIPTS_PATH/init-wrapper # Copy extra files to the image. COPY ./root/ / diff --git a/18/Dockerfile.rhel8 b/18/Dockerfile.rhel8 index be1ee88a..ff9f41c3 100644 --- a/18/Dockerfile.rhel8 +++ b/18/Dockerfile.rhel8 @@ -65,6 +65,7 @@ RUN yum -y module enable nodejs:$NODEJS_VERSION && \ # Copy the S2I scripts from the specific language image to $STI_SCRIPTS_PATH COPY ./s2i/bin/ $STI_SCRIPTS_PATH +RUN chmod +x $STI_SCRIPTS_PATH/init-wrapper # Copy extra files to the image. COPY ./root/ / diff --git a/18/Dockerfile.rhel9 b/18/Dockerfile.rhel9 index d9730bd7..d243fdf3 100644 --- a/18/Dockerfile.rhel9 +++ b/18/Dockerfile.rhel9 @@ -64,6 +64,7 @@ RUN yum -y module enable nodejs:$NODEJS_VERSION && \ # Copy the S2I scripts from the specific language image to $STI_SCRIPTS_PATH COPY ./s2i/bin/ $STI_SCRIPTS_PATH +RUN chmod +x $STI_SCRIPTS_PATH/init-wrapper # Copy extra files to the image. COPY ./root/ / From 24c9bce08380534a3d56b219df2ea8a4de360187 Mon Sep 17 00:00:00 2001 From: Costas Papastathis Date: Wed, 4 Jan 2023 13:12:26 +0200 Subject: [PATCH 14/23] fix: removing blank spaces --- 14-minimal/s2i/bin/run | 2 -- 14/s2i/bin/run | 2 -- 16-minimal/s2i/bin/run | 2 -- 16/s2i/bin/run | 2 -- 18-minimal/s2i/bin/run | 2 -- 18/s2i/bin/run | 2 -- 6 files changed, 12 deletions(-) diff --git a/14-minimal/s2i/bin/run b/14-minimal/s2i/bin/run index 1b9a0596..397a1a39 100755 --- a/14-minimal/s2i/bin/run +++ b/14-minimal/s2i/bin/run @@ -25,7 +25,6 @@ run_node() { echo "exec $NODE_CMD" fi elif [ "$INIT_WRAPPER" == true ]; then - package_json_start=$(cat package.json | grep "start" | sed -r 's/(.*)"start"([^:]*[^"]*")(.*)",/\3/') package_json_main=$(cat package.json | grep "main" | sed -r 's/(.*)"main"([^:]*[^"]*")(.*)",/\3/') @@ -39,7 +38,6 @@ run_node() { echo "Failed to find file for starting the Node.js application" exit 1 fi - echo "launching via init wrapper..." exec ${STI_SCRIPTS_PATH}/init-wrapper $start_command else diff --git a/14/s2i/bin/run b/14/s2i/bin/run index 15698997..75f1a8ff 100755 --- a/14/s2i/bin/run +++ b/14/s2i/bin/run @@ -29,7 +29,6 @@ run_node() { echo "exec $NODE_CMD" fi elif [ "$INIT_WRAPPER" == true ]; then - package_json_start=$(cat package.json | grep "start" | sed -r 's/(.*)"start"([^:]*[^"]*")(.*)",/\3/') package_json_main=$(cat package.json | grep "main" | sed -r 's/(.*)"main"([^:]*[^"]*")(.*)",/\3/') @@ -43,7 +42,6 @@ run_node() { echo "Failed to find file for starting the Node.js application" exit 1 fi - echo "launching via init wrapper..." exec ${STI_SCRIPTS_PATH}/init-wrapper $start_command else diff --git a/16-minimal/s2i/bin/run b/16-minimal/s2i/bin/run index 1b9a0596..397a1a39 100755 --- a/16-minimal/s2i/bin/run +++ b/16-minimal/s2i/bin/run @@ -25,7 +25,6 @@ run_node() { echo "exec $NODE_CMD" fi elif [ "$INIT_WRAPPER" == true ]; then - package_json_start=$(cat package.json | grep "start" | sed -r 's/(.*)"start"([^:]*[^"]*")(.*)",/\3/') package_json_main=$(cat package.json | grep "main" | sed -r 's/(.*)"main"([^:]*[^"]*")(.*)",/\3/') @@ -39,7 +38,6 @@ run_node() { echo "Failed to find file for starting the Node.js application" exit 1 fi - echo "launching via init wrapper..." exec ${STI_SCRIPTS_PATH}/init-wrapper $start_command else diff --git a/16/s2i/bin/run b/16/s2i/bin/run index 15698997..75f1a8ff 100755 --- a/16/s2i/bin/run +++ b/16/s2i/bin/run @@ -29,7 +29,6 @@ run_node() { echo "exec $NODE_CMD" fi elif [ "$INIT_WRAPPER" == true ]; then - package_json_start=$(cat package.json | grep "start" | sed -r 's/(.*)"start"([^:]*[^"]*")(.*)",/\3/') package_json_main=$(cat package.json | grep "main" | sed -r 's/(.*)"main"([^:]*[^"]*")(.*)",/\3/') @@ -43,7 +42,6 @@ run_node() { echo "Failed to find file for starting the Node.js application" exit 1 fi - echo "launching via init wrapper..." exec ${STI_SCRIPTS_PATH}/init-wrapper $start_command else diff --git a/18-minimal/s2i/bin/run b/18-minimal/s2i/bin/run index 1b9a0596..397a1a39 100755 --- a/18-minimal/s2i/bin/run +++ b/18-minimal/s2i/bin/run @@ -25,7 +25,6 @@ run_node() { echo "exec $NODE_CMD" fi elif [ "$INIT_WRAPPER" == true ]; then - package_json_start=$(cat package.json | grep "start" | sed -r 's/(.*)"start"([^:]*[^"]*")(.*)",/\3/') package_json_main=$(cat package.json | grep "main" | sed -r 's/(.*)"main"([^:]*[^"]*")(.*)",/\3/') @@ -39,7 +38,6 @@ run_node() { echo "Failed to find file for starting the Node.js application" exit 1 fi - echo "launching via init wrapper..." exec ${STI_SCRIPTS_PATH}/init-wrapper $start_command else diff --git a/18/s2i/bin/run b/18/s2i/bin/run index 15698997..75f1a8ff 100755 --- a/18/s2i/bin/run +++ b/18/s2i/bin/run @@ -29,7 +29,6 @@ run_node() { echo "exec $NODE_CMD" fi elif [ "$INIT_WRAPPER" == true ]; then - package_json_start=$(cat package.json | grep "start" | sed -r 's/(.*)"start"([^:]*[^"]*")(.*)",/\3/') package_json_main=$(cat package.json | grep "main" | sed -r 's/(.*)"main"([^:]*[^"]*")(.*)",/\3/') @@ -43,7 +42,6 @@ run_node() { echo "Failed to find file for starting the Node.js application" exit 1 fi - echo "launching via init wrapper..." exec ${STI_SCRIPTS_PATH}/init-wrapper $start_command else From e71126fb125211c0b705778f5720eff9ed972b92 Mon Sep 17 00:00:00 2001 From: Costas Papastathis Date: Mon, 24 Jul 2023 17:19:45 +0300 Subject: [PATCH 15/23] fix: updating run script for readablility and catching edge cases on regex --- 14-minimal/s2i/bin/run | 43 +++++++++++++++++++++--------------------- 14/s2i/bin/run | 43 +++++++++++++++++++++--------------------- 16-minimal/s2i/bin/run | 43 +++++++++++++++++++++--------------------- 16/s2i/bin/run | 43 +++++++++++++++++++++--------------------- 18-minimal/s2i/bin/run | 43 +++++++++++++++++++++--------------------- 18/s2i/bin/run | 43 +++++++++++++++++++++--------------------- 6 files changed, 126 insertions(+), 132 deletions(-) diff --git a/14-minimal/s2i/bin/run b/14-minimal/s2i/bin/run index 397a1a39..45d23d69 100755 --- a/14-minimal/s2i/bin/run +++ b/14-minimal/s2i/bin/run @@ -16,30 +16,29 @@ run_node() { if [ "$DEV_MODE" == true ]; then echo "Launching via nodemon..." exec nodemon --inspect="$DEBUG_PORT" - elif [ -v NODE_CMD ]; then - if [ "$INIT_WRAPPER" == true ]; then - echo "launching via init wrapper..." - exec ${STI_SCRIPTS_PATH}/init-wrapper $NODE_CMD + elif [ -n "$NODE_CMD" ] && [ "$INIT_WRAPPER" == true ]; then + echo "launching via init wrapper..." + exec ${STI_SCRIPTS_PATH}/init-wrapper $NODE_CMD + elif [ -n "$NODE_CMD" ] && [ "$INIT_WRAPPER" == false ]; then + echo "Launching via ${NODE_CMD}" + exec $NODE_CMD + elif [ ! -n "$NODE_CMD" ] && [ "$INIT_WRAPPER" == true ]; then + + package_json_start=$(sed -n 's/\s*"start"\s*:\s*"\(.*\)".*/\1/p' package.json) + package_json_main=$(sed -n 's/\s*"main"\s*:\s*"\(.*\)".*/\1/p' package.json) + + if [ -n "$package_json_start" ]; then + start_command=$package_json_start + elif [ -n $package_json_main ]; then + start_command="node ." + elif [ -f "server.js" ]; then + start_command="node server.js" else - echo "Launching via ${NODE_CMD}" - echo "exec $NODE_CMD" + echo "Failed to find file for starting the Node.js application" + exit 1 fi - elif [ "$INIT_WRAPPER" == true ]; then - package_json_start=$(cat package.json | grep "start" | sed -r 's/(.*)"start"([^:]*[^"]*")(.*)",/\3/') - package_json_main=$(cat package.json | grep "main" | sed -r 's/(.*)"main"([^:]*[^"]*")(.*)",/\3/') - - if [ -n "$package_json_start" ]; then - start_command=$package_json_start - elif [ -n $package_json_main ]; then - start_command="node ." - elif [ -f "server.js" ]; then - start_command="node server.js" - else - echo "Failed to find file for starting the Node.js application" - exit 1 - fi - echo "launching via init wrapper..." - exec ${STI_SCRIPTS_PATH}/init-wrapper $start_command + echo "launching via init wrapper..." + exec ${STI_SCRIPTS_PATH}/init-wrapper $start_command else echo "Launching via npm..." exec npm run -d $NPM_RUN diff --git a/14/s2i/bin/run b/14/s2i/bin/run index 75f1a8ff..9fc5cf90 100755 --- a/14/s2i/bin/run +++ b/14/s2i/bin/run @@ -20,30 +20,29 @@ run_node() { if [ "$DEV_MODE" == true ]; then echo "Launching via nodemon..." exec nodemon --inspect="$DEBUG_PORT" - elif [ -v NODE_CMD ]; then - if [ "$INIT_WRAPPER" == true ]; then - echo "launching via init wrapper..." - exec ${STI_SCRIPTS_PATH}/init-wrapper $NODE_CMD + elif [ -n "$NODE_CMD" ] && [ "$INIT_WRAPPER" == true ]; then + echo "launching via init wrapper..." + exec ${STI_SCRIPTS_PATH}/init-wrapper $NODE_CMD + elif [ -n "$NODE_CMD" ] && [ "$INIT_WRAPPER" == false ]; then + echo "Launching via ${NODE_CMD}" + exec $NODE_CMD + elif [ ! -n "$NODE_CMD" ] && [ "$INIT_WRAPPER" == true ]; then + + package_json_start=$(sed -n 's/\s*"start"\s*:\s*"\(.*\)".*/\1/p' package.json) + package_json_main=$(sed -n 's/\s*"main"\s*:\s*"\(.*\)".*/\1/p' package.json) + + if [ -n "$package_json_start" ]; then + start_command=$package_json_start + elif [ -n $package_json_main ]; then + start_command="node ." + elif [ -f "server.js" ]; then + start_command="node server.js" else - echo "Launching via ${NODE_CMD}" - echo "exec $NODE_CMD" + echo "Failed to find file for starting the Node.js application" + exit 1 fi - elif [ "$INIT_WRAPPER" == true ]; then - package_json_start=$(cat package.json | grep "start" | sed -r 's/(.*)"start"([^:]*[^"]*")(.*)",/\3/') - package_json_main=$(cat package.json | grep "main" | sed -r 's/(.*)"main"([^:]*[^"]*")(.*)",/\3/') - - if [ -n "$package_json_start" ]; then - start_command=$package_json_start - elif [ -n $package_json_main ]; then - start_command="node ." - elif [ -f "server.js" ]; then - start_command="node server.js" - else - echo "Failed to find file for starting the Node.js application" - exit 1 - fi - echo "launching via init wrapper..." - exec ${STI_SCRIPTS_PATH}/init-wrapper $start_command + echo "launching via init wrapper..." + exec ${STI_SCRIPTS_PATH}/init-wrapper $start_command else echo "Launching via npm..." exec npm run -d $NPM_RUN diff --git a/16-minimal/s2i/bin/run b/16-minimal/s2i/bin/run index 397a1a39..45d23d69 100755 --- a/16-minimal/s2i/bin/run +++ b/16-minimal/s2i/bin/run @@ -16,30 +16,29 @@ run_node() { if [ "$DEV_MODE" == true ]; then echo "Launching via nodemon..." exec nodemon --inspect="$DEBUG_PORT" - elif [ -v NODE_CMD ]; then - if [ "$INIT_WRAPPER" == true ]; then - echo "launching via init wrapper..." - exec ${STI_SCRIPTS_PATH}/init-wrapper $NODE_CMD + elif [ -n "$NODE_CMD" ] && [ "$INIT_WRAPPER" == true ]; then + echo "launching via init wrapper..." + exec ${STI_SCRIPTS_PATH}/init-wrapper $NODE_CMD + elif [ -n "$NODE_CMD" ] && [ "$INIT_WRAPPER" == false ]; then + echo "Launching via ${NODE_CMD}" + exec $NODE_CMD + elif [ ! -n "$NODE_CMD" ] && [ "$INIT_WRAPPER" == true ]; then + + package_json_start=$(sed -n 's/\s*"start"\s*:\s*"\(.*\)".*/\1/p' package.json) + package_json_main=$(sed -n 's/\s*"main"\s*:\s*"\(.*\)".*/\1/p' package.json) + + if [ -n "$package_json_start" ]; then + start_command=$package_json_start + elif [ -n $package_json_main ]; then + start_command="node ." + elif [ -f "server.js" ]; then + start_command="node server.js" else - echo "Launching via ${NODE_CMD}" - echo "exec $NODE_CMD" + echo "Failed to find file for starting the Node.js application" + exit 1 fi - elif [ "$INIT_WRAPPER" == true ]; then - package_json_start=$(cat package.json | grep "start" | sed -r 's/(.*)"start"([^:]*[^"]*")(.*)",/\3/') - package_json_main=$(cat package.json | grep "main" | sed -r 's/(.*)"main"([^:]*[^"]*")(.*)",/\3/') - - if [ -n "$package_json_start" ]; then - start_command=$package_json_start - elif [ -n $package_json_main ]; then - start_command="node ." - elif [ -f "server.js" ]; then - start_command="node server.js" - else - echo "Failed to find file for starting the Node.js application" - exit 1 - fi - echo "launching via init wrapper..." - exec ${STI_SCRIPTS_PATH}/init-wrapper $start_command + echo "launching via init wrapper..." + exec ${STI_SCRIPTS_PATH}/init-wrapper $start_command else echo "Launching via npm..." exec npm run -d $NPM_RUN diff --git a/16/s2i/bin/run b/16/s2i/bin/run index 75f1a8ff..9fc5cf90 100755 --- a/16/s2i/bin/run +++ b/16/s2i/bin/run @@ -20,30 +20,29 @@ run_node() { if [ "$DEV_MODE" == true ]; then echo "Launching via nodemon..." exec nodemon --inspect="$DEBUG_PORT" - elif [ -v NODE_CMD ]; then - if [ "$INIT_WRAPPER" == true ]; then - echo "launching via init wrapper..." - exec ${STI_SCRIPTS_PATH}/init-wrapper $NODE_CMD + elif [ -n "$NODE_CMD" ] && [ "$INIT_WRAPPER" == true ]; then + echo "launching via init wrapper..." + exec ${STI_SCRIPTS_PATH}/init-wrapper $NODE_CMD + elif [ -n "$NODE_CMD" ] && [ "$INIT_WRAPPER" == false ]; then + echo "Launching via ${NODE_CMD}" + exec $NODE_CMD + elif [ ! -n "$NODE_CMD" ] && [ "$INIT_WRAPPER" == true ]; then + + package_json_start=$(sed -n 's/\s*"start"\s*:\s*"\(.*\)".*/\1/p' package.json) + package_json_main=$(sed -n 's/\s*"main"\s*:\s*"\(.*\)".*/\1/p' package.json) + + if [ -n "$package_json_start" ]; then + start_command=$package_json_start + elif [ -n $package_json_main ]; then + start_command="node ." + elif [ -f "server.js" ]; then + start_command="node server.js" else - echo "Launching via ${NODE_CMD}" - echo "exec $NODE_CMD" + echo "Failed to find file for starting the Node.js application" + exit 1 fi - elif [ "$INIT_WRAPPER" == true ]; then - package_json_start=$(cat package.json | grep "start" | sed -r 's/(.*)"start"([^:]*[^"]*")(.*)",/\3/') - package_json_main=$(cat package.json | grep "main" | sed -r 's/(.*)"main"([^:]*[^"]*")(.*)",/\3/') - - if [ -n "$package_json_start" ]; then - start_command=$package_json_start - elif [ -n $package_json_main ]; then - start_command="node ." - elif [ -f "server.js" ]; then - start_command="node server.js" - else - echo "Failed to find file for starting the Node.js application" - exit 1 - fi - echo "launching via init wrapper..." - exec ${STI_SCRIPTS_PATH}/init-wrapper $start_command + echo "launching via init wrapper..." + exec ${STI_SCRIPTS_PATH}/init-wrapper $start_command else echo "Launching via npm..." exec npm run -d $NPM_RUN diff --git a/18-minimal/s2i/bin/run b/18-minimal/s2i/bin/run index 397a1a39..45d23d69 100755 --- a/18-minimal/s2i/bin/run +++ b/18-minimal/s2i/bin/run @@ -16,30 +16,29 @@ run_node() { if [ "$DEV_MODE" == true ]; then echo "Launching via nodemon..." exec nodemon --inspect="$DEBUG_PORT" - elif [ -v NODE_CMD ]; then - if [ "$INIT_WRAPPER" == true ]; then - echo "launching via init wrapper..." - exec ${STI_SCRIPTS_PATH}/init-wrapper $NODE_CMD + elif [ -n "$NODE_CMD" ] && [ "$INIT_WRAPPER" == true ]; then + echo "launching via init wrapper..." + exec ${STI_SCRIPTS_PATH}/init-wrapper $NODE_CMD + elif [ -n "$NODE_CMD" ] && [ "$INIT_WRAPPER" == false ]; then + echo "Launching via ${NODE_CMD}" + exec $NODE_CMD + elif [ ! -n "$NODE_CMD" ] && [ "$INIT_WRAPPER" == true ]; then + + package_json_start=$(sed -n 's/\s*"start"\s*:\s*"\(.*\)".*/\1/p' package.json) + package_json_main=$(sed -n 's/\s*"main"\s*:\s*"\(.*\)".*/\1/p' package.json) + + if [ -n "$package_json_start" ]; then + start_command=$package_json_start + elif [ -n $package_json_main ]; then + start_command="node ." + elif [ -f "server.js" ]; then + start_command="node server.js" else - echo "Launching via ${NODE_CMD}" - echo "exec $NODE_CMD" + echo "Failed to find file for starting the Node.js application" + exit 1 fi - elif [ "$INIT_WRAPPER" == true ]; then - package_json_start=$(cat package.json | grep "start" | sed -r 's/(.*)"start"([^:]*[^"]*")(.*)",/\3/') - package_json_main=$(cat package.json | grep "main" | sed -r 's/(.*)"main"([^:]*[^"]*")(.*)",/\3/') - - if [ -n "$package_json_start" ]; then - start_command=$package_json_start - elif [ -n $package_json_main ]; then - start_command="node ." - elif [ -f "server.js" ]; then - start_command="node server.js" - else - echo "Failed to find file for starting the Node.js application" - exit 1 - fi - echo "launching via init wrapper..." - exec ${STI_SCRIPTS_PATH}/init-wrapper $start_command + echo "launching via init wrapper..." + exec ${STI_SCRIPTS_PATH}/init-wrapper $start_command else echo "Launching via npm..." exec npm run -d $NPM_RUN diff --git a/18/s2i/bin/run b/18/s2i/bin/run index 75f1a8ff..9fc5cf90 100755 --- a/18/s2i/bin/run +++ b/18/s2i/bin/run @@ -20,30 +20,29 @@ run_node() { if [ "$DEV_MODE" == true ]; then echo "Launching via nodemon..." exec nodemon --inspect="$DEBUG_PORT" - elif [ -v NODE_CMD ]; then - if [ "$INIT_WRAPPER" == true ]; then - echo "launching via init wrapper..." - exec ${STI_SCRIPTS_PATH}/init-wrapper $NODE_CMD + elif [ -n "$NODE_CMD" ] && [ "$INIT_WRAPPER" == true ]; then + echo "launching via init wrapper..." + exec ${STI_SCRIPTS_PATH}/init-wrapper $NODE_CMD + elif [ -n "$NODE_CMD" ] && [ "$INIT_WRAPPER" == false ]; then + echo "Launching via ${NODE_CMD}" + exec $NODE_CMD + elif [ ! -n "$NODE_CMD" ] && [ "$INIT_WRAPPER" == true ]; then + + package_json_start=$(sed -n 's/\s*"start"\s*:\s*"\(.*\)".*/\1/p' package.json) + package_json_main=$(sed -n 's/\s*"main"\s*:\s*"\(.*\)".*/\1/p' package.json) + + if [ -n "$package_json_start" ]; then + start_command=$package_json_start + elif [ -n $package_json_main ]; then + start_command="node ." + elif [ -f "server.js" ]; then + start_command="node server.js" else - echo "Launching via ${NODE_CMD}" - echo "exec $NODE_CMD" + echo "Failed to find file for starting the Node.js application" + exit 1 fi - elif [ "$INIT_WRAPPER" == true ]; then - package_json_start=$(cat package.json | grep "start" | sed -r 's/(.*)"start"([^:]*[^"]*")(.*)",/\3/') - package_json_main=$(cat package.json | grep "main" | sed -r 's/(.*)"main"([^:]*[^"]*")(.*)",/\3/') - - if [ -n "$package_json_start" ]; then - start_command=$package_json_start - elif [ -n $package_json_main ]; then - start_command="node ." - elif [ -f "server.js" ]; then - start_command="node server.js" - else - echo "Failed to find file for starting the Node.js application" - exit 1 - fi - echo "launching via init wrapper..." - exec ${STI_SCRIPTS_PATH}/init-wrapper $start_command + echo "launching via init wrapper..." + exec ${STI_SCRIPTS_PATH}/init-wrapper $start_command else echo "Launching via npm..." exec npm run -d $NPM_RUN From 51ae0a2bfddb5bdda964dd2f1313d68a5521c15e Mon Sep 17 00:00:00 2001 From: Costas Papastathis Date: Mon, 24 Jul 2023 17:23:41 +0300 Subject: [PATCH 16/23] test: adding tests for NODE_CMD and INIT_WRAPPER options --- test/run | 11 ++++++++++ test/test-lib-nodejs.sh | 45 +++++++++++++++++++++++++++++++++++++++-- 2 files changed, 54 insertions(+), 2 deletions(-) diff --git a/test/run b/test/run index 9f6954c9..54822982 100755 --- a/test/run +++ b/test/run @@ -22,10 +22,16 @@ test_npm_tmp_cleared kill_test_application test_dev_mode_true_development test_dev_mode_false_production +test_node_cmd_development_init_wrapper_true +test_node_cmd_production_init_wrapper_true +test_node_cmd_development_init_wrapper_false +test_init_wrapper_true_development +test_init_wrapper_false_development " TEST_LIST_BINARY="\ test_run_binary_application +test_node_cmd_development_init_wrapper_true " TEST_LIST_NODE_ENV="\ @@ -36,6 +42,9 @@ test_npm_cache_exists kill_test_application test_dev_mode_true_development test_dev_mode_false_development +test_node_cmd_development_init_wrapper_true +test_node_cmd_production_init_wrapper_true +test_node_cmd_production_init_wrapper_false " TEST_LIST_DEV_MODE="\ @@ -53,6 +62,8 @@ test_safe_logging test_run_hw_application test_incremental_build test_build_express_webapp +test_node_cmd_development_init_wrapper_true +test_init_wrapper_false_development " source "${THISDIR}/test-lib.sh" diff --git a/test/test-lib-nodejs.sh b/test/test-lib-nodejs.sh index 1922b08c..53013e7f 100644 --- a/test/test-lib-nodejs.sh +++ b/test/test-lib-nodejs.sh @@ -164,6 +164,19 @@ run_test_application() { esac } +run_test_application_with_quoted_args() { + case "$1" in + app | hw | express-webapp | binary) + cid_file=$CID_FILE_DIR/$(mktemp -u -p . --suffix=.cid) + docker run -d --user=100001 $(ct_mount_ca_file) --rm --cidfile=${cid_file} "$2" ${IMAGE_NAME}-test$1 + ;; + *) + echo "No such test application" + return 1 + ;; + esac +} + run_client_test_suite() { cid_file=$CID_FILE_DIR/$(mktemp -u -p . --suffix=.cid) local cmd="npm test" @@ -447,7 +460,6 @@ function test_nodemon_present() { ct_check_testcase_result "$?" } - function test_npm_cache_cleared() { # Test that the npm cache has been cleared cache_loc=$(docker run --rm ${IMAGE_NAME}-testapp /bin/bash -c "npm config get cache") @@ -477,6 +489,36 @@ function test_dev_mode_true_development() { test_dev_mode app true development } +function test_node_cmd_production_init_wrapper_false() { + # NODE_ENV=production INIT_WRAPPER=false NODE_CMD="node server.js" + test_node_cmd app production false "node server.js" +} + +function test_node_cmd_development_init_wrapper_true() { + # NODE_ENV=development INIT_WRAPPER=true NODE_CMD="node server.js" + test_node_cmd app development true "node server.js" +} + +function test_node_cmd_production_init_wrapper_true() { + # NODE_ENV=production INIT_WRAPPER=true NODE_CMD="node server.js" + test_node_cmd app production true "node server.js" +} + +function test_node_cmd_development_init_wrapper_false() { + # NODE_ENV=development INIT_WRAPPER=false NODE_CMD="node server.js" + test_node_cmd app development false "node server.js" +} + +function test_init_wrapper_true_development() { + # NODE_ENV=development INIT_WRAPPER=true + test_node_cmd app development true +} + +function test_init_wrapper_false_development() { + # NODE_ENV=development INIT_WRAPPER=true + test_node_cmd app development false +} + function test_dev_mode_false_development() { # DEV_MODE=false NODE_ENV=development test_dev_mode app false development @@ -610,4 +652,3 @@ function test_latest_imagestreams() { } # vim: set tabstop=2:shiftwidth=2:expandtab: - From 7da41602bccdf8124962a20056c3c00c5df71bc9 Mon Sep 17 00:00:00 2001 From: Costas Papastathis Date: Tue, 12 Sep 2023 11:22:37 +0300 Subject: [PATCH 17/23] fix: adding init-wrapper for node version 20 --- 18-minimal/Dockerfile.fedora | 1 + 20-minimal/Dockerfile.c8s | 1 + 20-minimal/Dockerfile.c9s | 1 + 20-minimal/Dockerfile.fedora | 1 + 20-minimal/Dockerfile.rhel8 | 1 + 20-minimal/Dockerfile.rhel9 | 1 + 20-minimal/README.md | 47 +++++++++++++++++++++++++++++++++ 20-minimal/s2i/bin/init-wrapper | 18 +++++++++++++ 20-minimal/s2i/bin/run | 23 ++++++++++++++++ 20/Dockerfile.c8s | 1 + 20/Dockerfile.c9s | 1 + 20/Dockerfile.fedora | 1 + 20/Dockerfile.rhel8 | 1 + 20/Dockerfile.rhel9 | 1 + 20/README.md | 47 +++++++++++++++++++++++++++++++++ 20/s2i/bin/init-wrapper | 18 +++++++++++++ 20/s2i/bin/run | 23 ++++++++++++++++ 17 files changed, 187 insertions(+) create mode 100644 20-minimal/s2i/bin/init-wrapper create mode 100644 20/s2i/bin/init-wrapper diff --git a/18-minimal/Dockerfile.fedora b/18-minimal/Dockerfile.fedora index 6110b98e..e2025ff2 100644 --- a/18-minimal/Dockerfile.fedora +++ b/18-minimal/Dockerfile.fedora @@ -56,6 +56,7 @@ RUN INSTALL_PKGS="nodejs nodejs-nodemon nodejs-full-i18n nodejs-npm findutils ta rm -rf /mnt/rootfs/var/cache/* /mnt/rootfs/var/log/dnf* /mnt/rootfs/var/log/yum.* COPY ./s2i/bin/ /usr/libexec/s2i +RUN chmod +x $STI_SCRIPTS_PATH/init-wrapper # Copy extra files to the image. COPY ./root/ / diff --git a/20-minimal/Dockerfile.c8s b/20-minimal/Dockerfile.c8s index ac809767..d7829589 100644 --- a/20-minimal/Dockerfile.c8s +++ b/20-minimal/Dockerfile.c8s @@ -58,6 +58,7 @@ RUN INSTALL_PKGS="nodejs nodejs-nodemon nodejs-full-i18n npm findutils tar which rm -rf /mnt/rootfs/var/cache/* /mnt/rootfs/var/log/dnf* /mnt/rootfs/var/log/yum.* COPY ./s2i/bin/ /usr/libexec/s2i +RUN chmod +x /usr/libexec/s2i/init-wrapper # Copy extra files to the image. COPY ./root/ / diff --git a/20-minimal/Dockerfile.c9s b/20-minimal/Dockerfile.c9s index 2195813f..8d3ce96c 100644 --- a/20-minimal/Dockerfile.c9s +++ b/20-minimal/Dockerfile.c9s @@ -58,6 +58,7 @@ RUN INSTALL_PKGS="nodejs nodejs-nodemon nodejs-full-i18n npm findutils tar which rm -rf /mnt/rootfs/var/cache/* /mnt/rootfs/var/log/dnf* /mnt/rootfs/var/log/yum.* COPY ./s2i/bin/ /usr/libexec/s2i +RUN chmod +x /usr/libexec/s2i/init-wrapper # Copy extra files to the image. COPY ./root/ / diff --git a/20-minimal/Dockerfile.fedora b/20-minimal/Dockerfile.fedora index b7382df7..f6bcb7be 100644 --- a/20-minimal/Dockerfile.fedora +++ b/20-minimal/Dockerfile.fedora @@ -61,6 +61,7 @@ RUN INSTALL_PKGS="nodejs$NODEJS_VERSION nodejs-nodemon nodejs$NODEJS_VERSION-ful # COPY ./s2i/bin/ /usr/libexec/s2i +RUN chmod +x /usr/libexec/s2i/init-wrapper # Copy extra files to the image. COPY ./root/ / diff --git a/20-minimal/Dockerfile.rhel8 b/20-minimal/Dockerfile.rhel8 index b07d147c..7722c748 100644 --- a/20-minimal/Dockerfile.rhel8 +++ b/20-minimal/Dockerfile.rhel8 @@ -59,6 +59,7 @@ RUN INSTALL_PKGS="nodejs nodejs-nodemon nodejs-full-i18n npm findutils tar which rm -rf /mnt/rootfs/var/cache/* /mnt/rootfs/var/log/dnf* /mnt/rootfs/var/log/yum.* COPY ./s2i/bin/ /usr/libexec/s2i +RUN chmod +x /usr/libexec/s2i/init-wrapper # Copy extra files to the image. COPY ./root/ / diff --git a/20-minimal/Dockerfile.rhel9 b/20-minimal/Dockerfile.rhel9 index e09f110c..8d0a45c5 100644 --- a/20-minimal/Dockerfile.rhel9 +++ b/20-minimal/Dockerfile.rhel9 @@ -59,6 +59,7 @@ RUN INSTALL_PKGS="nodejs nodejs-nodemon nodejs-full-i18n npm findutils tar which rm -rf /mnt/rootfs/var/cache/* /mnt/rootfs/var/log/dnf* /mnt/rootfs/var/log/yum.* COPY ./s2i/bin/ /usr/libexec/s2i +RUN chmod +x /usr/libexec/s2i/init-wrapper # Copy extra files to the image. COPY ./root/ / diff --git a/20-minimal/README.md b/20-minimal/README.md index daa20cbc..d599f8a3 100644 --- a/20-minimal/README.md +++ b/20-minimal/README.md @@ -215,6 +215,12 @@ Application developers can use the following environment variables to configure **`NPM_RUN`** Select an alternate / custom runtime mode, defined in your `package.json` file's [`scripts`](https://docs.npmjs.com/misc/scripts) section (default: npm run "start"). These user-defined run-scripts are unavailable while `DEV_MODE` is in use. +**`NODE_CMD`** + When specified (e.g.Specify `NODE_CMD="node server.js"`) the value of `NODE_CMD` is used to start the application instead of `npm start`. + +**`INIT_WRAPPER`** + When set to "true", the application is started via the `init-wrapper` script instead of using `npm start`, by looking for the presence of the files `server.js`, `index.js` or `main.js` in the order in which they are listed. In case of `NODE_CMD` environemnt variale is specified, then `init-wrapper` script will use the value of `NODE_CMD` to start your application. + #### Additional variables used in the full-sized image **`HTTP_PROXY`** @@ -316,6 +322,47 @@ Below is an example _package.json_ file with the _main_ attribute and _start_ sc #### Note: `oc rsync` is only available in versions 3.1+ of OpenShift. +## init-wrapper + +init-wrapper script is located on `/usr/libexec/s2i/init-wrapper` and is used to handle: + +- Proper signal handling and propagation, as Node.js was not designed to run as PID 1. +- Reaping zombie child processes +Avoiding use of npm, there is more information on why you want to avoid that in the [Node.js reference architecture](https://github.com/nodeshift/nodejs-reference-architecture/blob/e4c4dc1fd20c2cac392e862859aaad27f85d504f/docs/development/building-good-containers.md#avoiding-using-npm-to-start-application). When the INIT_WRAPPER is set to true the application is started via the init script instead of using npm start. + +A detailed explanation on how the init-wrapper script works is avalable in +[this url](http://veithen.io/2014/11/16/sigterm-propagation.html). + +Example of using init-wrapper: + +**During image build** +``` +s2i -e INIT_WRAPPER=true build . buildImage node-app +docker run node-app +``` +**During container start** +``` +s2i build . buildImage node-app +docker run -e INIT_WRAPPER=true node-app +``` + +`init-wrapper` script can be disabled by setting the `INIT_WRAPPER` env variable to `false`. + +``` +docker run -e INIT_WRAPPER=false node-app +``` +`NODE_CMD` can be used during the build process or container start, in order to have more control on the command that `init-wrapper` script will wrap. + +For example: + +**during container build** +``` +s2i -e INIT_WRAPPER=true -e NODE_CMD="node index.js" build . buildImage node-app +``` +**during container start** +``` +docker run -e INIT_WRAPPER=false -e NODE_CMD="node index.js" node-app +``` See also -------- diff --git a/20-minimal/s2i/bin/init-wrapper b/20-minimal/s2i/bin/init-wrapper new file mode 100644 index 00000000..24e0d078 --- /dev/null +++ b/20-minimal/s2i/bin/init-wrapper @@ -0,0 +1,18 @@ +#!/bin/bash + +# Overview of how this script works: http://veithen.io/2014/11/16/sigterm-propagation.html +# Set a trap to kill the main app process when this +# init script receives SIGTERM or SIGINT +trap 'kill -s TERM $PID' TERM INT +# Execute the main application in the background +"$@" & +PID=$! +# wait command always terminates when trap is caught, even if the process hasn't finished yet +wait $PID +# Remove the trap and wait till the app process finishes completely +trap - TERM INT +# We wait again, since the first wait terminates when trap is caught +wait $PID +# Exit with the exit code of the app process +STATUS=$? +exit $STATUS \ No newline at end of file diff --git a/20-minimal/s2i/bin/run b/20-minimal/s2i/bin/run index 7894f47f..10150f34 100755 --- a/20-minimal/s2i/bin/run +++ b/20-minimal/s2i/bin/run @@ -16,6 +16,29 @@ run_node() { if [ "$DEV_MODE" == true ]; then echo "Launching via nodemon..." exec nodemon --inspect="$DEBUG_PORT" + elif [ -n "$NODE_CMD" ] && [ "$INIT_WRAPPER" == true ]; then + echo "launching via init wrapper..." + exec ${STI_SCRIPTS_PATH}/init-wrapper $NODE_CMD + elif [ -n "$NODE_CMD" ] && [ "$INIT_WRAPPER" == false ]; then + echo "Launching via ${NODE_CMD}" + exec $NODE_CMD + elif [ ! -n "$NODE_CMD" ] && [ "$INIT_WRAPPER" == true ]; then + + package_json_start=$(sed -n 's/\s*"start"\s*:\s*"\(.*\)".*/\1/p' package.json) + package_json_main=$(sed -n 's/\s*"main"\s*:\s*"\(.*\)".*/\1/p' package.json) + + if [ -n "$package_json_start" ]; then + start_command=$package_json_start + elif [ -n $package_json_main ]; then + start_command="node ." + elif [ -f "server.js" ]; then + start_command="node server.js" + else + echo "Failed to find file for starting the Node.js application" + exit 1 + fi + echo "launching via init wrapper..." + exec ${STI_SCRIPTS_PATH}/init-wrapper $start_command else echo "Launching via npm..." exec npm run -d $NPM_RUN diff --git a/20/Dockerfile.c8s b/20/Dockerfile.c8s index 7e9fdc2b..abc9d7b9 100644 --- a/20/Dockerfile.c8s +++ b/20/Dockerfile.c8s @@ -65,6 +65,7 @@ RUN yum -y module enable nodejs:$NODEJS_VERSION && \ # Copy the S2I scripts from the specific language image to $STI_SCRIPTS_PATH COPY ./s2i/bin/ $STI_SCRIPTS_PATH +RUN chmod +x $STI_SCRIPTS_PATH/init-wrapper # Copy extra files to the image. COPY ./root/ / diff --git a/20/Dockerfile.c9s b/20/Dockerfile.c9s index 224acb30..d0cba57a 100644 --- a/20/Dockerfile.c9s +++ b/20/Dockerfile.c9s @@ -65,6 +65,7 @@ RUN yum -y module enable nodejs:$NODEJS_VERSION && \ # Copy the S2I scripts from the specific language image to $STI_SCRIPTS_PATH COPY ./s2i/bin/ $STI_SCRIPTS_PATH +RUN chmod +x $STI_SCRIPTS_PATH/init-wrapper # Copy extra files to the image. COPY ./root/ / diff --git a/20/Dockerfile.fedora b/20/Dockerfile.fedora index b162fb10..63c07378 100644 --- a/20/Dockerfile.fedora +++ b/20/Dockerfile.fedora @@ -61,6 +61,7 @@ RUN MODULE_DEPS="make gcc gcc-c++ libatomic_ops git openssl-devel" && \ # Copy the S2I scripts from the specific language image to $STI_SCRIPTS_PATH COPY ./s2i/bin/ $STI_SCRIPTS_PATH +RUN chmod +x $STI_SCRIPTS_PATH/init-wrapper # Copy extra files to the image, including help file. COPY ./root/ / diff --git a/20/Dockerfile.rhel8 b/20/Dockerfile.rhel8 index f13bf884..cfea99fe 100644 --- a/20/Dockerfile.rhel8 +++ b/20/Dockerfile.rhel8 @@ -65,6 +65,7 @@ RUN yum -y module enable nodejs:$NODEJS_VERSION && \ # Copy the S2I scripts from the specific language image to $STI_SCRIPTS_PATH COPY ./s2i/bin/ $STI_SCRIPTS_PATH +RUN chmod +x $STI_SCRIPTS_PATH/init-wrapper # Copy extra files to the image. COPY ./root/ / diff --git a/20/Dockerfile.rhel9 b/20/Dockerfile.rhel9 index 6bf05d11..1aff401a 100644 --- a/20/Dockerfile.rhel9 +++ b/20/Dockerfile.rhel9 @@ -64,6 +64,7 @@ RUN yum -y module enable nodejs:$NODEJS_VERSION && \ # Copy the S2I scripts from the specific language image to $STI_SCRIPTS_PATH COPY ./s2i/bin/ $STI_SCRIPTS_PATH +RUN chmod +x $STI_SCRIPTS_PATH/init-wrapper # Copy extra files to the image. COPY ./root/ / diff --git a/20/README.md b/20/README.md index f5209b6e..2d9db373 100644 --- a/20/README.md +++ b/20/README.md @@ -145,6 +145,12 @@ Application developers can use the following environment variables to configure **`NPM_RUN`** Select an alternate / custom runtime mode, defined in your `package.json` file's [`scripts`](https://docs.npmjs.com/misc/scripts) section (default: npm run "start"). These user-defined run-scripts are unavailable while `DEV_MODE` is in use. +**`NODE_CMD`** + When specified (e.g.Specify `NODE_CMD="node server.js"`) the value of `NODE_CMD` is used to start the application instead of `npm start`. + +**`INIT_WRAPPER`** + When set to "true", the application is started via the `init-wrapper` script instead of using `npm start`, by looking for the presence of the files `server.js`, `index.js` or `main.js` in the order in which they are listed. In case of `NODE_CMD` environemnt variale is specified, then `init-wrapper` script will use the value of `NODE_CMD` to start your application. + **`HTTP_PROXY`** Use an npm proxy during assembly @@ -244,6 +250,47 @@ Below is an example _package.json_ file with the _main_ attribute and _start_ sc #### Note: `oc rsync` is only available in versions 3.1+ of OpenShift. +## init-wrapper + +init-wrapper script is located on `/usr/libexec/s2i/init-wrapper` and is used to handle: + +- Proper signal handling and propagation, as Node.js was not designed to run as PID 1. +- Reaping zombie child processes +Avoiding use of npm, there is more information on why you want to avoid that in the [Node.js reference architecture](https://github.com/nodeshift/nodejs-reference-architecture/blob/e4c4dc1fd20c2cac392e862859aaad27f85d504f/docs/development/building-good-containers.md#avoiding-using-npm-to-start-application). When the INIT_WRAPPER is set to true the application is started via the init script instead of using npm start. + +A detailed explanation on how the init-wrapper script works is avalable in +[this url](http://veithen.io/2014/11/16/sigterm-propagation.html). + +Example of using init-wrapper: + +**During image build** +``` +s2i -e INIT_WRAPPER=true build . buildImage node-app +docker run node-app +``` +**During container start** +``` +s2i build . buildImage node-app +docker run -e INIT_WRAPPER=true node-app +``` + +`init-wrapper` script can be disabled by setting the `INIT_WRAPPER` env variable to `false`. + +``` +docker run -e INIT_WRAPPER=false node-app +``` +`NODE_CMD` can be used during the build process or container start, in order to have more control on the command that `init-wrapper` script will wrap. + +For example: + +**during container build** +``` +s2i -e INIT_WRAPPER=true -e NODE_CMD="node index.js" build . buildImage node-app +``` +**during container start** +``` +docker run -e INIT_WRAPPER=false -e NODE_CMD="node index.js" node-app +``` See also -------- diff --git a/20/s2i/bin/init-wrapper b/20/s2i/bin/init-wrapper new file mode 100644 index 00000000..24e0d078 --- /dev/null +++ b/20/s2i/bin/init-wrapper @@ -0,0 +1,18 @@ +#!/bin/bash + +# Overview of how this script works: http://veithen.io/2014/11/16/sigterm-propagation.html +# Set a trap to kill the main app process when this +# init script receives SIGTERM or SIGINT +trap 'kill -s TERM $PID' TERM INT +# Execute the main application in the background +"$@" & +PID=$! +# wait command always terminates when trap is caught, even if the process hasn't finished yet +wait $PID +# Remove the trap and wait till the app process finishes completely +trap - TERM INT +# We wait again, since the first wait terminates when trap is caught +wait $PID +# Exit with the exit code of the app process +STATUS=$? +exit $STATUS \ No newline at end of file diff --git a/20/s2i/bin/run b/20/s2i/bin/run index ff566f55..9a207bce 100755 --- a/20/s2i/bin/run +++ b/20/s2i/bin/run @@ -20,6 +20,29 @@ run_node() { if [ "$DEV_MODE" == true ]; then echo "Launching via nodemon..." exec nodemon --inspect="$DEBUG_PORT" + elif [ -n "$NODE_CMD" ] && [ "$INIT_WRAPPER" == true ]; then + echo "launching via init wrapper..." + exec ${STI_SCRIPTS_PATH}/init-wrapper $NODE_CMD + elif [ -n "$NODE_CMD" ] && [ "$INIT_WRAPPER" == false ]; then + echo "Launching via ${NODE_CMD}" + exec $NODE_CMD + elif [ ! -n "$NODE_CMD" ] && [ "$INIT_WRAPPER" == true ]; then + + package_json_start=$(sed -n 's/\s*"start"\s*:\s*"\(.*\)".*/\1/p' package.json) + package_json_main=$(sed -n 's/\s*"main"\s*:\s*"\(.*\)".*/\1/p' package.json) + + if [ -n "$package_json_start" ]; then + start_command=$package_json_start + elif [ -n $package_json_main ]; then + start_command="node ." + elif [ -f "server.js" ]; then + start_command="node server.js" + else + echo "Failed to find file for starting the Node.js application" + exit 1 + fi + echo "launching via init wrapper..." + exec ${STI_SCRIPTS_PATH}/init-wrapper $start_command else echo "Launching via npm..." exec npm run -d $NPM_RUN From 61ebc3d05b780e6ea44f1840d5b0ecbbb15910b4 Mon Sep 17 00:00:00 2001 From: Costas Papastathis Date: Tue, 3 Oct 2023 14:51:25 +0300 Subject: [PATCH 18/23] fix: removing duplicate code and using absolute path on change chmod of init-wrapper --- 14/Dockerfile.fedora | 2 +- 18-minimal/Dockerfile.c8s | 4 +--- 18-minimal/Dockerfile.c9s | 5 +---- 18-minimal/Dockerfile.fedora | 2 +- 18-minimal/Dockerfile.rhel8 | 4 +--- 18-minimal/Dockerfile.rhel9 | 4 +--- 6 files changed, 6 insertions(+), 15 deletions(-) diff --git a/14/Dockerfile.fedora b/14/Dockerfile.fedora index 33928583..2dbd51de 100644 --- a/14/Dockerfile.fedora +++ b/14/Dockerfile.fedora @@ -58,7 +58,7 @@ RUN yum -y module enable nodejs:$NODEJS_VERSION && \ # Copy the S2I scripts from the specific language image to $STI_SCRIPTS_PATH COPY ./s2i/bin/ $STI_SCRIPTS_PATH -RUN chmod +x $STI_SCRIPTS_PATH/init-wrapper +RUN chmod +x /usr/libexec/s2i/init-wrapper # Copy extra files to the image, including help file. COPY ./root/ / diff --git a/18-minimal/Dockerfile.c8s b/18-minimal/Dockerfile.c8s index c35dfe58..07b65fb4 100644 --- a/18-minimal/Dockerfile.c8s +++ b/18-minimal/Dockerfile.c8s @@ -59,9 +59,7 @@ RUN INSTALL_PKGS="nodejs nodejs-nodemon nodejs-full-i18n npm findutils tar which COPY ./s2i/bin/ /usr/libexec/s2i -# Copy the S2I scripts from the specific language image to $STI_SCRIPTS_PATH -COPY ./s2i/bin/ $STI_SCRIPTS_PATH -RUN chmod +x $STI_SCRIPTS_PATH/init-wrapper +RUN chmod +x /usr/libexec/s2i/init-wrapper # Copy extra files to the image. COPY ./root/ / diff --git a/18-minimal/Dockerfile.c9s b/18-minimal/Dockerfile.c9s index 5eab7d2c..ecba5276 100644 --- a/18-minimal/Dockerfile.c9s +++ b/18-minimal/Dockerfile.c9s @@ -58,10 +58,7 @@ RUN INSTALL_PKGS="nodejs nodejs-nodemon nodejs-full-i18n npm findutils tar which rm -rf /mnt/rootfs/var/cache/* /mnt/rootfs/var/log/dnf* /mnt/rootfs/var/log/yum.* COPY ./s2i/bin/ /usr/libexec/s2i - -# Copy the S2I scripts from the specific language image to $STI_SCRIPTS_PATH -COPY ./s2i/bin/ $STI_SCRIPTS_PATH -RUN chmod +x $STI_SCRIPTS_PATH/init-wrapper +RUN chmod +x /usr/libexec/s2i/init-wrapper # Copy extra files to the image. COPY ./root/ / diff --git a/18-minimal/Dockerfile.fedora b/18-minimal/Dockerfile.fedora index e2025ff2..18ec1c36 100644 --- a/18-minimal/Dockerfile.fedora +++ b/18-minimal/Dockerfile.fedora @@ -56,7 +56,7 @@ RUN INSTALL_PKGS="nodejs nodejs-nodemon nodejs-full-i18n nodejs-npm findutils ta rm -rf /mnt/rootfs/var/cache/* /mnt/rootfs/var/log/dnf* /mnt/rootfs/var/log/yum.* COPY ./s2i/bin/ /usr/libexec/s2i -RUN chmod +x $STI_SCRIPTS_PATH/init-wrapper +RUN chmod +x /usr/libexec/s2i/init-wrapper # Copy extra files to the image. COPY ./root/ / diff --git a/18-minimal/Dockerfile.rhel8 b/18-minimal/Dockerfile.rhel8 index c0a5fe24..61327509 100644 --- a/18-minimal/Dockerfile.rhel8 +++ b/18-minimal/Dockerfile.rhel8 @@ -60,9 +60,7 @@ RUN INSTALL_PKGS="nodejs nodejs-nodemon nodejs-full-i18n npm findutils tar which COPY ./s2i/bin/ /usr/libexec/s2i -# Copy the S2I scripts from the specific language image to $STI_SCRIPTS_PATH -COPY ./s2i/bin/ $STI_SCRIPTS_PATH -RUN chmod +x $STI_SCRIPTS_PATH/init-wrapper +RUN chmod +x /usr/libexec/s2i/init-wrapper # Copy extra files to the image. COPY ./root/ / diff --git a/18-minimal/Dockerfile.rhel9 b/18-minimal/Dockerfile.rhel9 index 1168757c..cdff8219 100644 --- a/18-minimal/Dockerfile.rhel9 +++ b/18-minimal/Dockerfile.rhel9 @@ -60,9 +60,7 @@ RUN INSTALL_PKGS="nodejs nodejs-nodemon nodejs-full-i18n npm findutils tar which COPY ./s2i/bin/ /usr/libexec/s2i -# Copy the S2I scripts from the specific language image to $STI_SCRIPTS_PATH -COPY ./s2i/bin/ $STI_SCRIPTS_PATH -RUN chmod +x $STI_SCRIPTS_PATH/init-wrapper +RUN chmod +x /usr/libexec/s2i/init-wrapper # Copy extra files to the image. COPY ./root/ / From 8d2a34f51885762de352a45ad647ef2f30917b67 Mon Sep 17 00:00:00 2001 From: Costas Papastathis Date: Tue, 17 Oct 2023 15:21:48 +0300 Subject: [PATCH 19/23] fix: usring on 14 rhel7 absolute path instead of STI_SCRIPTS_PATH variable --- 14/Dockerfile.rhel7 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/14/Dockerfile.rhel7 b/14/Dockerfile.rhel7 index 68736a3f..50d998c8 100644 --- a/14/Dockerfile.rhel7 +++ b/14/Dockerfile.rhel7 @@ -67,7 +67,7 @@ RUN yum install -y yum-utils && \ # Copy the S2I scripts from the specific language image to $STI_SCRIPTS_PATH COPY ./s2i/bin/ $STI_SCRIPTS_PATH -RUN chmod +x $STI_SCRIPTS_PATH/init-wrapper +RUN chmod +x /usr/libexec/s2i/init-wrapper # Copy extra files to the image. COPY ./root/ / From 8aa1b868141c06d26dd5dd3a3ae6a0894501cf06 Mon Sep 17 00:00:00 2001 From: Costas Papastathis Date: Fri, 10 Nov 2023 17:07:23 +0200 Subject: [PATCH 20/23] fix: adding absolute path on copying scripts. rhel 7 node 14 --- 14/Dockerfile.rhel7 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/14/Dockerfile.rhel7 b/14/Dockerfile.rhel7 index 50d998c8..5a2e74dd 100644 --- a/14/Dockerfile.rhel7 +++ b/14/Dockerfile.rhel7 @@ -66,7 +66,7 @@ RUN yum install -y yum-utils && \ yum -y clean all --enablerepo='*' # Copy the S2I scripts from the specific language image to $STI_SCRIPTS_PATH -COPY ./s2i/bin/ $STI_SCRIPTS_PATH +COPY ./s2i/bin/ /usr/libexec/s2i RUN chmod +x /usr/libexec/s2i/init-wrapper # Copy extra files to the image. From f3a8baa47c3a0856560d271fbbe2b8954a37b9c8 Mon Sep 17 00:00:00 2001 From: Costas Papastathis Date: Tue, 4 Jun 2024 15:56:27 +0300 Subject: [PATCH 21/23] excluding init wrapper from rhel7 --- 14/Dockerfile.rhel7 | 3 +-- test/test-lib-nodejs.sh | 36 ++++++++++++++++++++++++------------ 2 files changed, 25 insertions(+), 14 deletions(-) diff --git a/14/Dockerfile.rhel7 b/14/Dockerfile.rhel7 index 5a2e74dd..2e9879a2 100644 --- a/14/Dockerfile.rhel7 +++ b/14/Dockerfile.rhel7 @@ -66,8 +66,7 @@ RUN yum install -y yum-utils && \ yum -y clean all --enablerepo='*' # Copy the S2I scripts from the specific language image to $STI_SCRIPTS_PATH -COPY ./s2i/bin/ /usr/libexec/s2i -RUN chmod +x /usr/libexec/s2i/init-wrapper +COPY ./s2i/bin/ $STI_SCRIPTS_PATH # Copy extra files to the image. COPY ./root/ / diff --git a/test/test-lib-nodejs.sh b/test/test-lib-nodejs.sh index 53013e7f..d689c468 100644 --- a/test/test-lib-nodejs.sh +++ b/test/test-lib-nodejs.sh @@ -490,33 +490,45 @@ function test_dev_mode_true_development() { } function test_node_cmd_production_init_wrapper_false() { - # NODE_ENV=production INIT_WRAPPER=false NODE_CMD="node server.js" - test_node_cmd app production false "node server.js" + if [ "$OS" != "rhel7" ]; then + # NODE_ENV=production INIT_WRAPPER=false NODE_CMD="node server.js" + test_node_cmd app production false "node server.js" + fi } function test_node_cmd_development_init_wrapper_true() { - # NODE_ENV=development INIT_WRAPPER=true NODE_CMD="node server.js" - test_node_cmd app development true "node server.js" + if [ "$OS" != "rhel7" ]; then + # NODE_ENV=development INIT_WRAPPER=true NODE_CMD="node server.js" + test_node_cmd app development true "node server.js" + fi } function test_node_cmd_production_init_wrapper_true() { - # NODE_ENV=production INIT_WRAPPER=true NODE_CMD="node server.js" - test_node_cmd app production true "node server.js" + if [ "$OS" != "rhel7" ]; then + # NODE_ENV=production INIT_WRAPPER=true NODE_CMD="node server.js" + test_node_cmd app production true "node server.js" + fi } function test_node_cmd_development_init_wrapper_false() { - # NODE_ENV=development INIT_WRAPPER=false NODE_CMD="node server.js" - test_node_cmd app development false "node server.js" + if [ "$OS" != "rhel7" ]; then + # NODE_ENV=development INIT_WRAPPER=false NODE_CMD="node server.js" + test_node_cmd app development false "node server.js" + fi } function test_init_wrapper_true_development() { - # NODE_ENV=development INIT_WRAPPER=true - test_node_cmd app development true + if [ "$OS" != "rhel7" ]; then + # NODE_ENV=development INIT_WRAPPER=true + test_node_cmd app development true + fi } function test_init_wrapper_false_development() { - # NODE_ENV=development INIT_WRAPPER=true - test_node_cmd app development false + if [ "$OS" != "rhel7" ]; then + # NODE_ENV=development INIT_WRAPPER=true + test_node_cmd app development false + fi } function test_dev_mode_false_development() { From 7578c8a61dd247e6b609a3312d844b07c8f71bdc Mon Sep 17 00:00:00 2001 From: Costas Papastathis Date: Fri, 20 Sep 2024 11:07:31 +0300 Subject: [PATCH 22/23] Rebasing and adding inti-wrapper for node 22 --- 22-minimal/Dockerfile.c10s | 1 + 22-minimal/Dockerfile.c8s | 1 + 22-minimal/Dockerfile.c9s | 1 + 22-minimal/Dockerfile.fedora | 1 + 22-minimal/Dockerfile.rhel8 | 1 + 22-minimal/Dockerfile.rhel9 | 1 + 22-minimal/README.md | 46 ++++++++++++++++++++++++++++++++ 22-minimal/s2i/bin/init-wrapper | 18 +++++++++++++ 22-minimal/s2i/bin/run | 23 ++++++++++++++++ 22/Dockerfile.c10s | 1 + 22/Dockerfile.c8s | 1 + 22/Dockerfile.c9s | 1 + 22/Dockerfile.fedora | 1 + 22/Dockerfile.rhel8 | 1 + 22/Dockerfile.rhel9 | 1 + 22/README.md | 47 +++++++++++++++++++++++++++++++++ 22/s2i/bin/init-wrapper | 18 +++++++++++++ 22/s2i/bin/run | 23 ++++++++++++++++ 18 files changed, 187 insertions(+) create mode 100644 22-minimal/s2i/bin/init-wrapper create mode 100644 22/s2i/bin/init-wrapper diff --git a/22-minimal/Dockerfile.c10s b/22-minimal/Dockerfile.c10s index 80ccecbf..b558a0ba 100644 --- a/22-minimal/Dockerfile.c10s +++ b/22-minimal/Dockerfile.c10s @@ -56,6 +56,7 @@ RUN INSTALL_PKGS="nodejs$NODEJS_VERSION nodejs-nodemon nodejs$NODEJS_VERSION-ful rm -rf /mnt/rootfs/var/cache/* /mnt/rootfs/var/log/dnf* /mnt/rootfs/var/log/yum.* COPY ./s2i/bin/ /usr/libexec/s2i +RUN chmod +x /usr/libexec/s2i/init-wrapper # Copy extra files to the image. COPY ./root/ / diff --git a/22-minimal/Dockerfile.c8s b/22-minimal/Dockerfile.c8s index ac809767..d7829589 100644 --- a/22-minimal/Dockerfile.c8s +++ b/22-minimal/Dockerfile.c8s @@ -58,6 +58,7 @@ RUN INSTALL_PKGS="nodejs nodejs-nodemon nodejs-full-i18n npm findutils tar which rm -rf /mnt/rootfs/var/cache/* /mnt/rootfs/var/log/dnf* /mnt/rootfs/var/log/yum.* COPY ./s2i/bin/ /usr/libexec/s2i +RUN chmod +x /usr/libexec/s2i/init-wrapper # Copy extra files to the image. COPY ./root/ / diff --git a/22-minimal/Dockerfile.c9s b/22-minimal/Dockerfile.c9s index c9f1c534..92275fbe 100644 --- a/22-minimal/Dockerfile.c9s +++ b/22-minimal/Dockerfile.c9s @@ -58,6 +58,7 @@ RUN INSTALL_PKGS="nodejs nodejs-nodemon nodejs-full-i18n npm findutils tar which rm -rf /mnt/rootfs/var/cache/* /mnt/rootfs/var/log/dnf* /mnt/rootfs/var/log/yum.* COPY ./s2i/bin/ /usr/libexec/s2i +RUN chmod +x /usr/libexec/s2i/init-wrapper # Copy extra files to the image. COPY ./root/ / diff --git a/22-minimal/Dockerfile.fedora b/22-minimal/Dockerfile.fedora index 73cbe75d..2fefa30d 100644 --- a/22-minimal/Dockerfile.fedora +++ b/22-minimal/Dockerfile.fedora @@ -60,6 +60,7 @@ RUN INSTALL_PKGS="nodejs$NODEJS_VERSION nodejs-nodemon nodejs$NODEJS_VERSION-ful # COPY ./s2i/bin/ /usr/libexec/s2i +RUN chmod +x /usr/libexec/s2i/init-wrapper # Copy extra files to the image. COPY ./root/ / diff --git a/22-minimal/Dockerfile.rhel8 b/22-minimal/Dockerfile.rhel8 index 34d5daa2..5f6d0bc3 100644 --- a/22-minimal/Dockerfile.rhel8 +++ b/22-minimal/Dockerfile.rhel8 @@ -59,6 +59,7 @@ RUN INSTALL_PKGS="nodejs nodejs-nodemon nodejs-full-i18n npm findutils tar which rm -rf /mnt/rootfs/var/cache/* /mnt/rootfs/var/log/dnf* /mnt/rootfs/var/log/yum.* COPY ./s2i/bin/ /usr/libexec/s2i +RUN chmod +x /usr/libexec/s2i/init-wrapper # Copy extra files to the image. COPY ./root/ / diff --git a/22-minimal/Dockerfile.rhel9 b/22-minimal/Dockerfile.rhel9 index 61259460..9a18e3ec 100644 --- a/22-minimal/Dockerfile.rhel9 +++ b/22-minimal/Dockerfile.rhel9 @@ -59,6 +59,7 @@ RUN INSTALL_PKGS="nodejs nodejs-nodemon nodejs-full-i18n npm findutils tar which rm -rf /mnt/rootfs/var/cache/* /mnt/rootfs/var/log/dnf* /mnt/rootfs/var/log/yum.* COPY ./s2i/bin/ /usr/libexec/s2i +RUN chmod +x /usr/libexec/s2i/init-wrapper # Copy extra files to the image. COPY ./root/ / diff --git a/22-minimal/README.md b/22-minimal/README.md index 21b64b01..ae1beedb 100644 --- a/22-minimal/README.md +++ b/22-minimal/README.md @@ -215,6 +215,12 @@ Application developers can use the following environment variables to configure **`NPM_RUN`** Select an alternate / custom runtime mode, defined in your `package.json` file's [`scripts`](https://docs.npmjs.com/misc/scripts) section (default: npm run "start"). These user-defined run-scripts are unavailable while `DEV_MODE` is in use. +**`NODE_CMD`** + When specified (e.g.Specify `NODE_CMD="node server.js"`) the value of `NODE_CMD` is used to start the application instead of `npm start`. + +**`INIT_WRAPPER`** + When set to "true", the application is started via the `init-wrapper` script instead of using `npm start`, by looking for the presence of the files `server.js`, `index.js` or `main.js` in the order in which they are listed. In case of `NODE_CMD` environemnt variale is specified, then `init-wrapper` script will use the value of `NODE_CMD` to start your application. + #### Additional variables used in the full-sized image **`HTTP_PROXY`** @@ -316,7 +322,47 @@ Below is an example _package.json_ file with the _main_ attribute and _start_ sc #### Note: `oc rsync` is only available in versions 3.1+ of OpenShift. +## init-wrapper + +init-wrapper script is located on `/usr/libexec/s2i/init-wrapper` and is used to handle: + +- Proper signal handling and propagation, as Node.js was not designed to run as PID 1. +- Reaping zombie child processes +Avoiding use of npm, there is more information on why you want to avoid that in the [Node.js reference architecture](https://github.com/nodeshift/nodejs-reference-architecture/blob/e4c4dc1fd20c2cac392e862859aaad27f85d504f/docs/development/building-good-containers.md#avoiding-using-npm-to-start-application). When the INIT_WRAPPER is set to true the application is started via the init script instead of using npm start. + +A detailed explanation on how the init-wrapper script works is avalable in +[this url](http://veithen.io/2014/11/16/sigterm-propagation.html). + +Example of using init-wrapper: + +**During image build** +``` +s2i -e INIT_WRAPPER=true build . buildImage node-app +docker run node-app +``` +**During container start** +``` +s2i build . buildImage node-app +docker run -e INIT_WRAPPER=true node-app +``` + +`init-wrapper` script can be disabled by setting the `INIT_WRAPPER` env variable to `false`. + +``` +docker run -e INIT_WRAPPER=false node-app +``` +`NODE_CMD` can be used during the build process or container start, in order to have more control on the command that `init-wrapper` script will wrap. + +For example: +**during container build** +``` +s2i -e INIT_WRAPPER=true -e NODE_CMD="node index.js" build . buildImage node-app +``` +**during container start** +``` +docker run -e INIT_WRAPPER=false -e NODE_CMD="node index.js" node-app +``` See also -------- Dockerfile and other sources are available on https://github.com/sclorg/s2i-nodejs-container. diff --git a/22-minimal/s2i/bin/init-wrapper b/22-minimal/s2i/bin/init-wrapper new file mode 100644 index 00000000..24e0d078 --- /dev/null +++ b/22-minimal/s2i/bin/init-wrapper @@ -0,0 +1,18 @@ +#!/bin/bash + +# Overview of how this script works: http://veithen.io/2014/11/16/sigterm-propagation.html +# Set a trap to kill the main app process when this +# init script receives SIGTERM or SIGINT +trap 'kill -s TERM $PID' TERM INT +# Execute the main application in the background +"$@" & +PID=$! +# wait command always terminates when trap is caught, even if the process hasn't finished yet +wait $PID +# Remove the trap and wait till the app process finishes completely +trap - TERM INT +# We wait again, since the first wait terminates when trap is caught +wait $PID +# Exit with the exit code of the app process +STATUS=$? +exit $STATUS \ No newline at end of file diff --git a/22-minimal/s2i/bin/run b/22-minimal/s2i/bin/run index 7894f47f..10150f34 100755 --- a/22-minimal/s2i/bin/run +++ b/22-minimal/s2i/bin/run @@ -16,6 +16,29 @@ run_node() { if [ "$DEV_MODE" == true ]; then echo "Launching via nodemon..." exec nodemon --inspect="$DEBUG_PORT" + elif [ -n "$NODE_CMD" ] && [ "$INIT_WRAPPER" == true ]; then + echo "launching via init wrapper..." + exec ${STI_SCRIPTS_PATH}/init-wrapper $NODE_CMD + elif [ -n "$NODE_CMD" ] && [ "$INIT_WRAPPER" == false ]; then + echo "Launching via ${NODE_CMD}" + exec $NODE_CMD + elif [ ! -n "$NODE_CMD" ] && [ "$INIT_WRAPPER" == true ]; then + + package_json_start=$(sed -n 's/\s*"start"\s*:\s*"\(.*\)".*/\1/p' package.json) + package_json_main=$(sed -n 's/\s*"main"\s*:\s*"\(.*\)".*/\1/p' package.json) + + if [ -n "$package_json_start" ]; then + start_command=$package_json_start + elif [ -n $package_json_main ]; then + start_command="node ." + elif [ -f "server.js" ]; then + start_command="node server.js" + else + echo "Failed to find file for starting the Node.js application" + exit 1 + fi + echo "launching via init wrapper..." + exec ${STI_SCRIPTS_PATH}/init-wrapper $start_command else echo "Launching via npm..." exec npm run -d $NPM_RUN diff --git a/22/Dockerfile.c10s b/22/Dockerfile.c10s index 226938c4..0cc8da62 100644 --- a/22/Dockerfile.c10s +++ b/22/Dockerfile.c10s @@ -65,6 +65,7 @@ RUN INSTALL_PKGS="make gcc gcc-c++ git openssl-devel nodejs nodejs-nodemon nodej # Copy the S2I scripts from the specific language image to $STI_SCRIPTS_PATH COPY ./s2i/bin/ $STI_SCRIPTS_PATH +RUN chmod +x /usr/libexec/s2i/init-wrapper # Copy extra files to the image. COPY ./root/ / diff --git a/22/Dockerfile.c8s b/22/Dockerfile.c8s index 7e9fdc2b..6a7e0501 100644 --- a/22/Dockerfile.c8s +++ b/22/Dockerfile.c8s @@ -65,6 +65,7 @@ RUN yum -y module enable nodejs:$NODEJS_VERSION && \ # Copy the S2I scripts from the specific language image to $STI_SCRIPTS_PATH COPY ./s2i/bin/ $STI_SCRIPTS_PATH +RUN chmod +x /usr/libexec/s2i/init-wrapper # Copy extra files to the image. COPY ./root/ / diff --git a/22/Dockerfile.c9s b/22/Dockerfile.c9s index efb59bf5..0b47eefa 100644 --- a/22/Dockerfile.c9s +++ b/22/Dockerfile.c9s @@ -65,6 +65,7 @@ RUN dnf -y module enable nodejs:$NODEJS_VERSION && \ # Copy the S2I scripts from the specific language image to $STI_SCRIPTS_PATH COPY ./s2i/bin/ $STI_SCRIPTS_PATH +RUN chmod +x /usr/libexec/s2i/init-wrapper # Copy extra files to the image. COPY ./root/ / diff --git a/22/Dockerfile.fedora b/22/Dockerfile.fedora index 89f588a5..81708749 100644 --- a/22/Dockerfile.fedora +++ b/22/Dockerfile.fedora @@ -59,6 +59,7 @@ RUN INSTALL_PKGS="make gcc gcc-c++ libatomic_ops git openssl-devel nodejs$NODEJS # Copy the S2I scripts from the specific language image to $STI_SCRIPTS_PATH COPY ./s2i/bin/ $STI_SCRIPTS_PATH +RUN chmod +x /usr/libexec/s2i/init-wrapper # Copy extra files to the image, including help file. COPY ./root/ / diff --git a/22/Dockerfile.rhel8 b/22/Dockerfile.rhel8 index c2f5028b..15d4896e 100644 --- a/22/Dockerfile.rhel8 +++ b/22/Dockerfile.rhel8 @@ -65,6 +65,7 @@ RUN dnf -y module enable nodejs:$NODEJS_VERSION && \ # Copy the S2I scripts from the specific language image to $STI_SCRIPTS_PATH COPY ./s2i/bin/ $STI_SCRIPTS_PATH +RUN chmod +x /usr/libexec/s2i/init-wrapper # Copy extra files to the image. COPY ./root/ / diff --git a/22/Dockerfile.rhel9 b/22/Dockerfile.rhel9 index 0dbe3cb7..c6c4a1e6 100644 --- a/22/Dockerfile.rhel9 +++ b/22/Dockerfile.rhel9 @@ -64,6 +64,7 @@ RUN dnf -y module enable nodejs:$NODEJS_VERSION && \ # Copy the S2I scripts from the specific language image to $STI_SCRIPTS_PATH COPY ./s2i/bin/ $STI_SCRIPTS_PATH +RUN chmod +x /usr/libexec/s2i/init-wrapper # Copy extra files to the image. COPY ./root/ / diff --git a/22/README.md b/22/README.md index 19880178..3d814e81 100644 --- a/22/README.md +++ b/22/README.md @@ -142,6 +142,12 @@ Application developers can use the following environment variables to configure **`NPM_BUILD`** Select an alternate / custom build command, defined in your `package.json` file's [`scripts`](https://docs.npmjs.com/misc/scripts) section (default: npm run "build"). These user-defined run-scripts are unavailable while `DEV_MODE` is in use. +**`NODE_CMD`** + When specified (e.g.Specify `NODE_CMD="node server.js"`) the value of `NODE_CMD` is used to start the application instead of `npm start`. + +**`INIT_WRAPPER`** + When set to "true", the application is started via the `init-wrapper` script instead of using `npm start`, by looking for the presence of the files `server.js`, `index.js` or `main.js` in the order in which they are listed. In case of `NODE_CMD` environemnt variale is specified, then `init-wrapper` script will use the value of `NODE_CMD` to start your application. + **`NPM_RUN`** Select an alternate / custom runtime mode, defined in your `package.json` file's [`scripts`](https://docs.npmjs.com/misc/scripts) section (default: npm run "start"). These user-defined run-scripts are unavailable while `DEV_MODE` is in use. @@ -244,6 +250,47 @@ Below is an example _package.json_ file with the _main_ attribute and _start_ sc #### Note: `oc rsync` is only available in versions 3.1+ of OpenShift. +## init-wrapper + +init-wrapper script is located on `/usr/libexec/s2i/init-wrapper` and is used to handle: + +- Proper signal handling and propagation, as Node.js was not designed to run as PID 1. +- Reaping zombie child processes +Avoiding use of npm, there is more information on why you want to avoid that in the [Node.js reference architecture](https://github.com/nodeshift/nodejs-reference-architecture/blob/e4c4dc1fd20c2cac392e862859aaad27f85d504f/docs/development/building-good-containers.md#avoiding-using-npm-to-start-application). When the INIT_WRAPPER is set to true the application is started via the init script instead of using npm start. + +A detailed explanation on how the init-wrapper script works is avalable in +[this url](http://veithen.io/2014/11/16/sigterm-propagation.html). + +Example of using init-wrapper: + +**During image build** +``` +s2i -e INIT_WRAPPER=true build . buildImage node-app +docker run node-app +``` +**During container start** +``` +s2i build . buildImage node-app +docker run -e INIT_WRAPPER=true node-app +``` + +`init-wrapper` script can be disabled by setting the `INIT_WRAPPER` env variable to `false`. + +``` +docker run -e INIT_WRAPPER=false node-app +``` +`NODE_CMD` can be used during the build process or container start, in order to have more control on the command that `init-wrapper` script will wrap. + +For example: + +**during container build** +``` +s2i -e INIT_WRAPPER=true -e NODE_CMD="node index.js" build . buildImage node-app +``` +**during container start** +``` +docker run -e INIT_WRAPPER=false -e NODE_CMD="node index.js" node-app +``` See also -------- diff --git a/22/s2i/bin/init-wrapper b/22/s2i/bin/init-wrapper new file mode 100644 index 00000000..24e0d078 --- /dev/null +++ b/22/s2i/bin/init-wrapper @@ -0,0 +1,18 @@ +#!/bin/bash + +# Overview of how this script works: http://veithen.io/2014/11/16/sigterm-propagation.html +# Set a trap to kill the main app process when this +# init script receives SIGTERM or SIGINT +trap 'kill -s TERM $PID' TERM INT +# Execute the main application in the background +"$@" & +PID=$! +# wait command always terminates when trap is caught, even if the process hasn't finished yet +wait $PID +# Remove the trap and wait till the app process finishes completely +trap - TERM INT +# We wait again, since the first wait terminates when trap is caught +wait $PID +# Exit with the exit code of the app process +STATUS=$? +exit $STATUS \ No newline at end of file diff --git a/22/s2i/bin/run b/22/s2i/bin/run index ff566f55..9a207bce 100755 --- a/22/s2i/bin/run +++ b/22/s2i/bin/run @@ -20,6 +20,29 @@ run_node() { if [ "$DEV_MODE" == true ]; then echo "Launching via nodemon..." exec nodemon --inspect="$DEBUG_PORT" + elif [ -n "$NODE_CMD" ] && [ "$INIT_WRAPPER" == true ]; then + echo "launching via init wrapper..." + exec ${STI_SCRIPTS_PATH}/init-wrapper $NODE_CMD + elif [ -n "$NODE_CMD" ] && [ "$INIT_WRAPPER" == false ]; then + echo "Launching via ${NODE_CMD}" + exec $NODE_CMD + elif [ ! -n "$NODE_CMD" ] && [ "$INIT_WRAPPER" == true ]; then + + package_json_start=$(sed -n 's/\s*"start"\s*:\s*"\(.*\)".*/\1/p' package.json) + package_json_main=$(sed -n 's/\s*"main"\s*:\s*"\(.*\)".*/\1/p' package.json) + + if [ -n "$package_json_start" ]; then + start_command=$package_json_start + elif [ -n $package_json_main ]; then + start_command="node ." + elif [ -f "server.js" ]; then + start_command="node server.js" + else + echo "Failed to find file for starting the Node.js application" + exit 1 + fi + echo "launching via init wrapper..." + exec ${STI_SCRIPTS_PATH}/init-wrapper $start_command else echo "Launching via npm..." exec npm run -d $NPM_RUN From 45048fd97981b0924e5a1fd0c86272f3bc91a6cf Mon Sep 17 00:00:00 2001 From: Costas Papastathis Date: Wed, 25 Sep 2024 14:21:06 +0300 Subject: [PATCH 23/23] adding missing library --- test/test-lib-nodejs.sh | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/test/test-lib-nodejs.sh b/test/test-lib-nodejs.sh index d689c468..61a4a699 100644 --- a/test/test-lib-nodejs.sh +++ b/test/test-lib-nodejs.sh @@ -356,6 +356,31 @@ test_incremental_build() { } +test_node_cmd() { + local app=$1 + local node_env=$2 + local init_wrapper=$3 + local node_cmd=$4 + + run_test_application_with_quoted_args $app "-e NODE_ENV=$node_env -e INIT_WRAPPER=$init_wrapper -e NODE_CMD=$node_cmd" + logs=$(container_logs) + wait_for_cid + + test_connection + ct_check_testcase_result $? + + logs=$(container_logs) + echo ${logs} | grep -q DEBUG_PORT=5858 + ct_check_testcase_result $? + echo ${logs} | grep -q NODE_ENV=$node_env + ct_check_testcase_result $? + echo ${logs} | grep -q INIT_WRAPPER=$init_wrapper + ct_check_testcase_result $? + echo ${logs} | grep -q NODE_CMD="$node_cmd" + ct_check_testcase_result $? + + kill_test_application +} # test express webapp run_s2i_build_express_webapp() {