Skip to content

Commit aa852d7

Browse files
Costas Papastathisgithub-actions[bot]
Costas Papastathis
authored andcommitted
Rebasing and adding inti-wrapper for node 22
1 parent 1967b4d commit aa852d7

18 files changed

+187
-0
lines changed

22-minimal/Dockerfile.c10s

+1
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ RUN INSTALL_PKGS="nodejs$NODEJS_VERSION nodejs-nodemon nodejs$NODEJS_VERSION-ful
5656
rm -rf /mnt/rootfs/var/cache/* /mnt/rootfs/var/log/dnf* /mnt/rootfs/var/log/yum.*
5757

5858
COPY ./s2i/bin/ /usr/libexec/s2i
59+
RUN chmod +x /usr/libexec/s2i/init-wrapper
5960

6061
# Copy extra files to the image.
6162
COPY ./root/ /

22-minimal/Dockerfile.c8s

+1
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ RUN INSTALL_PKGS="nodejs nodejs-nodemon nodejs-full-i18n npm findutils tar which
5858
rm -rf /mnt/rootfs/var/cache/* /mnt/rootfs/var/log/dnf* /mnt/rootfs/var/log/yum.*
5959

6060
COPY ./s2i/bin/ /usr/libexec/s2i
61+
RUN chmod +x /usr/libexec/s2i/init-wrapper
6162

6263
# Copy extra files to the image.
6364
COPY ./root/ /

22-minimal/Dockerfile.c9s

+1
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ RUN INSTALL_PKGS="nodejs nodejs-nodemon nodejs-full-i18n npm findutils tar which
5858
rm -rf /mnt/rootfs/var/cache/* /mnt/rootfs/var/log/dnf* /mnt/rootfs/var/log/yum.*
5959

6060
COPY ./s2i/bin/ /usr/libexec/s2i
61+
RUN chmod +x /usr/libexec/s2i/init-wrapper
6162

6263
# Copy extra files to the image.
6364
COPY ./root/ /

22-minimal/Dockerfile.fedora

+1
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ RUN INSTALL_PKGS="nodejs$NODEJS_VERSION nodejs-nodemon nodejs$NODEJS_VERSION-ful
6060

6161
#
6262
COPY ./s2i/bin/ /usr/libexec/s2i
63+
RUN chmod +x /usr/libexec/s2i/init-wrapper
6364

6465
# Copy extra files to the image.
6566
COPY ./root/ /

22-minimal/Dockerfile.rhel8

+1
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ RUN INSTALL_PKGS="nodejs nodejs-nodemon nodejs-full-i18n npm findutils tar which
5959
rm -rf /mnt/rootfs/var/cache/* /mnt/rootfs/var/log/dnf* /mnt/rootfs/var/log/yum.*
6060

6161
COPY ./s2i/bin/ /usr/libexec/s2i
62+
RUN chmod +x /usr/libexec/s2i/init-wrapper
6263

6364
# Copy extra files to the image.
6465
COPY ./root/ /

22-minimal/Dockerfile.rhel9

+1
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ RUN INSTALL_PKGS="nodejs nodejs-nodemon nodejs-full-i18n npm findutils tar which
5959
rm -rf /mnt/rootfs/var/cache/* /mnt/rootfs/var/log/dnf* /mnt/rootfs/var/log/yum.*
6060

6161
COPY ./s2i/bin/ /usr/libexec/s2i
62+
RUN chmod +x /usr/libexec/s2i/init-wrapper
6263

6364
# Copy extra files to the image.
6465
COPY ./root/ /

22-minimal/README.md

+46
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,12 @@ Application developers can use the following environment variables to configure
215215
**`NPM_RUN`**
216216
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.
217217

218+
**`NODE_CMD`**
219+
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`.
220+
221+
**`INIT_WRAPPER`**
222+
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.
223+
218224
#### Additional variables used in the full-sized image
219225

220226
**`HTTP_PROXY`**
@@ -316,7 +322,47 @@ Below is an example _package.json_ file with the _main_ attribute and _start_ sc
316322
#### Note:
317323
`oc rsync` is only available in versions 3.1+ of OpenShift.
318324

325+
## init-wrapper
326+
327+
init-wrapper script is located on `/usr/libexec/s2i/init-wrapper` and is used to handle:
328+
329+
- Proper signal handling and propagation, as Node.js was not designed to run as PID 1.
330+
- Reaping zombie child processes
331+
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.
332+
333+
A detailed explanation on how the init-wrapper script works is avalable in
334+
[this url](http://veithen.io/2014/11/16/sigterm-propagation.html).
335+
336+
Example of using init-wrapper:
337+
338+
**During image build**
339+
```
340+
s2i -e INIT_WRAPPER=true build . buildImage node-app
341+
docker run node-app
342+
```
343+
**During container start**
344+
```
345+
s2i build . buildImage node-app
346+
docker run -e INIT_WRAPPER=true node-app
347+
```
348+
349+
`init-wrapper` script can be disabled by setting the `INIT_WRAPPER` env variable to `false`.
350+
351+
```
352+
docker run -e INIT_WRAPPER=false node-app
353+
```
354+
`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.
355+
356+
For example:
319357

358+
**during container build**
359+
```
360+
s2i -e INIT_WRAPPER=true -e NODE_CMD="node index.js" build . buildImage node-app
361+
```
362+
**during container start**
363+
```
364+
docker run -e INIT_WRAPPER=false -e NODE_CMD="node index.js" node-app
365+
```
320366
See also
321367
--------
322368
Dockerfile and other sources are available on https://github.com/sclorg/s2i-nodejs-container.

22-minimal/s2i/bin/init-wrapper

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
#!/bin/bash
2+
3+
# Overview of how this script works: http://veithen.io/2014/11/16/sigterm-propagation.html
4+
# Set a trap to kill the main app process when this
5+
# init script receives SIGTERM or SIGINT
6+
trap 'kill -s TERM $PID' TERM INT
7+
# Execute the main application in the background
8+
"$@" &
9+
PID=$!
10+
# wait command always terminates when trap is caught, even if the process hasn't finished yet
11+
wait $PID
12+
# Remove the trap and wait till the app process finishes completely
13+
trap - TERM INT
14+
# We wait again, since the first wait terminates when trap is caught
15+
wait $PID
16+
# Exit with the exit code of the app process
17+
STATUS=$?
18+
exit $STATUS

22-minimal/s2i/bin/run

+23
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,29 @@ run_node() {
1616
if [ "$DEV_MODE" == true ]; then
1717
echo "Launching via nodemon..."
1818
exec nodemon --inspect="$DEBUG_PORT"
19+
elif [ -n "$NODE_CMD" ] && [ "$INIT_WRAPPER" == true ]; then
20+
echo "launching via init wrapper..."
21+
exec ${STI_SCRIPTS_PATH}/init-wrapper $NODE_CMD
22+
elif [ -n "$NODE_CMD" ] && [ "$INIT_WRAPPER" == false ]; then
23+
echo "Launching via ${NODE_CMD}"
24+
exec $NODE_CMD
25+
elif [ ! -n "$NODE_CMD" ] && [ "$INIT_WRAPPER" == true ]; then
26+
27+
package_json_start=$(sed -n 's/\s*"start"\s*:\s*"\(.*\)".*/\1/p' package.json)
28+
package_json_main=$(sed -n 's/\s*"main"\s*:\s*"\(.*\)".*/\1/p' package.json)
29+
30+
if [ -n "$package_json_start" ]; then
31+
start_command=$package_json_start
32+
elif [ -n $package_json_main ]; then
33+
start_command="node ."
34+
elif [ -f "server.js" ]; then
35+
start_command="node server.js"
36+
else
37+
echo "Failed to find file for starting the Node.js application"
38+
exit 1
39+
fi
40+
echo "launching via init wrapper..."
41+
exec ${STI_SCRIPTS_PATH}/init-wrapper $start_command
1942
else
2043
echo "Launching via npm..."
2144
exec npm run -d $NPM_RUN

