6

I'm currently trying to install node18 on a amazoncorretto:11 base image. I'm getting the error

#6 11.04 Error: Package: 2:nodejs-18.16.0-1nodesource.x86_64 (nodesource)
#6 11.04            Requires: libc.so.6(GLIBC_2.28)(64bit)
#6 11.04 Error: Package: 2:nodejs-18.16.0-1nodesource.x86_64 (nodesource)
#6 11.04            Requires: libm.so.6(GLIBC_2.27)(64bit)

which is described here: https://github.com/nodesource/distributions/issues/1381

I think I need to update glibc to a version which will support node18, but is this possible on amazonlinux2?

hardillb
  • 1,809
kilseic
  • 61

5 Answers5

5

The answer at:
Node.js 18 is compiled for glibc 2.28
is certainly correct although highly unsatisfying.

You cannot run the binary on your system because it relies on a version of glibc which is not available on your system.

$ docker run -it amazoncorretto:11 bash
bash-4.2# cat /etc/os-release
NAME="Amazon Linux"
VERSION="2"
ID="amzn"
ID_LIKE="centos rhel fedora"
VERSION_ID="2"
PRETTY_NAME="Amazon Linux 2"
ANSI_COLOR="0;33"
CPE_NAME="cpe:2.3:o:amazon:amazon_linux:2"
HOME_URL="https://amazonlinux.com/"
bash-4.2# rpm -q --provides glibc|grep -i libc.so
libc.so.6()(64bit)
libc.so.6(GLIBC_2.10)(64bit)
libc.so.6(GLIBC_2.11)(64bit)
libc.so.6(GLIBC_2.12)(64bit)
libc.so.6(GLIBC_2.13)(64bit)
libc.so.6(GLIBC_2.14)(64bit)
libc.so.6(GLIBC_2.15)(64bit)
libc.so.6(GLIBC_2.16)(64bit)
libc.so.6(GLIBC_2.17)(64bit)
libc.so.6(GLIBC_2.18)(64bit)
libc.so.6(GLIBC_2.2.5)(64bit)
libc.so.6(GLIBC_2.2.6)(64bit)
libc.so.6(GLIBC_2.22)(64bit)
libc.so.6(GLIBC_2.23)(64bit)
libc.so.6(GLIBC_2.24)(64bit)
libc.so.6(GLIBC_2.25)(64bit)
libc.so.6(GLIBC_2.26)(64bit)
libc.so.6(GLIBC_2.3)(64bit)
libc.so.6(GLIBC_2.3.2)(64bit)
libc.so.6(GLIBC_2.3.3)(64bit)
libc.so.6(GLIBC_2.3.4)(64bit)
libc.so.6(GLIBC_2.4)(64bit)
libc.so.6(GLIBC_2.5)(64bit)
libc.so.6(GLIBC_2.6)(64bit)
libc.so.6(GLIBC_2.7)(64bit)
libc.so.6(GLIBC_2.8)(64bit)
libc.so.6(GLIBC_2.9)(64bit)

It supports only up to GLIBC_2.26.

Also amazoncorretto:latest only supports up to glibc 2.26:

$ docker run -it amazoncorretto bash
bash-4.2# cat /etc/os-release
NAME="Amazon Linux"
VERSION="2"
ID="amzn"
ID_LIKE="centos rhel fedora"
VERSION_ID="2"
PRETTY_NAME="Amazon Linux 2"
ANSI_COLOR="0;33"
CPE_NAME="cpe:2.3:o:amazon:amazon_linux:2"
HOME_URL="https://amazonlinux.com/"
bash-4.2# rpm -q --provides glibc|grep -i libc.so
libc.so.6()(64bit)
libc.so.6(GLIBC_2.10)(64bit)
libc.so.6(GLIBC_2.11)(64bit)
libc.so.6(GLIBC_2.12)(64bit)
libc.so.6(GLIBC_2.13)(64bit)
libc.so.6(GLIBC_2.14)(64bit)
libc.so.6(GLIBC_2.15)(64bit)
libc.so.6(GLIBC_2.16)(64bit)
libc.so.6(GLIBC_2.17)(64bit)
libc.so.6(GLIBC_2.18)(64bit)
libc.so.6(GLIBC_2.2.5)(64bit)
libc.so.6(GLIBC_2.2.6)(64bit)
libc.so.6(GLIBC_2.22)(64bit)
libc.so.6(GLIBC_2.23)(64bit)
libc.so.6(GLIBC_2.24)(64bit)
libc.so.6(GLIBC_2.25)(64bit)
libc.so.6(GLIBC_2.26)(64bit)
libc.so.6(GLIBC_2.3)(64bit)
libc.so.6(GLIBC_2.3.2)(64bit)
libc.so.6(GLIBC_2.3.3)(64bit)
libc.so.6(GLIBC_2.3.4)(64bit)
libc.so.6(GLIBC_2.4)(64bit)
libc.so.6(GLIBC_2.5)(64bit)
libc.so.6(GLIBC_2.6)(64bit)
libc.so.6(GLIBC_2.7)(64bit)
libc.so.6(GLIBC_2.8)(64bit)
libc.so.6(GLIBC_2.9)(64bit)

