|
| 1 | +# Start with the latest version of hardened builder image |
| 2 | +FROM cgr.dev/chainguard/wolfi-base:latest AS builder |
| 3 | + |
| 4 | +# Install required dependencies |
| 5 | +RUN apk add --no-cache bash curl git ca-certificates libstdc++ coreutils && \ |
| 6 | + update-ca-certificates && \ |
| 7 | + touch ~/.bash_profile |
| 8 | + |
| 9 | +# Get desired Node.js version and install it |
| 10 | +COPY .nvmrc /tmp/.nvmrc |
| 11 | +RUN export NODE_VERSION=$(cat /tmp/.nvmrc | tr -d '[:space:]') && \ |
| 12 | + ARCH=$(uname -m) && \ |
| 13 | + echo $ARCH && \ |
| 14 | + case $ARCH in \ |
| 15 | + x86_64) ARCH_NAME="x64";; \ |
| 16 | + aarch64) ARCH_NAME="arm64";; \ |
| 17 | + *) echo "Unsupported architecture: $ARCH" && exit 1;; \ |
| 18 | + esac && \ |
| 19 | + echo "Architecture: $ARCH_NAME" && \ |
| 20 | + PLATFORM_ARCH="linux-${ARCH_NAME}" && \ |
| 21 | + echo "Platform architecture: $PLATFORM_ARCH https://nodejs.org/dist/v${NODE_VERSION}/node-v${NODE_VERSION}-${PLATFORM_ARCH}.tar.gz" && \ |
| 22 | + echo "Installing Node.js version: ${NODE_VERSION} for $ARCH_NAME" && \ |
| 23 | + DOWNLOAD_URL="https://nodejs.org/dist/v${NODE_VERSION}/node-v${NODE_VERSION}-${PLATFORM_ARCH}.tar.gz" && \ |
| 24 | + echo "Downloading from: $DOWNLOAD_URL" && \ |
| 25 | + curl -fsSL --retry 3 "$DOWNLOAD_URL" -o /tmp/node.tar.gz && \ |
| 26 | + tar -xzf /tmp/node.tar.gz -C /usr/local --strip-components=1 && \ |
| 27 | + rm /tmp/node.tar.gz /tmp/.nvmrc && \ |
| 28 | + echo -n "Node.js installed version: " && node -v && \ |
| 29 | + echo -n "npm installed version: " && npm -v && \ |
| 30 | + apk del glibc # Remove glibc package to resolve CVE CVE-2025-0395 |
| 31 | + |
| 32 | + |
| 33 | +# Install yarn and resolve vulnerability in cross-spawn, by upgrading it to a version with resolved CVE |
| 34 | +# Newly found CVEs can be resolved in similar manner - by upgrading to the closest fixed version |
| 35 | +RUN apk add --no-cache yarn && \ |
| 36 | + |
| 37 | +# Extract Node.js version from the image |
| 38 | +SHELL ["/bin/ash", "-o", "pipefail", "-c"] |
| 39 | +RUN node --version | awk -F'v' '{print $2}' |
| 40 | +WORKDIR /app |
| 41 | +# Prep package manager as root and drop privileges |
| 42 | +USER root |
| 43 | +COPY --chown=nonroot . . |
| 44 | +RUN chown nonroot:nonroot ./ && npm install -g corepack |
| 45 | +# Run install/buiuld as unprivileged user |
| 46 | +USER nonroot |
| 47 | +RUN yarn install --immutable && yarn build:production |
| 48 | + |
| 49 | +# Web server stage |
| 50 | +# This image runs as a unprivileged user by default, so there's no need to explicitly set user - see the Note block in the link below for more context |
| 51 | +# https://edu.chainguard.dev/chainguard/chainguard-images/getting-started/nginx/#advanced-usage |
| 52 | +FROM cgr.dev/chainguard/nginx AS server |
| 53 | +COPY nginx.conf /etc/nginx/nginx.conf |
| 54 | +COPY --from=builder /app/build /usr/share/nginx/html |
| 55 | +EXPOSE 8080 |
| 56 | +CMD ["nginx", "-g", "daemon off;"] |
0 commit comments