22/Dockerfile.c10s

+1
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ RUN INSTALL_PKGS="make gcc gcc-c++ git openssl-devel nodejs nodejs-nodemon nodej
6565

6666
# Copy the S2I scripts from the specific language image to $STI_SCRIPTS_PATH
6767
COPY ./s2i/bin/ $STI_SCRIPTS_PATH
68+
RUN chmod +x /usr/libexec/s2i/init-wrapper
6869

6970
# Copy extra files to the image.
7071
COPY ./root/ /

22/Dockerfile.c8s

+1
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ RUN yum -y module enable nodejs:$NODEJS_VERSION && \
6565

6666
# Copy the S2I scripts from the specific language image to $STI_SCRIPTS_PATH
6767
COPY ./s2i/bin/ $STI_SCRIPTS_PATH
68+
RUN chmod +x /usr/libexec/s2i/init-wrapper
6869

6970
# Copy extra files to the image.
7071
COPY ./root/ /

22/Dockerfile.c9s

+1
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ RUN dnf -y module enable nodejs:$NODEJS_VERSION && \
6565

6666
# Copy the S2I scripts from the specific language image to $STI_SCRIPTS_PATH
6767
COPY ./s2i/bin/ $STI_SCRIPTS_PATH
68+
RUN chmod +x /usr/libexec/s2i/init-wrapper
6869

6970
# Copy extra files to the image.
7071
COPY ./root/ /

22/Dockerfile.fedora

+1
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ RUN INSTALL_PKGS="make gcc gcc-c++ libatomic_ops git openssl-devel nodejs$NODEJS
5959

6060
# Copy the S2I scripts from the specific language image to $STI_SCRIPTS_PATH
6161
COPY ./s2i/bin/ $STI_SCRIPTS_PATH
62+
RUN chmod +x /usr/libexec/s2i/init-wrapper
6263

6364
# Copy extra files to the image, including help file.
6465
COPY ./root/ /

22/Dockerfile.rhel8

+1
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ RUN dnf -y module enable nodejs:$NODEJS_VERSION && \
6565