You cannot update your glibc library because it is part of the Linux Kernel. It will be upgraded when you migrate to a newer Operating System Version.

The way to get it running on your system would be to rebuild it from the Source Code for your system and ideally package it for easily reproducible installation.

You might setup a docker image from amazoncorretto Base Image with the Packaging Environment set up.

An Package build on the Packaging Docker Host will be installable on all amazoncorretto:11 Systems.

Useful will be the pre-built .spec file which can be found at:
NodeJS .spec file
Then you only need to build your rpmbuild environment to create your installable NodeJS .rpm package.

AWS NodeJS Lambda Runner:

@Rich mentioned the public.ecr.aws/lambda/nodejs:18 AWS Lambda Runner image.
This is an image which is designed to run NodeJS tasks with the CMD dockerfile instruction at startup.
This actually might be fine for some single shot task (what it is designed for) or to startup directly a ExpressJS web app.
A downside is that you cannot independently update the NodeJS engine without upgrading the whole base image because the NodeJS engine is not installed as a system package.


$ docker run -it public.ecr.aws/lambda/nodejs:18 
19 Jun 2023 09:53:51,148 [INFO] (rapid) exec '/var/runtime/bootstrap' (cwd=/var/task, handler=)

^C19 Jun 2023 09:54:26,776 [INFO] (rapid) Received signal signal=interrupt 19 Jun 2023 09:54:26,776 [INFO] (rapid) Shutting down... 19 Jun 2023 09:54:26,776 [WARNING] (rapid) Reset initiated: SandboxTerminated 19 Jun 2023 09:54:26,776 [INFO] (rapid) Stopping runtime domain 19 Jun 2023 09:54:26,776 [INFO] (rapid) Waiting for runtime domain processes termination 19 Jun 2023 09:54:26,776 [INFO] (rapid) Stopping operator domain 19 Jun 2023 09:54:26,776 [INFO] (rapid) Starting runtime domain

$ docker run --entrypoint bash -it public.ecr.aws/lambda/nodejs:18
bash-4.2# rpm -qa|grep -i node|wc -l
0
bash-4.2# node --version
v18.16.0
bash-4.2# npm --version
9.5.1
bash-4.2# cat /lambda-entrypoint.sh
#!/bin/sh
# Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.

