Repository: GoogleContainerTools/distroless
Pull request #1794: Add node24
Author: login: omBratteng
Created: 2025-05-08T09:07:49Z | Merged: 2025-05-08T17:33:14Z

Nodejs 24 was released on Tuesday, and is the next LTS version


Diff:
diff --git a/BUILD b/BUILD
index 4c4f2544b..cb0d53676 100644
--- a/BUILD
+++ b/BUILD
@@ -1,6 +1,7 @@
 load("//:checksums.bzl", "ARCHITECTURES", "BASE_ARCHITECTURES")
 load("//base:distro.bzl", "DISTROS")
 load("//private/oci:defs.bzl", "sign_and_push_all")
+load("//nodejs:node_arch.bzl", "node_arch")
 
 package(default_visibility = ["//visibility:public"])
 
@@ -179,6 +180,7 @@ PYTHON3 |= {
 NODEJS_VERSIONS = [
     "20",
     "22",
+    "24",
 ]
 
 NODEJS_VARIATIONS = [
@@ -190,9 +192,9 @@ NODEJS_VARIATIONS = [
 
 NODEJS = {
     "{REGISTRY}/{PROJECT_ID}/nodejs" + version + "-" + distro + ":" + tag_base + "-" + arch: "//nodejs:nodejs" + version + label + "_" + user + "_" + arch + "_" + distro
-    for arch in ARCHITECTURES
-    for distro in DISTROS
     for version in NODEJS_VERSIONS
+    for arch in node_arch(version)
+    for distro in DISTROS
     for (tag_base, label, user) in NODEJS_VARIATIONS
 }
 
@@ -206,8 +208,8 @@ NODEJS |= {
 
 NODEJS |= {
     "{REGISTRY}/{PROJECT_ID}/nodejs" + version + ":" + tag_base + "-" + arch: "//nodejs:nodejs" + version + label + "_" + user + "_" + arch + "_" + DEFAULT_DISTRO
-    for arch in ARCHITECTURES
     for version in NODEJS_VERSIONS
+    for arch in node_arch(version)
     for (tag_base, label, user) in NODEJS_VARIATIONS
 }
 
diff --git a/MODULE.bazel b/MODULE.bazel
index 6cf4c1afe..846364e50 100644
--- a/MODULE.bazel
+++ b/MODULE.bazel
@@ -58,7 +58,7 @@ include("//private/repos:java.MODULE.bazel")
 ### NODE ###
 node = use_extension("//private/extensions:node.bzl", "node")
 node.archive()
-use_repo(node, "nodejs20_amd64", "nodejs20_arm", "nodejs20_arm64", "nodejs20_ppc64le", "nodejs20_s390x", "nodejs22_amd64", "nodejs22_arm", "nodejs22_arm64", "nodejs22_ppc64le", "nodejs22_s390x")
+use_repo(node, "nodejs20_amd64", "nodejs20_arm", "nodejs20_arm64", "nodejs20_ppc64le", "nodejs20_s390x", "nodejs22_amd64", "nodejs22_arm", "nodejs22_arm64", "nodejs22_ppc64le", "nodejs22_s390x", "nodejs24_amd64", "nodejs24_arm64", "nodejs24_ppc64le", "nodejs24_s390x")
 
 ### DEBIAN ###
 include("//private/repos/deb:deb.MODULE.bazel")
diff --git a/MODULE.bazel.lock b/MODULE.bazel.lock
index 33f8ea0ff..2361b76c9 100644
--- a/MODULE.bazel.lock
+++ b/MODULE.bazel.lock
@@ -373,7 +373,7 @@
     },
     "//private/extensions:node.bzl%node": {
       "general": {
-        "bzlTransitiveDigest": "AIJARq6qX9w6hU8hd+3SsL+gPw2uGb9OEIYfh3TY6eE=",
+        "bzlTransitiveDigest": "EDX+FIkJQvb/qPSYS8tNnYCl3QPlqhK4ejSeJFVujj4=",
         "usagesDigest": "oo4hnOxowfXXa21Wd8roJmpRdyG7Fy97FBO9vJoyK/M=",
         "recordedFileInputs": {},
         "recordedDirentsInputs": {},
@@ -518,6 +518,62 @@
               "architecture": "s390x",
               "control": "@@//nodejs:control"
             }
+          },
+          "nodejs24_amd64": {
+            "bzlFile": "@@//private/extensions:node.bzl",
+            "ruleClassName": "node_archive",
+            "attributes": {
+              "sha256": "b760ed6de40c35a25eb011b3cf5943d35d7a76f0c8c331d5a801e10925826cb3",
+              "strip_prefix": "node-v24.0.0-linux-x64/",
+              "urls": [
+                "https://nodejs.org/dist/v24.0.0/node-v24.0.0-linux-x64.tar.gz"
+              ],
+              "version": "24.0.0",
+              "architecture": "amd64",
+              "control": "@@//nodejs:control"
+            }
+          },
+          "nodejs24_arm64": {
+            "bzlFile": "@@//private/extensions:node.bzl",
+            "ruleClassName": "node_archive",
+            "attributes": {
+              "sha256": "4104136ddd3d2f167d799f1b21bac72ccf500d80c24be849195f831df6371b83",
+              "strip_prefix": "node-v24.0.0-linux-arm64/",
+              "urls": [
+                "https://nodejs.org/dist/v24.0.0/node-v24.0.0-linux-arm64.tar.gz"
+              ],
+              "version": "24.0.0",
+              "architecture": "arm64",
+              "control": "@@//nodejs:control"
+            }
+          },
+          "nodejs24_ppc64le": {
+            "bzlFile": "@@//private/extensions:node.bzl",
+            "ruleClassName": "node_archive",
+            "attributes": {
+              "sha256": "04654c22d8f9fc3021a27f37a95c16f820870908a49cd361f4cf74ed14509a10",
+              "strip_prefix": "node-v24.0.0-linux-ppc64le/",
+              "urls": [
+                "https://nodejs.org/dist/v24.0.0/node-v24.0.0-linux-ppc64le.tar.gz"
+              ],
+              "version": "24.0.0",
+              "architecture": "ppc64le",
+              "control": "@@//nodejs:control"
+            }
+          },
+          "nodejs24_s390x": {
+            "bzlFile": "@@//private/extensions:node.bzl",
+            "ruleClassName": "node_archive",
+            "attributes": {
+              "sha256": "aa6fa7c5dc7d699116a39a781eb1685a68e3843d2d95bcd98527fd28922de63a",
+              "strip_prefix": "node-v24.0.0-linux-s390x/",
+              "urls": [
+                "https://nodejs.org/dist/v24.0.0/node-v24.0.0-linux-s390x.tar.gz"
+              ],
+              "version": "24.0.0",
+              "architecture": "s390x",
+              "control": "@@//nodejs:control"
+            }
           }
         },
         "moduleExtensionMetadata": {
@@ -531,7 +587,11 @@
             "nodejs22_arm64",
             "nodejs22_arm",
             "nodejs22_ppc64le",
-            "nodejs22_s390x"
+            "nodejs22_s390x",
+            "nodejs24_amd64",
+            "nodejs24_arm64",
+            "nodejs24_ppc64le",
+            "nodejs24_s390x"
           ],
           "explicitRootModuleDirectDevDeps": [],
           "useAllRepos": "NO",
diff --git a/README.md b/README.md
index ddca3b3ce..499a23b9f 100644
--- a/README.md
+++ b/README.md
@@ -42,6 +42,7 @@ The following images are currently published and updated by the distroless proje
 | gcr.io/distroless/java21-debian12     | latest, nonroot, debug, debug-nonroot | amd64, arm64, ppc64le             |
 | gcr.io/distroless/nodejs20-debian12   | latest, nonroot, debug, debug-nonroot | amd64, arm64, arm, s390x, ppc64le |
 | gcr.io/distroless/nodejs22-debian12   | latest, nonroot, debug, debug-nonroot | amd64, arm64, arm, s390x, ppc64le |
+| gcr.io/distroless/nodejs24-debian12   | latest, nonroot, debug, debug-nonroot | amd64, arm64, s390x, ppc64le |
 
 These images refer to image indexes with references to all supported architectures. Architecture specific images can be directly referenced using an additional architecture suffix on the tag, like `gcr.io/distroless/static-debian12:latest-amd64`
 
diff --git a/SUPPORT_POLICY.md b/SUPPORT_POLICY.md
index bde6014a1..4daa1195f 100644
--- a/SUPPORT_POLICY.md
+++ b/SUPPORT_POLICY.md
@@ -21,7 +21,7 @@ The current estimation of end of life for images with the pattern:
 Java will only support current LTS version distributed by debian [see here](https://wiki.debian.org/Java).
 
 ### Node
-Node version support is for even numbered releases (20, 22, etc) that are current, active or in LTS maintenance. For more information, [see here](https://nodejs.org/en/about/previous-releases#release-schedule).
+Node version support is for even numbered releases (20, 22, 24, etc) that are current, active or in LTS maintenance. For more information, [see here](https://nodejs.org/en/about/previous-releases#release-schedule).
 
 ### Images no longer supported (TBD)
 A list of supported image tags is available here: https://github.com/GoogleContainerTools/distroless#what-images-are-available
diff --git a/nodejs/BUILD b/nodejs/BUILD
index d829c60cf..72ffc1f50 100644
--- a/nodejs/BUILD
+++ b/nodejs/BUILD
@@ -1,12 +1,12 @@
 load("@container_structure_test//:defs.bzl", "container_structure_test")
 load("@rules_oci//oci:defs.bzl", "oci_image", "oci_image_index")
 load("@rules_pkg//:pkg.bzl", "pkg_tar")
-load("//:checksums.bzl", "ARCHITECTURES")
 load("//base:distro.bzl", "DISTROS")
+load("//nodejs:node_arch.bzl", "node_arch")
 
 package(default_visibility = ["//visibility:public"])
 
-NODEJS_MAJOR_VERISONS = ("20", "22")
+NODEJS_MAJOR_VERISONS = ("20", "22", "24")
 
 MODE = [
     "",
@@ -23,7 +23,7 @@ USER = [
         name = "nodejs" + major_version + ("" if (not mode) else mode) + "_" + user + "_" + distro,
         images = [
             "nodejs" + major_version + ("" if (not mode) else mode) + "_" + user + "_" + arch + "_" + distro
-            for arch in ARCHITECTURES
+            for arch in node_arch(major_version)
         ],
     )
     for mode in MODE
@@ -44,7 +44,7 @@ USER = [
     for mode in MODE
     for user in USER
     for major_version in NODEJS_MAJOR_VERISONS
-    for arch in ARCHITECTURES
+    for arch in node_arch(major_version)
     for distro in DISTROS
 ]
 
@@ -65,7 +65,7 @@ USER = [
     for mode in MODE
     for user in USER
     for major_version in NODEJS_MAJOR_VERISONS
-    for arch in ARCHITECTURES
+    for arch in node_arch(major_version)
     for distro in DISTROS
 ]
 
@@ -85,7 +85,7 @@ pkg_tar(
     for mode in MODE
     for user in USER
     for major_version in NODEJS_MAJOR_VERISONS
-    for arch in ARCHITECTURES
+    for arch in node_arch(major_version)
     for distro in DISTROS
 ]
 
@@ -102,6 +102,6 @@ pkg_tar(
     for mode in MODE
     for user in USER
     for major_version in NODEJS_MAJOR_VERISONS
-    for arch in ARCHITECTURES
+    for arch in node_arch(major_version)
     for distro in DISTROS
 ]
diff --git a/nodejs/README.md b/nodejs/README.md
index 5f0c4cbc8..c4c8a823b 100644
--- a/nodejs/README.md
+++ b/nodejs/README.md
@@ -8,6 +8,7 @@ Specifically, these images contain everything in the [base image](../base/README
 
 - Node.js v20 (`gcr.io/distroless/nodejs20-debian12`) and its dependencies.
 - Node.js v22 (`gcr.io/distroless/nodejs22-debian12`) and its dependencies.
+- Node.js v24 (`gcr.io/distroless/nodejs24-debian12`) and its dependencies.
 
 ## Usage
 
diff --git a/nodejs/node_arch.bzl b/nodejs/node_arch.bzl
new file mode 100644
index 000000000..6102a80a8
--- /dev/null
+++ b/nodejs/node_arch.bzl
@@ -0,0 +1,7 @@
+load("//:checksums.bzl", "ARCHITECTURES")
+
+# Function to filter architectures based on Node.js version
+def node_arch(major_version):
+    if int(major_version) >= 24:
+        return [arch for arch in ARCHITECTURES if arch != "arm"]
+    return ARCHITECTURES
diff --git a/nodejs/testdata/nodejs24.yaml b/nodejs/testdata/nodejs24.yaml
new file mode 100644
index 000000000..beb56e24f
--- /dev/null
+++ b/nodejs/testdata/nodejs24.yaml
@@ -0,0 +1,6 @@
+schemaVersion: "2.0.0"
+commandTests:
+  - name: nodejs
+    command: "/nodejs/bin/node"
+    args: ["--version"]
+    expectedOutput: ["v24.0.0"]
diff --git a/private/extensions/node.bzl b/private/extensions/node.bzl
index 072e89dba..423f3b0ac 100644
--- a/private/extensions/node.bzl
+++ b/private/extensions/node.bzl
@@ -197,6 +197,46 @@ def _node_impl(module_ctx):
         control = "//nodejs:control",
     )
 
+    node_archive(
+        name = "nodejs24_amd64",
+        sha256 = "b760ed6de40c35a25eb011b3cf5943d35d7a76f0c8c331d5a801e10925826cb3",
+        strip_prefix = "node-v24.0.0-linux-x64/",
+        urls = ["https://nodejs.org/dist/v24.0.0/node-v24.0.0-linux-x64.tar.gz"],
+        version = "24.0.0",
+        architecture = "amd64",
+        control = "//nodejs:control",
+    )
+
+    node_archive(
+        name = "nodejs24_arm64",
+        sha256 = "4104136ddd3d2f167d799f1b21bac72ccf500d80c24be849195f831df6371b83",
+        strip_prefix = "node-v24.0.0-linux-arm64/",
+        urls = ["https://nodejs.org/dist/v24.0.0/node-v24.0.0-linux-arm64.tar.gz"],
+        version = "24.0.0",
+        architecture = "arm64",
+        control = "//nodejs:control",
+    )
+
+    node_archive(
+        name = "nodejs24_ppc64le",
+        sha256 = "04654c22d8f9fc3021a27f37a95c16f820870908a49cd361f4cf74ed14509a10",
+        strip_prefix = "node-v24.0.0-linux-ppc64le/",
+        urls = ["https://nodejs.org/dist/v24.0.0/node-v24.0.0-linux-ppc64le.tar.gz"],
+        version = "24.0.0",
+        architecture = "ppc64le",
+        control = "//nodejs:control",
+    )
+
+    node_archive(
+        name = "nodejs24_s390x",
+        sha256 = "aa6fa7c5dc7d699116a39a781eb1685a68e3843d2d95bcd98527fd28922de63a",
+        strip_prefix = "node-v24.0.0-linux-s390x/",
+        urls = ["https://nodejs.org/dist/v24.0.0/node-v24.0.0-linux-s390x.tar.gz"],
+        version = "24.0.0",
+        architecture = "s390x",
+        control = "//nodejs:control",
+    )
+
     return module_ctx.extension_metadata(
         root_module_direct_deps = [
             "nodejs20_amd64",
@@ -209,6 +249,10 @@ def _node_impl(module_ctx):
             "nodejs22_arm",
             "nodejs22_ppc64le",
             "nodejs22_s390x",
+            "nodejs24_amd64",
+            "nodejs24_arm64",
+            "nodejs24_ppc64le",
+            "nodejs24_s390x",
         ],
         root_module_direct_dev_deps = [],
     )


Reviews:
user: login: loosebazooka
state: APPROVED
author_association: MEMBER
submitted_at: 2025-05-08T11:18:39Z
user: login: loosebazooka
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-05-08T15:12:11Z
user: login: omBratteng
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-05-08T15:14:43Z
user: login: slagiewka
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-08T16:12:14Z
user: login: slagiewka
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-08T16:41:15Z
user: login: loosebazooka
state: APPROVED
author_association: MEMBER
submitted_at: 2025-05-08T17:33:08Z

Review comments:
diff_hunk: @@ -179,6 +179,7 @@ PYTHON3 |= {
 NODEJS_VERSIONS = [
     "20",
     "22",
+    "24",
path: BUILD
user: login: loosebazooka
body: I thin you might still need to handle this section: https://github.com/GoogleContainerTools/distroless/blob/main/BUILD#L191-L219 for architectures using node_arch.bzl
created_at: 2025-05-08T15:12:11Z
author_association: MEMBER
diff_hunk: @@ -179,6 +179,7 @@ PYTHON3 |= {
 NODEJS_VERSIONS = [
     "20",
     "22",
+    "24",
path: BUILD
user: login: omBratteng
body: Added it as well
created_at: 2025-05-08T15:14:43Z
author_association: COLLABORATOR
diff_hunk: @@ -190,7 +192,7 @@ NODEJS_VARIATIONS = [
 
 NODEJS = {
     "{REGISTRY}/{PROJECT_ID}/nodejs" + version + "-" + distro + ":" + tag_base + "-" + arch: "//nodejs:nodejs" + version + label + "_" + user + "_" + arch + "_" + distro
-    for arch in ARCHITECTURES
+    for arch in node_arch(version)
     for distro in DISTROS
     for version in NODEJS_VERSIONS
path: BUILD
user: login: slagiewka
body: Likely this should do it:
```suggestion
    for version in NODEJS_VERSIONS
    for arch in node_arch(version)
    for distro in DISTROS
```
created_at: 2025-05-08T16:12:14Z
author_association: CONTRIBUTOR
diff_hunk: @@ -206,7 +208,7 @@ NODEJS |= {
 
 NODEJS |= {
     "{REGISTRY}/{PROJECT_ID}/nodejs" + version + ":" + tag_base + "-" + arch: "//nodejs:nodejs" + version + label + "_" + user + "_" + arch + "_" + DEFAULT_DISTRO
-    for arch in ARCHITECTURES
+    for arch in node_arch(version)
     for version in NODEJS_VERSIONS
path: BUILD
user: login: slagiewka
body: One more here:
```suggestion
    for version in NODEJS_VERSIONS
    for arch in node_arch(version)
```

PS. Signed the CLA since it's needed from me 😉 
created_at: 2025-05-08T16:41:15Z
author_association: CONTRIBUTOR

PR comments:
user: login: omBratteng
created_at: 2025-05-08T11:28:17Z
body: Should be good now. Forgot that Nodejs v24 dropped support for armv7
author_association: COLLABORATOR
user: login: loosebazooka
created_at: 2025-05-08T15:09:46Z
body: > Forgot that Nodejs v24 dropped support for armv7

forever?
author_association: MEMBER
user: login: omBratteng
created_at: 2025-05-08T15:12:38Z
body: > > Forgot that Nodejs v24 dropped support for armv7
> 
> forever?

Yeah, appears so. They downgraded armv7 to experimental because of issues with V8
https://github.com/nodejs/node/pull/58071
author_association: COLLABORATOR
user: login: omBratteng
created_at: 2025-05-08T16:58:09Z
body: Thanks @slagiewka, passes now
author_association: COLLABORATOR