6666
# Copy the S2I scripts from the specific language image to $STI_SCRIPTS_PATH
6767
COPY ./s2i/bin/ $STI_SCRIPTS_PATH
68+
RUN chmod +x /usr/libexec/s2i/init-wrapper
6869

6970
# Copy extra files to the image.
7071
COPY ./root/ /

22/Dockerfile.rhel9

+1
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ RUN dnf -y module enable nodejs:$NODEJS_VERSION && \
6464

6565
# Copy the S2I scripts from the specific language image to $STI_SCRIPTS_PATH
6666
COPY ./s2i/bin/ $STI_SCRIPTS_PATH
67+
RUN chmod +x /usr/libexec/s2i/init-wrapper
6768

6869
# Copy extra files to the image.
6970
COPY ./root/ /

22/README.md

+47
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,12 @@ Application developers can use the following environment variables to configure
142142
**`NPM_BUILD`**
143143
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.
144144

145+
**`NODE_CMD`**
146+
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`.
147+
148+
**`INIT_WRAPPER`**
149+
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.
150+
145151
**`NPM_RUN`**
146152
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.
147153

@@ -244,6 +250,47 @@ Below is an example _package.json_ file with the _main_ attribute and _start_ sc
244250
#### Note:
245251
`oc rsync` is only available in versions 3.1+ of OpenShift.
246252

253+
## init-wrapper
254+
255+
init-wrapper script is located on `/usr/libexec/s2i/init-wrapper` and is used to handle:
256+
257+
- Proper signal handling and propagation, as Node.js was not designed to run as PID 1.
258+
- Reaping zombie child processes
259+
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.
260+
261+
A detailed explanation on how the init-wrapper script works is avalable in
262+
[this url](http://veithen.io/2014/11/16/sigterm-propagation.html).
263+
264+
Example of using init-wrapper:
265+
266+
**During image build**
267+
```
268+
s2i -e INIT_WRAPPER=true build . buildImage node-app
269+
docker run node-app
270+
```
271+
**During container start**
272+
```
273+
s2i build . buildImage node-app
274+
docker run -e INIT_WRAPPER=true node-app
275+
```
276+
277+
`init-wrapper` script can be disabled by setting the `INIT_WRAPPER` env variable to `false`.
278+
279+
```
280+
docker run -e INIT_WRAPPER=false node-app
281+
```
282+
`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.
283+
284+
For example:
285+
286+
**during container build**
287+
```
288+
s2i -e INIT_WRAPPER=true -e NODE_CMD="node index.js" build . buildImage node-app
289+
```
290+
**during container start**
291+
```
292+
docker run -e INIT_WRAPPER=false -e NODE_CMD="node index.js" node-app
293+
```
247294

248295
See also
249296
--------

22/s2i/bin/init-wrapper

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
#!/bin/bash
2+
3+
# Overview of how this script works: http://veithen.io/2014/11/16/sigterm-propagation.html
4+
# Set a trap to kill the main app process when this
5+
# init script receives SIGTERM or SIGINT
6+
trap 'kill -s TERM $PID' TERM INT
7+
# Execute the main application in the background
8+
"$@" &
9+
PID=$!
10+
# wait command always terminates when trap is caught, even if the process hasn't finished yet
11+
wait $PID
12+
# Remove the trap and wait till the app process finishes completely
13+
trap - TERM INT
14+
# We wait again, since the first wait terminates when trap is caught
15+
wait $PID
16+
# Exit with the exit code of the app process
17+
STATUS=$?
18+
exit $STATUS

22/s2i/bin/run

+23
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,29 @@ run_node() {
2020
if [ "$DEV_MODE" == true ]; then
2121
echo "Launching via nodemon..."
2222
exec nodemon --inspect="$DEBUG_PORT"
23+
elif [ -n "$NODE_CMD" ] && [ "$INIT_WRAPPER" == true ]; then
24+
echo "launching via init wrapper..."
25+
exec ${STI_SCRIPTS_PATH}/init-wrapper $NODE_CMD
26+
elif [ -n "$NODE_CMD" ] && [ "$INIT_WRAPPER" == false ]; then
27+
echo "Launching via ${NODE_CMD}"
28+
exec $NODE_CMD
29+
elif [ ! -n "$NODE_CMD" ] && [ "$INIT_WRAPPER" == true ]; then
30+
31+
package_json_start=$(sed -n 's/\s*"start"\s*:\s*"\(.*\)".*/\1/p' package.json)
32+
package_json_main=$(sed -n 's/\s*"main"\s*:\s*"\(.*\)".*/\1/p' package.json)
33+
34+
if [ -n "$package_json_start" ]; then
35+
start_command=$package_json_start
36+
elif [ -n $package_json_main ]; then
37+
start_command="node ."
38+
elif [ -f "server.js" ]; then
39+
start_command="node server.js"
40+
else
41+
echo "Failed to find file for starting the Node.js application"
42+
exit 1
43+
fi
44+
echo "launching via init wrapper..."
45+
exec ${STI_SCRIPTS_PATH}/init-wrapper $start_command
2346
else
2447
echo "Launching via npm..."
2548
exec npm run -d $NPM_RUN

0 commit comments

Comments
 (0)