if [ $# -ne 1 ]; then
  echo "entrypoint requires the handler name to be the first argument" 1>&2
  exit 142
fi
export _HANDLER="$1"

RUNTIME_ENTRYPOINT=/var/runtime/bootstrap
if [ -z "${AWS_LAMBDA_RUNTIME_API}" ]; then
  exec /usr/local/bin/aws-lambda-rie $RUNTIME_ENTRYPOINT
else
  exec $RUNTIME_ENTRYPOINT
fi
bash-4.2# ls -lah /usr/local/bin/aws-lambda-rie
-rwxr-xr-x 1 root root 5.6M Jun 12 13:21 /usr/local/bin/aws-lambda-rie
bash-4.2# ls -lah /etc/yum.repos.d
total 12K
drwxr-xr-x 2 root root 4.0K Jun 23  2022 .
drwxr-xr-x 1 root root 4.0K Jun 19 09:57 ..
-rw-r--r-- 1 root root 1003 Oct 26  2021 amzn2-core.repo
4

Building up on the answer by Bodo Hugo Barwich and the comment by Rich:

If you do not want to use the Docker image public.ecr.aws/lambda/nodejs:18 directly, you can copy node from that image to your own image via multi-stage build:

FROM public.ecr.aws/lambda/nodejs:18 as nodesource

FROM amazonlinux:2 ENV PATH="$PATH:/var/lang/bin" COPY --from=nodesource /var/lang /var/lang

RUN npm i whatever

udondan
  • 2,139
4

NodeJS v18 and v20 can be compiled on RHEL7 and Amazon Linux 2 from source using the following script:

#!/bin/bash

install YUM package preques

sudo yum -y update sudo yum groupinstall -y "Development Tools" sudo yum install -y git libffi-devel openssl-devel openssl-devel
dbus-devel p11-kit-devel
python3-devel pip3 rust cargo clang llvm-devel readline-devel
libcurl-devel expat-devel libarchive-devel libpng-devel
libspectre-devel bzip2-devel brotli-devel gperf libjpeg-turbo-devel
openjpeg2-devel libtiff-devel lcms2-devel
gcc10-c++ gcc10-gdb-plugin gcc10-plugin-devel gcc10 gcc10-binutils
gcc10-binutils-devel gcc10-binutils-gold clang-devel clang-tools-extra

Python script helps fetch the most current version of NodeJS v18 or v20

cat << "EOL" > "nodejs_version.py" import sys import re import urllib.request

def usage(): sys.stderr.write(f'usage: {sys.argv[0]} <node-ver: 18 or 20>') sys.exit(1)

def node_version_fetch(url, src_re): with urllib.request.urlopen(url) as response: html = response.read().decode('utf-8') return src_re.search(html)

try: node_ver = sys.argv[1] except (IndexError): usage()

nver_src_mo = node_version_fetch( f'https://nodejs.org/download/release/latest-v{node_ver}.x/', re.compile(f'node-v{node_ver}.(\d+).(\d+).tar.gz', re.M) ) node_full_ver = f'{node_ver}.{nver_src_mo.group(1)}.{nver_src_mo.group(2)}' print(node_full_ver) EOL

fetch most current version of NodeJS

NODE_MAJOR_VERSION=20 NODE_VERSION=$(python3 nodejs_version.py ${NODE_MAJOR_VERSION}) echo "BUILDING NODEJS VERSION=${NODE_VERSION}"

prepare envionment

BUILDDIR=build-v${NODE_VERSION} NODE_DIR=node-v${NODE_VERSION} SOURCE_URL="https://nodejs.org/dist/v${NODE_VERSION}/${NODE_DIR}.tar.gz" PREFIX=/opt/node/${NODE_DIR} NPROC=$(nproc) CC=gcc10-gcc CXX=gcc10-g++ export CC CXX

build, test, install

rm -rf ${BUILDDIR} mkdir -p ${BUILDDIR} pushd ${BUILDDIR} wget "${SOURCE_URL}" tar xf ${NODE_DIR}.tar.gz pushd ${NODE_DIR} ./configure --prefix=${PREFIX} make clean make -j${NPROC} make -j${NPROC} test-only sudo make -j${NPROC} install popd popd

1

You can custom compile on an AL2 instance which will put into the directory from where you downloaded under node/out/Release:

# Needs libfortran
sudo yum-config-manager --add-repo http://mirror.centos.org/centos/7/sclo/x86_64/rh/
wget http://mirror.centos.org/centos/7/os/x86_64/Packages/libgfortran5-8.3.1-2.1.1.el7.x86_64.rpm
sudo yum install libgfortran5-8.3.1-2.1.1.el7.x86_64.rpm -y

Requires gcc and g++ 8.3 or greater

sudo yum install -y devtoolset-8 --nogpgcheck scl enable devtoolset-8 bash

cd ~/ git clone git@github.com:nodejs/node.git git checkout tags/v18.18.0 ./configure

Skip cctest as it fails on AL2

make -C out node BUILDTYPE=Release -j4

If you want to also fix when using nvm...

nvm install v18.18.0
cd ~/.nvm/versions/node/v18.18.0/bin/
mv node node-GLIBC_2.27
ln -s ~/node/out/Release/node node 
nvm alias default v18.18.0

Also found that you can alternatively skip devtools-8 if you install gcc10 and use that before the configure:

sudo yum install gcc10-c++ libgfortran10
CC=gcc10-cc CXX=gcc10-c++ ./configure
1

Multiple AWS teams have compiled binaries for NodeJS v18.x for Amazon Linux 2. You can find them in the CloudWatch logs related to ElasticBeanstalk and Cloud9 resources.

Borrowing the binary from the Cloud9 team, you can install the NodeJS version on your Amazon Linux 2 based host.

wget -nv https://d3rnber7ry90et.cloudfront.net/linux-x86_64/node-v18.17.1.tar.gz
mkdir /usr/local/lib/node
tar -xf node-v18.17.1.tar.gz
mv node-v18.17.1 /usr/local/lib/node/nodejs
### Unload NVM, use the new node in the path, then install some items globally.
echo "export NVM_DIR=''" >> /home/ec2-user/.bashrc
echo "export NODEJS_HOME=/usr/local/lib/node/nodejs" >> /home/ec2-user/.bashrc
echo "export PATH=\$NODEJS_HOME/bin:\$PATH" >> /home/ec2-user/.bashrc
### Reload environment
. /home/ec2-user/.bashrc
### Verify NodeJS v18.x is operating
node -e "console.log('Running Node.js ' + process.version)"