Skip to content

Docker images build on node:20-alpine, which is EOL and no longer receives rebuilds #1110

Description

@jochristian

All published images build on node:20-alpine:

file line
server/Dockerfile 3 (builder), 33 (runtime)
client/Dockerfile 1 (base, inherited by deps/builder/runner)
monitor-agent/Dockerfile 1

Node.js 20 reached end-of-life at the end of April 2026, and the Docker Hub tag reflects that — it has not been rebuilt in nearly four months:

tag last pushed
node:20-alpine 2026-04-15
node:22-alpine 2026-07-29
node:24-alpine 2026-08-03

(Checked 2026-08-11. The 20-alpine image currently contains Node v20.20.2 on Alpine 3.23.4.)

Why this matters beyond the version number

Because the tag is frozen, rebuilding the images cannot pick up fixes for anything already in that layer — the Node runtime and its bundled OpenSSL included. docker build --pull fetches the same April image every time.

That specifically penalises self-hosters who rebuild on a schedule to stay patched. We rebuilt v2.8.0 from source on 2026-08-11 — two weeks after the published image was built — and Trivy reported identical results:

image published ghcr.io rebuilt from the same tag
rybbit-backend:v2.8.0 107 fixed HIGH/CRITICAL 107
rybbit-client:v2.8.0 25 fixed HIGH/CRITICAL 25

Same CVEs, same packages. Reproducible with:

trivy image --scanners vuln --ignore-unfixed --severity HIGH,CRITICAL \
  ghcr.io/rybbit-io/rybbit-backend:v2.8.0

Two of those findings are libcrypto3/libssl3 at 3.5.6-r0 (CVE-2026-45447, OpenSSL heap use-after-free in PKCS7_verify(), fixed in 3.5.7-r0) — inherited directly from the frozen base and unreachable by a rebuild. Moving to a maintained base tag resolves those on the next build.

Compatibility looks straightforward

  • No package.json in the repo declares an engines constraint, so nothing pins Node 20 explicitly.
  • next@16.2.6 requires node >=20.9.0 — an open lower bound. Node 22 and 24 both satisfy it.
  • fastify@5.8.5, react@19.2.4 and drizzle-orm@0.45.2 all support Node 22 and 24.
  • The only workflows referencing node-version: 20 are translate.yml and translate-docs.yml (docs translation), not application build or test — so CI coupling to Node 20 looks minimal.

Suggested fix

Bump the four FROM lines to node:22-alpine (Active LTS through April 2027) or node:24-alpine. Worth bumping @types/node alongside — it is pinned at ^20.14.8 in both server/package.json and client/package.json.

Happy to open the PR if that would help; it seemed better to check which major you would prefer before sending one.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions