Repository: nodejs/docker-node Branch: main Commit: 7c04ffca981b Files: 101 Total size: 240.2 KB Directory structure: gitextract__dann8y5/ ├── .editorconfig ├── .gitattributes ├── .github/ │ ├── ISSUE_TEMPLATE/ │ │ ├── 1-bug-report.md │ │ ├── 2-feature-request.md │ │ └── config.yml │ ├── PULL_REQUEST_TEMPLATE.md │ ├── dependabot.yml │ └── workflows/ │ ├── automatic-updates.yml │ ├── build-test.yml │ ├── doctoc.yml │ ├── eclint.yml │ ├── markdown-link-check.yml │ ├── missing-checksum.yml │ ├── official-pr.yml │ ├── scorecard.yml │ └── shfmt.yml ├── 20/ │ ├── alpine3.22/ │ │ ├── Dockerfile │ │ └── docker-entrypoint.sh │ ├── alpine3.23/ │ │ ├── Dockerfile │ │ └── docker-entrypoint.sh │ ├── bookworm/ │ │ ├── Dockerfile │ │ └── docker-entrypoint.sh │ ├── bookworm-slim/ │ │ ├── Dockerfile │ │ └── docker-entrypoint.sh │ ├── bullseye/ │ │ ├── Dockerfile │ │ └── docker-entrypoint.sh │ ├── bullseye-slim/ │ │ ├── Dockerfile │ │ └── docker-entrypoint.sh │ ├── trixie/ │ │ ├── Dockerfile │ │ └── docker-entrypoint.sh │ └── trixie-slim/ │ ├── Dockerfile │ └── docker-entrypoint.sh ├── 22/ │ ├── alpine3.22/ │ │ ├── Dockerfile │ │ └── docker-entrypoint.sh │ ├── alpine3.23/ │ │ ├── Dockerfile │ │ └── docker-entrypoint.sh │ ├── bookworm/ │ │ ├── Dockerfile │ │ └── docker-entrypoint.sh │ ├── bookworm-slim/ │ │ ├── Dockerfile │ │ └── docker-entrypoint.sh │ ├── bullseye/ │ │ ├── Dockerfile │ │ └── docker-entrypoint.sh │ ├── bullseye-slim/ │ │ ├── Dockerfile │ │ └── docker-entrypoint.sh │ ├── trixie/ │ │ ├── Dockerfile │ │ └── docker-entrypoint.sh │ └── trixie-slim/ │ ├── Dockerfile │ └── docker-entrypoint.sh ├── 24/ │ ├── alpine3.22/ │ │ ├── Dockerfile │ │ └── docker-entrypoint.sh │ ├── alpine3.23/ │ │ ├── Dockerfile │ │ └── docker-entrypoint.sh │ ├── bookworm/ │ │ ├── Dockerfile │ │ └── docker-entrypoint.sh │ ├── bookworm-slim/ │ │ ├── Dockerfile │ │ └── docker-entrypoint.sh │ ├── bullseye/ │ │ ├── Dockerfile │ │ └── docker-entrypoint.sh │ ├── bullseye-slim/ │ │ ├── Dockerfile │ │ └── docker-entrypoint.sh │ ├── trixie/ │ │ ├── Dockerfile │ │ └── docker-entrypoint.sh │ └── trixie-slim/ │ ├── Dockerfile │ └── docker-entrypoint.sh ├── 25/ │ ├── alpine3.22/ │ │ ├── Dockerfile │ │ └── docker-entrypoint.sh │ ├── alpine3.23/ │ │ ├── Dockerfile │ │ └── docker-entrypoint.sh │ ├── bookworm/ │ │ ├── Dockerfile │ │ └── docker-entrypoint.sh │ ├── bookworm-slim/ │ │ ├── Dockerfile │ │ └── docker-entrypoint.sh │ ├── bullseye/ │ │ ├── Dockerfile │ │ └── docker-entrypoint.sh │ ├── bullseye-slim/ │ │ ├── Dockerfile │ │ └── docker-entrypoint.sh │ ├── trixie/ │ │ ├── Dockerfile │ │ └── docker-entrypoint.sh │ └── trixie-slim/ │ ├── Dockerfile │ └── docker-entrypoint.sh ├── CONTRIBUTING.md ├── Dockerfile-alpine.template ├── Dockerfile-debian.template ├── Dockerfile-slim.template ├── GOVERNANCE.md ├── LICENSE ├── README.md ├── SECURITY.md ├── architectures ├── build-automation.mjs ├── config ├── docker-entrypoint.sh ├── docs/ │ └── BestPractices.md ├── functions.sh ├── genMatrix.js ├── keys/ │ └── node.keys ├── markdown_link_check_config.json ├── stackbrew.js ├── update-keys.sh ├── update.sh └── versions.json ================================================ FILE CONTENTS ================================================ ================================================ FILE: .editorconfig ================================================ root = true [*] charset = utf-8 end_of_line = lf indent_size = 2 indent_style = space insert_final_newline = true trim_trailing_whitespace = true ================================================ FILE: .gitattributes ================================================ * text=auto eol=lf /Dockerfile*.template linguist-language=Dockerfile ================================================ FILE: .github/ISSUE_TEMPLATE/1-bug-report.md ================================================ --- name: "\U0001F41B Bug Report" about: Create a bug report to help us improve --- ## Environment * **Platform**: * **Docker Version**: * **Node.js Version**: * **Image Tag**: ## Expected Behavior ## Current Behavior ## Possible Solution ## Steps to Reproduce ## Additional Information ================================================ FILE: .github/ISSUE_TEMPLATE/2-feature-request.md ================================================ --- name: "\U0001F680 Feature Request" about: Suggest an idea for this project --- ## Problem ## Solution ## Alternatives to Consider ================================================ FILE: .github/ISSUE_TEMPLATE/config.yml ================================================ blank_issues_enabled: false contact_links: - name: Need help with Node.js? url: https://github.com/nodejs/help about: Please file an issue in our help repo. - name: Found a problem with Node.js beyond the API reference documentation? url: https://github.com/nodejs/nodejs.org/issues/new/choose about: Please file an issue in the Node.js website repository. - name: Want to report security issues or vulnerabilites? url: https://github.com/nodejs/docker-node/security/policy about: Please go through our policy for reporting CVEs and security issues. - name: Need help with common questions related to using Node.js with Docker? url: https://stackoverflow.com/questions/tagged/node.js%2bdocker%2bdockerfile about: Please visit Stack Overflow to explore related questions and answers. ================================================ FILE: .github/PULL_REQUEST_TEMPLATE.md ================================================ ## Description ## Motivation and Context ## Testing Details ## Example Output(if appropriate) ## Types of changes - [ ] Documentation - [ ] Version change (Update, remove or add more Node.js versions) - [ ] Variant change (Update, remove or add more variants, or versions of variants) - [ ] Bug fix (non-breaking change which fixes an issue) - [ ] New feature (non-breaking change which adds functionality) - [ ] Breaking change (fix or feature that would cause existing functionality to change) - [ ] Other (none of the above) ## Checklist - [ ] My code follows the code style of this project. - [ ] My change requires a change to the documentation. - [ ] I have updated the documentation accordingly. - [ ] I have read the **CONTRIBUTING.md** document. - [ ] All new and existing tests passed. ================================================ FILE: .github/dependabot.yml ================================================ version: 2 updates: - package-ecosystem: github-actions directory: "/" schedule: interval: daily open-pull-requests-limit: 10 ================================================ FILE: .github/workflows/automatic-updates.yml ================================================ name: Automatically update Docker image versions on: schedule: - cron: "*/15 * * * *" jobs: build: runs-on: ubuntu-latest if: github.repository_owner == 'nodejs' permissions: pull-requests: write steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Run automation script uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 id: updt with: result-encoding: string script: | const { default: script } = await import(`${process.env.GITHUB_WORKSPACE}/build-automation.mjs`); return script(github); - name: Create update PR id: cpr uses: peter-evans/create-pull-request@c0f553fe549906ede9cf27b5156039d195d2ece0 # v8.1.0 with: token: ${{ secrets.GH_API_TOKEN }} author: "Node.js GitHub Bot " branch: update-branch base: main commit-message: "feat: Node.js ${{ steps.updt.outputs.result }}" title: "feat: Node.js ${{ steps.updt.outputs.result }}" delete-branch: true team-reviewers: | nodejs/docker ================================================ FILE: .github/workflows/build-test.yml ================================================ name: build-test on: push: paths: - "**/Dockerfile" - "**/docker-entrypoint.sh" - genMatrix.js - ".github/workflows/build-test.yml" pull_request: paths: - "**/Dockerfile" - "**/docker-entrypoint.sh" - genMatrix.js - ".github/workflows/build-test.yml" jobs: gen-matrix: name: generate-matrix runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Calculate file differences id: diff uses: tj-actions/changed-files@22103cc46bda19c2b464ffe86db46df6922fd323 # v47.0.5 with: json: true escape_json: false - name: Generate testing matrix uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 id: generator with: github-token: ${{ secrets.GITHUB_TOKEN }} script: | const script = require(`${process.env.GITHUB_WORKSPACE}/genMatrix.js`) return script( ${{ steps.diff.outputs.added_files }}, ${{ steps.diff.outputs.modified_files }}, ${{ steps.diff.outputs.renamed_files }}, ); outputs: matrix: ${{ steps.generator.outputs.result }} build: if: ${{ fromJson(needs.gen-matrix.outputs.matrix) }} needs: gen-matrix name: build runs-on: ubuntu-latest timeout-minutes: 60 strategy: fail-fast: false matrix: ${{ fromJson(needs.gen-matrix.outputs.matrix) }} steps: - name: Get short node version uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 id: short-version with: result-encoding: string script: return "${{ matrix.version }}".split('.')[0] - name: Checkout uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Build image uses: docker/build-push-action@d08e5c354a6adb9ed34480a06d141179aa583294 # v7.0.0 with: push: false load: true context: . file: ./${{ steps.short-version.outputs.result }}/${{ matrix.variant }}/Dockerfile tags: node:${{ matrix.version }}-${{ matrix.variant }} - name: Test for node version run: | image_node_version=$(docker run --rm node:${{ matrix.version }}-${{ matrix.variant }} node --print "process.versions.node") echo "Expected: \"${{ matrix.version }}\", Got: \"${image_node_version}\"" [ "${image_node_version}" == "${{ matrix.version }}" ] - name: Verify entrypoint runs regular, non-executable files with node run: | tmp_file=$(mktemp) echo 'console.log("success")' > "${tmp_file}" output=$(docker run --rm -v "${tmp_file}:/app/index.js" node:${{ matrix.version }}-${{ matrix.variant }} app/index.js) [ "${output}" = 'success' ] - name: Test for npm run: docker run --rm node:${{ matrix.version }}-${{ matrix.variant }} npm --version - name: Test for yarn run: docker run --rm node:${{ matrix.version }}-${{ matrix.variant }} yarn --version ================================================ FILE: .github/workflows/doctoc.yml ================================================ name: Check generated TOCs on: pull_request: paths: - "README.md" - "docs/BestPractices.md" permissions: contents: read jobs: doctoc: name: Doc TOC Check runs-on: ubuntu-latest steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0 with: node-version: 'lts/*' - name: Install doctoc run: npm i -g doctoc - name: Create README copy and diff with doctoc run: cp README.md README.md.tmp && doctoc --title='## Table of Contents' --github README.md && diff -q README.md README.md.tmp - name: Create "docs/BestPractices.md" copy and diff with doctoc run: cp docs/BestPractices.md docs/BestPractices.md.tmp && doctoc --title='## Table of Contents' --github docs/BestPractices.md && diff -q docs/BestPractices.md docs/BestPractices.md.tmp ================================================ FILE: .github/workflows/eclint.yml ================================================ name: Test Whitespace and line endings on: [pull_request] permissions: contents: read jobs: eclint: runs-on: ubuntu-latest steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0 with: node-version: 'lts/*' - run: npm i -g eclint - run: eclint check ================================================ FILE: .github/workflows/markdown-link-check.yml ================================================ name: Check Markdown links on: pull_request: paths: - "**/*.md" - "markdown_link_check_config.json" permissions: contents: read jobs: markdown-link-check: runs-on: ubuntu-latest steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0 with: node-version: 'lts/*' - name: Install markdown-link-check run: npm i -g markdown-link-check@3.14.1 - name: Run markdown-link-check on MD files run: find . -name "*.md" | xargs -n 1 markdown-link-check -c markdown_link_check_config.json -q ================================================ FILE: .github/workflows/missing-checksum.yml ================================================ name: Check Alpine CHECKSUM on: pull_request: paths: - ".github/workflows/missing-checksum.yml" - "**/alpine*/Dockerfile" permissions: contents: read jobs: test: runs-on: ubuntu-latest steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Count number of Alpine Dockersfiles without CHECKSUM run: | git grep -n 'CHECKSUM=""' -- '*alpine*/Dockerfile' | sed -E 's/^([^:]+):([^:]+):\s*/::error file=\1,line=\2::Missing pre-built checksum/' if [ "${PIPESTATUS[0]}" -eq 0 ]; then exit 1 fi ================================================ FILE: .github/workflows/official-pr.yml ================================================ name: Create official images PR on: pull_request_target: types: - closed paths: - ".github/workflows/official-pr.yml" - "**/Dockerfile" - "**/docker-entrypoint.sh" - "versions.json" - "stackbrew.js" jobs: pr: runs-on: ubuntu-latest if: github.repository_owner == 'nodejs' && github.event.pull_request.merged_by != '' permissions: pull-requests: write steps: - name: Checkout the docker-node repo uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: path: docker-node ref: ${{ github.base_ref }} fetch-depth: 50 - name: Checkout the official-images repo uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: path: official-images repository: docker-library/official-images - name: Generate Stackbrew for diff run: | cd docker-node ./stackbrew.js > ../official-images/library/node - name: Create PR in official-images id: create-pr uses: peter-evans/create-pull-request@c0f553fe549906ede9cf27b5156039d195d2ece0 # v8.1.0 with: token: ${{ secrets.GH_API_TOKEN }} push-to-fork: nodejs/official-images path: official-images branch: node commit-message: "Node: ${{ github.event.pull_request.title }}" title: "Node: ${{ github.event.pull_request.title }}" body: | Pull Request: ${{ github.event.pull_request.html_url }} @LaurentGoderre @PeterDaveHello @SimenB @Starefossen @nschonni @ttshivers - name: PR details run: | echo "Pull Request Number - ${{ steps.create-pr.outputs.pull-request-number }}" echo "Pull Request URL - ${{ steps.create-pr.outputs.pull-request-url }}" - name: Create PR comment uses: peter-evans/create-or-update-comment@e8674b075228eee787fea43ef493e45ece1004c9 # v5.0.0 if: ${{ steps.create-pr.outputs.pull-request-url != '' }} with: issue-number: ${{ github.event.pull_request.number }} body: | Created PR on the official-images repo (${{ steps.create-pr.outputs.pull-request-url }}). See https://github.com/docker-library/faq#an-images-source-changed-in-git-now-what if you are wondering when it will be available on the Docker Hub. ================================================ FILE: .github/workflows/scorecard.yml ================================================ # This workflow uses actions that are not certified by GitHub. They are provided # by a third-party and are governed by separate terms of service, privacy # policy, and support documentation. name: Scorecard supply-chain security on: # For Branch-Protection check. Only the default branch is supported. See # https://github.com/ossf/scorecard/blob/main/docs/checks.md#branch-protection branch_protection_rule: # To guarantee Maintained check is occasionally updated. See # https://github.com/ossf/scorecard/blob/main/docs/checks.md#maintained schedule: - cron: '30 12 * * 6' push: branches: [ "main" ] # Declare default permissions as read only. permissions: read-all jobs: analysis: name: Scorecard analysis runs-on: ubuntu-latest permissions: # Needed to upload the results to code-scanning dashboard. security-events: write # Needed to publish results and get a badge (see publish_results below). id-token: write # Uncomment the permissions below if installing in a private repository. # contents: read # actions: read steps: - name: "Checkout code" uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: persist-credentials: false - name: "Run analysis" uses: ossf/scorecard-action@4eaacf0543bb3f2c246792bd56e8cdeffafb205a # v2.4.3 with: results_file: results.sarif results_format: sarif # (Optional) "write" PAT token. Uncomment the `repo_token` line below if: # - you want to enable the Branch-Protection check on a *public* repository, or # - you are installing Scorecard on a *private* repository # To create the PAT, follow the steps in https://github.com/ossf/scorecard-action?tab=readme-ov-file#authentication-with-fine-grained-pat-optional. # repo_token: ${{ secrets.SCORECARD_TOKEN }} # Public repositories: # - Publish results to OpenSSF REST API for easy access by consumers # - Allows the repository to include the Scorecard badge. # - See https://github.com/ossf/scorecard-action#publishing-results. # For private repositories: # - `publish_results` will always be set to `false`, regardless # of the value entered here. publish_results: true # Upload the results as artifacts (optional). Commenting out will disable uploads of run results in SARIF # format to the repository Actions tab. - name: "Upload artifact" uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0 with: name: SARIF file path: results.sarif retention-days: 5 # Upload the results to GitHub's code scanning dashboard (optional). # Commenting out will disable upload of results to your repo's Code Scanning dashboard - name: "Upload to code-scanning" uses: github/codeql-action/upload-sarif@b1bff81932f5cdfc8695c7752dcee935dcd061c8 # v4.33.0 with: sarif_file: results.sarif ================================================ FILE: .github/workflows/shfmt.yml ================================================ name: Check Shell scripts on: pull_request: paths: - "**/*.sh" permissions: contents: read jobs: shfmt: runs-on: ubuntu-latest steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - run: docker run -v "$(pwd)":/sh -w /sh peterdavehello/shfmt:2.6.3 shfmt -sr -i 2 -l -w -ci . - run: git diff --color --exit-code shellcheck: runs-on: ubuntu-latest steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - run: shellcheck *.sh ================================================ FILE: 20/alpine3.22/Dockerfile ================================================ FROM alpine:3.22 ENV NODE_VERSION=20.20.1 RUN addgroup -g 1000 node \ && adduser -u 1000 -G node -s /bin/sh -D node \ && apk add --no-cache \ libstdc++ \ && apk add --no-cache --virtual .build-deps \ curl \ && ARCH= OPENSSL_ARCH='linux*' && alpineArch="$(apk --print-arch)" \ && case "${alpineArch##*-}" in \ x86_64) ARCH='x64' CHECKSUM="7f9e644a6fcc02699e186c3c3a8c8926170a1ad55f14da09b2d19652be222f35" OPENSSL_ARCH=linux-x86_64;; \ x86) OPENSSL_ARCH=linux-elf;; \ aarch64) OPENSSL_ARCH=linux-aarch64;; \ arm*) OPENSSL_ARCH=linux-armv4;; \ ppc64le) OPENSSL_ARCH=linux-ppc64le;; \ s390x) OPENSSL_ARCH=linux-s390x;; \ *) ;; \ esac \ && if [ -n "${CHECKSUM}" ]; then \ set -eu; \ curl -fsSLO --compressed "https://unofficial-builds.nodejs.org/download/release/v$NODE_VERSION/node-v$NODE_VERSION-linux-$ARCH-musl.tar.xz"; \ echo "$CHECKSUM node-v$NODE_VERSION-linux-$ARCH-musl.tar.xz" | sha256sum -c - \ && tar -xJf "node-v$NODE_VERSION-linux-$ARCH-musl.tar.xz" -C /usr/local --strip-components=1 --no-same-owner \ && ln -s /usr/local/bin/node /usr/local/bin/nodejs; \ else \ echo "Building from source" \ # backup build && apk add --no-cache --virtual .build-deps-full \ binutils-gold \ g++ \ gcc \ gnupg \ libgcc \ linux-headers \ make \ python3 \ py-setuptools \ # use pre-existing gpg directory, see https://github.com/nodejs/docker-node/pull/1895#issuecomment-1550389150 && export GNUPGHOME="$(mktemp -d)" \ # gpg keys listed at https://github.com/nodejs/node#release-keys && for key in \ 5BE8A3F6C8A5C01D106C0AD820B1A390B168D356 \ DD792F5973C6DE52C432CBDAC77ABFA00DDBF2B7 \ CC68F5A3106FF448322E48ED27F5E38D5B0A215F \ 8FCCA13FEF1D0C2E91008E09770F7A9A5AE15600 \ 890C08DB8579162FEE0DF9DB8BEAB4DFCF555EF4 \ C82FA3AE1CBEDC6BE46B9360C43CEC45C17AB93C \ 108F52B48DB57BB0CC439B2997B01419BD92F80A \ A363A499291CBBC940DD62E41F10027AF002F8B0 \ ; do \ { gpg --batch --keyserver hkps://keys.openpgp.org --recv-keys "$key" && gpg --batch --fingerprint "$key"; } || \ { gpg --batch --keyserver keyserver.ubuntu.com --recv-keys "$key" && gpg --batch --fingerprint "$key"; } ; \ done \ && curl -fsSLO --compressed "https://nodejs.org/dist/v$NODE_VERSION/node-v$NODE_VERSION.tar.xz" \ && curl -fsSLO --compressed "https://nodejs.org/dist/v$NODE_VERSION/SHASUMS256.txt.asc" \ && gpg --batch --decrypt --output SHASUMS256.txt SHASUMS256.txt.asc \ && gpgconf --kill all \ && rm -rf "$GNUPGHOME" \ && grep " node-v$NODE_VERSION.tar.xz\$" SHASUMS256.txt | sha256sum -c - \ && tar -xf "node-v$NODE_VERSION.tar.xz" \ && cd "node-v$NODE_VERSION" \ && ./configure \ && make -j$(getconf _NPROCESSORS_ONLN) V= \ && make install \ && apk del .build-deps-full \ && cd .. \ && rm -Rf "node-v$NODE_VERSION" \ && rm "node-v$NODE_VERSION.tar.xz" SHASUMS256.txt.asc SHASUMS256.txt; \ fi \ && rm -f "node-v$NODE_VERSION-linux-$ARCH-musl.tar.xz" \ # Remove unused OpenSSL headers to save ~34MB. See this NodeJS issue: https://github.com/nodejs/node/issues/46451 && find /usr/local/include/node/openssl/archs -mindepth 1 -maxdepth 1 ! -name "$OPENSSL_ARCH" -exec rm -rf {} \; \ && apk del .build-deps \ # smoke tests && node --version \ && npm --version \ && rm -rf /tmp/* ENV YARN_VERSION=1.22.22 RUN apk add --no-cache --virtual .build-deps-yarn curl gnupg tar \ # use pre-existing gpg directory, see https://github.com/nodejs/docker-node/pull/1895#issuecomment-1550389150 && export GNUPGHOME="$(mktemp -d)" \ && for key in \ 6A010C5166006599AA17F08146C2130DFD2497F5 \ ; do \ { gpg --batch --keyserver hkps://keys.openpgp.org --recv-keys "$key" && gpg --batch --fingerprint "$key"; } || \ { gpg --batch --keyserver keyserver.ubuntu.com --recv-keys "$key" && gpg --batch --fingerprint "$key"; } ; \ done \ && curl -fsSLO --compressed "https://yarnpkg.com/downloads/$YARN_VERSION/yarn-v$YARN_VERSION.tar.gz" \ && curl -fsSLO --compressed "https://yarnpkg.com/downloads/$YARN_VERSION/yarn-v$YARN_VERSION.tar.gz.asc" \ && gpg --batch --verify yarn-v$YARN_VERSION.tar.gz.asc yarn-v$YARN_VERSION.tar.gz \ && gpgconf --kill all \ && rm -rf "$GNUPGHOME" \ && mkdir -p /opt \ && tar -xzf yarn-v$YARN_VERSION.tar.gz -C /opt/ \ && ln -s /opt/yarn-v$YARN_VERSION/bin/yarn /usr/local/bin/yarn \ && ln -s /opt/yarn-v$YARN_VERSION/bin/yarnpkg /usr/local/bin/yarnpkg \ && rm yarn-v$YARN_VERSION.tar.gz.asc yarn-v$YARN_VERSION.tar.gz \ && apk del .build-deps-yarn \ # smoke test && yarn --version \ && rm -rf /tmp/* COPY docker-entrypoint.sh /usr/local/bin/ ENTRYPOINT ["docker-entrypoint.sh"] CMD [ "node" ] ================================================ FILE: 20/alpine3.22/docker-entrypoint.sh ================================================ #!/bin/sh set -e # Run command with node if the first argument contains a "-" or is not a system command. The last # part inside the "{}" is a workaround for the following bug in ash/dash: # https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=874264 if [ "${1#-}" != "${1}" ] || [ -z "$(command -v "${1}")" ] || { [ -f "${1}" ] && ! [ -x "${1}" ]; }; then set -- node "$@" fi exec "$@" ================================================ FILE: 20/alpine3.23/Dockerfile ================================================ FROM alpine:3.23 ENV NODE_VERSION=20.20.1 RUN addgroup -g 1000 node \ && adduser -u 1000 -G node -s /bin/sh -D node \ && apk add --no-cache \ libstdc++ \ && apk add --no-cache --virtual .build-deps \ curl \ && ARCH= OPENSSL_ARCH='linux*' && alpineArch="$(apk --print-arch)" \ && case "${alpineArch##*-}" in \ x86_64) ARCH='x64' CHECKSUM="7f9e644a6fcc02699e186c3c3a8c8926170a1ad55f14da09b2d19652be222f35" OPENSSL_ARCH=linux-x86_64;; \ x86) OPENSSL_ARCH=linux-elf;; \ aarch64) OPENSSL_ARCH=linux-aarch64;; \ arm*) OPENSSL_ARCH=linux-armv4;; \ ppc64le) OPENSSL_ARCH=linux-ppc64le;; \ s390x) OPENSSL_ARCH=linux-s390x;; \ *) ;; \ esac \ && if [ -n "${CHECKSUM}" ]; then \ set -eu; \ curl -fsSLO --compressed "https://unofficial-builds.nodejs.org/download/release/v$NODE_VERSION/node-v$NODE_VERSION-linux-$ARCH-musl.tar.xz"; \ echo "$CHECKSUM node-v$NODE_VERSION-linux-$ARCH-musl.tar.xz" | sha256sum -c - \ && tar -xJf "node-v$NODE_VERSION-linux-$ARCH-musl.tar.xz" -C /usr/local --strip-components=1 --no-same-owner \ && ln -s /usr/local/bin/node /usr/local/bin/nodejs; \ else \ echo "Building from source" \ # backup build && apk add --no-cache --virtual .build-deps-full \ binutils-gold \ g++ \ gcc \ gnupg \ libgcc \ linux-headers \ make \ python3 \ py-setuptools \ # use pre-existing gpg directory, see https://github.com/nodejs/docker-node/pull/1895#issuecomment-1550389150 && export GNUPGHOME="$(mktemp -d)" \ # gpg keys listed at https://github.com/nodejs/node#release-keys && for key in \ 5BE8A3F6C8A5C01D106C0AD820B1A390B168D356 \ DD792F5973C6DE52C432CBDAC77ABFA00DDBF2B7 \ CC68F5A3106FF448322E48ED27F5E38D5B0A215F \ 8FCCA13FEF1D0C2E91008E09770F7A9A5AE15600 \ 890C08DB8579162FEE0DF9DB8BEAB4DFCF555EF4 \ C82FA3AE1CBEDC6BE46B9360C43CEC45C17AB93C \ 108F52B48DB57BB0CC439B2997B01419BD92F80A \ A363A499291CBBC940DD62E41F10027AF002F8B0 \ ; do \ { gpg --batch --keyserver hkps://keys.openpgp.org --recv-keys "$key" && gpg --batch --fingerprint "$key"; } || \ { gpg --batch --keyserver keyserver.ubuntu.com --recv-keys "$key" && gpg --batch --fingerprint "$key"; } ; \ done \ && curl -fsSLO --compressed "https://nodejs.org/dist/v$NODE_VERSION/node-v$NODE_VERSION.tar.xz" \ && curl -fsSLO --compressed "https://nodejs.org/dist/v$NODE_VERSION/SHASUMS256.txt.asc" \ && gpg --batch --decrypt --output SHASUMS256.txt SHASUMS256.txt.asc \ && gpgconf --kill all \ && rm -rf "$GNUPGHOME" \ && grep " node-v$NODE_VERSION.tar.xz\$" SHASUMS256.txt | sha256sum -c - \ && tar -xf "node-v$NODE_VERSION.tar.xz" \ && cd "node-v$NODE_VERSION" \ && ./configure \ && make -j$(getconf _NPROCESSORS_ONLN) V= \ && make install \ && apk del .build-deps-full \ && cd .. \ && rm -Rf "node-v$NODE_VERSION" \ && rm "node-v$NODE_VERSION.tar.xz" SHASUMS256.txt.asc SHASUMS256.txt; \ fi \ && rm -f "node-v$NODE_VERSION-linux-$ARCH-musl.tar.xz" \ # Remove unused OpenSSL headers to save ~34MB. See this NodeJS issue: https://github.com/nodejs/node/issues/46451 && find /usr/local/include/node/openssl/archs -mindepth 1 -maxdepth 1 ! -name "$OPENSSL_ARCH" -exec rm -rf {} \; \ && apk del .build-deps \ # smoke tests && node --version \ && npm --version \ && rm -rf /tmp/* ENV YARN_VERSION=1.22.22 RUN apk add --no-cache --virtual .build-deps-yarn curl gnupg tar \ # use pre-existing gpg directory, see https://github.com/nodejs/docker-node/pull/1895#issuecomment-1550389150 && export GNUPGHOME="$(mktemp -d)" \ && for key in \ 6A010C5166006599AA17F08146C2130DFD2497F5 \ ; do \ { gpg --batch --keyserver hkps://keys.openpgp.org --recv-keys "$key" && gpg --batch --fingerprint "$key"; } || \ { gpg --batch --keyserver keyserver.ubuntu.com --recv-keys "$key" && gpg --batch --fingerprint "$key"; } ; \ done \ && curl -fsSLO --compressed "https://yarnpkg.com/downloads/$YARN_VERSION/yarn-v$YARN_VERSION.tar.gz" \ && curl -fsSLO --compressed "https://yarnpkg.com/downloads/$YARN_VERSION/yarn-v$YARN_VERSION.tar.gz.asc" \ && gpg --batch --verify yarn-v$YARN_VERSION.tar.gz.asc yarn-v$YARN_VERSION.tar.gz \ && gpgconf --kill all \ && rm -rf "$GNUPGHOME" \ && mkdir -p /opt \ && tar -xzf yarn-v$YARN_VERSION.tar.gz -C /opt/ \ && ln -s /opt/yarn-v$YARN_VERSION/bin/yarn /usr/local/bin/yarn \ && ln -s /opt/yarn-v$YARN_VERSION/bin/yarnpkg /usr/local/bin/yarnpkg \ && rm yarn-v$YARN_VERSION.tar.gz.asc yarn-v$YARN_VERSION.tar.gz \ && apk del .build-deps-yarn \ # smoke test && yarn --version \ && rm -rf /tmp/* COPY docker-entrypoint.sh /usr/local/bin/ ENTRYPOINT ["docker-entrypoint.sh"] CMD [ "node" ] ================================================ FILE: 20/alpine3.23/docker-entrypoint.sh ================================================ #!/bin/sh set -e # Run command with node if the first argument contains a "-" or is not a system command. The last # part inside the "{}" is a workaround for the following bug in ash/dash: # https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=874264 if [ "${1#-}" != "${1}" ] || [ -z "$(command -v "${1}")" ] || { [ -f "${1}" ] && ! [ -x "${1}" ]; }; then set -- node "$@" fi exec "$@" ================================================ FILE: 20/bookworm/Dockerfile ================================================ FROM buildpack-deps:bookworm RUN groupadd --gid 1000 node \ && useradd --uid 1000 --gid node --shell /bin/bash --create-home node ENV NODE_VERSION=20.20.1 RUN ARCH= && dpkgArch="$(dpkg --print-architecture)" \ && case "${dpkgArch##*-}" in \ amd64) ARCH='x64';; \ ppc64el) ARCH='ppc64le';; \ s390x) ARCH='s390x';; \ arm64) ARCH='arm64';; \ armhf) ARCH='armv7l';; \ i386) ARCH='x86';; \ *) echo "unsupported architecture"; exit 1 ;; \ esac \ # use pre-existing gpg directory, see https://github.com/nodejs/docker-node/pull/1895#issuecomment-1550389150 && export GNUPGHOME="$(mktemp -d)" \ # gpg keys listed at https://github.com/nodejs/node#release-keys && set -ex \ && for key in \ 5BE8A3F6C8A5C01D106C0AD820B1A390B168D356 \ DD792F5973C6DE52C432CBDAC77ABFA00DDBF2B7 \ CC68F5A3106FF448322E48ED27F5E38D5B0A215F \ 8FCCA13FEF1D0C2E91008E09770F7A9A5AE15600 \ 890C08DB8579162FEE0DF9DB8BEAB4DFCF555EF4 \ C82FA3AE1CBEDC6BE46B9360C43CEC45C17AB93C \ 108F52B48DB57BB0CC439B2997B01419BD92F80A \ A363A499291CBBC940DD62E41F10027AF002F8B0 \ ; do \ { gpg --batch --keyserver hkps://keys.openpgp.org --recv-keys "$key" && gpg --batch --fingerprint "$key"; } || \ { gpg --batch --keyserver keyserver.ubuntu.com --recv-keys "$key" && gpg --batch --fingerprint "$key"; } ; \ done \ && curl -fsSLO --compressed "https://nodejs.org/dist/v$NODE_VERSION/node-v$NODE_VERSION-linux-$ARCH.tar.xz" \ && curl -fsSLO --compressed "https://nodejs.org/dist/v$NODE_VERSION/SHASUMS256.txt.asc" \ && gpg --batch --decrypt --output SHASUMS256.txt SHASUMS256.txt.asc \ && gpgconf --kill all \ && rm -rf "$GNUPGHOME" \ && grep " node-v$NODE_VERSION-linux-$ARCH.tar.xz\$" SHASUMS256.txt | sha256sum -c - \ && tar -xJf "node-v$NODE_VERSION-linux-$ARCH.tar.xz" -C /usr/local --strip-components=1 --no-same-owner \ && rm "node-v$NODE_VERSION-linux-$ARCH.tar.xz" SHASUMS256.txt.asc SHASUMS256.txt \ && ln -s /usr/local/bin/node /usr/local/bin/nodejs \ # smoke tests && node --version \ && npm --version \ && rm -rf /tmp/* ENV YARN_VERSION=1.22.22 RUN set -ex \ # use pre-existing gpg directory, see https://github.com/nodejs/docker-node/pull/1895#issuecomment-1550389150 && export GNUPGHOME="$(mktemp -d)" \ && for key in \ 6A010C5166006599AA17F08146C2130DFD2497F5 \ ; do \ { gpg --batch --keyserver hkps://keys.openpgp.org --recv-keys "$key" && gpg --batch --fingerprint "$key"; } || \ { gpg --batch --keyserver keyserver.ubuntu.com --recv-keys "$key" && gpg --batch --fingerprint "$key"; } ; \ done \ && curl -fsSLO --compressed "https://yarnpkg.com/downloads/$YARN_VERSION/yarn-v$YARN_VERSION.tar.gz" \ && curl -fsSLO --compressed "https://yarnpkg.com/downloads/$YARN_VERSION/yarn-v$YARN_VERSION.tar.gz.asc" \ && gpg --batch --verify yarn-v$YARN_VERSION.tar.gz.asc yarn-v$YARN_VERSION.tar.gz \ && gpgconf --kill all \ && rm -rf "$GNUPGHOME" \ && mkdir -p /opt \ && tar -xzf yarn-v$YARN_VERSION.tar.gz -C /opt/ \ && ln -s /opt/yarn-v$YARN_VERSION/bin/yarn /usr/local/bin/yarn \ && ln -s /opt/yarn-v$YARN_VERSION/bin/yarnpkg /usr/local/bin/yarnpkg \ && rm yarn-v$YARN_VERSION.tar.gz.asc yarn-v$YARN_VERSION.tar.gz \ # smoke test && yarn --version \ && rm -rf /tmp/* COPY docker-entrypoint.sh /usr/local/bin/ ENTRYPOINT ["docker-entrypoint.sh"] CMD [ "node" ] ================================================ FILE: 20/bookworm/docker-entrypoint.sh ================================================ #!/bin/sh set -e # Run command with node if the first argument contains a "-" or is not a system command. The last # part inside the "{}" is a workaround for the following bug in ash/dash: # https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=874264 if [ "${1#-}" != "${1}" ] || [ -z "$(command -v "${1}")" ] || { [ -f "${1}" ] && ! [ -x "${1}" ]; }; then set -- node "$@" fi exec "$@" ================================================ FILE: 20/bookworm-slim/Dockerfile ================================================ FROM debian:bookworm-slim RUN groupadd --gid 1000 node \ && useradd --uid 1000 --gid node --shell /bin/bash --create-home node ENV NODE_VERSION=20.20.1 RUN ARCH= OPENSSL_ARCH= && dpkgArch="$(dpkg --print-architecture)" \ && case "${dpkgArch##*-}" in \ amd64) ARCH='x64' OPENSSL_ARCH='linux-x86_64';; \ ppc64el) ARCH='ppc64le' OPENSSL_ARCH='linux-ppc64le';; \ s390x) ARCH='s390x' OPENSSL_ARCH='linux*-s390x';; \ arm64) ARCH='arm64' OPENSSL_ARCH='linux-aarch64';; \ armhf) ARCH='armv7l' OPENSSL_ARCH='linux-armv4';; \ i386) ARCH='x86' OPENSSL_ARCH='linux-elf';; \ *) echo "unsupported architecture"; exit 1 ;; \ esac \ && set -ex \ # libatomic1 for arm && apt-get update && apt-get install -y ca-certificates curl wget gnupg dirmngr xz-utils libatomic1 --no-install-recommends \ && rm -rf /var/lib/apt/lists/* \ # use pre-existing gpg directory, see https://github.com/nodejs/docker-node/pull/1895#issuecomment-1550389150 && export GNUPGHOME="$(mktemp -d)" \ # gpg keys listed at https://github.com/nodejs/node#release-keys && for key in \ 5BE8A3F6C8A5C01D106C0AD820B1A390B168D356 \ DD792F5973C6DE52C432CBDAC77ABFA00DDBF2B7 \ CC68F5A3106FF448322E48ED27F5E38D5B0A215F \ 8FCCA13FEF1D0C2E91008E09770F7A9A5AE15600 \ 890C08DB8579162FEE0DF9DB8BEAB4DFCF555EF4 \ C82FA3AE1CBEDC6BE46B9360C43CEC45C17AB93C \ 108F52B48DB57BB0CC439B2997B01419BD92F80A \ A363A499291CBBC940DD62E41F10027AF002F8B0 \ ; do \ { gpg --batch --keyserver hkps://keys.openpgp.org --recv-keys "$key" && gpg --batch --fingerprint "$key"; } || \ { gpg --batch --keyserver keyserver.ubuntu.com --recv-keys "$key" && gpg --batch --fingerprint "$key"; } ; \ done \ && curl -fsSLO --compressed "https://nodejs.org/dist/v$NODE_VERSION/node-v$NODE_VERSION-linux-$ARCH.tar.xz" \ && curl -fsSLO --compressed "https://nodejs.org/dist/v$NODE_VERSION/SHASUMS256.txt.asc" \ && gpg --batch --decrypt --output SHASUMS256.txt SHASUMS256.txt.asc \ && gpgconf --kill all \ && rm -rf "$GNUPGHOME" \ && grep " node-v$NODE_VERSION-linux-$ARCH.tar.xz\$" SHASUMS256.txt | sha256sum -c - \ && tar -xJf "node-v$NODE_VERSION-linux-$ARCH.tar.xz" -C /usr/local --strip-components=1 --no-same-owner \ && rm "node-v$NODE_VERSION-linux-$ARCH.tar.xz" SHASUMS256.txt.asc SHASUMS256.txt \ # Remove unused OpenSSL headers to save ~34MB. See this NodeJS issue: https://github.com/nodejs/node/issues/46451 && find /usr/local/include/node/openssl/archs -mindepth 1 -maxdepth 1 ! -name "$OPENSSL_ARCH" -exec rm -rf {} \; \ && apt-mark auto '.*' > /dev/null \ && find /usr/local -type f -executable -exec ldd '{}' ';' \ | awk '/=>/ { so = $(NF-1); if (index(so, "/usr/local/") == 1) { next }; gsub("^/(usr/)?", "", so); print so }' \ | sort -u \ | xargs -r dpkg-query --search \ | cut -d: -f1 \ | sort -u \ | xargs -r apt-mark manual \ && apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false \ && ln -s /usr/local/bin/node /usr/local/bin/nodejs \ # smoke tests && node --version \ && npm --version \ && rm -rf /tmp/* ENV YARN_VERSION=1.22.22 RUN set -ex \ && savedAptMark="$(apt-mark showmanual)" \ && apt-get update && apt-get install -y ca-certificates curl wget gnupg dirmngr --no-install-recommends \ && rm -rf /var/lib/apt/lists/* \ # use pre-existing gpg directory, see https://github.com/nodejs/docker-node/pull/1895#issuecomment-1550389150 && export GNUPGHOME="$(mktemp -d)" \ && for key in \ 6A010C5166006599AA17F08146C2130DFD2497F5 \ ; do \ { gpg --batch --keyserver hkps://keys.openpgp.org --recv-keys "$key" && gpg --batch --fingerprint "$key"; } || \ { gpg --batch --keyserver keyserver.ubuntu.com --recv-keys "$key" && gpg --batch --fingerprint "$key"; } ; \ done \ && curl -fsSLO --compressed "https://yarnpkg.com/downloads/$YARN_VERSION/yarn-v$YARN_VERSION.tar.gz" \ && curl -fsSLO --compressed "https://yarnpkg.com/downloads/$YARN_VERSION/yarn-v$YARN_VERSION.tar.gz.asc" \ && gpg --batch --verify yarn-v$YARN_VERSION.tar.gz.asc yarn-v$YARN_VERSION.tar.gz \ && gpgconf --kill all \ && rm -rf "$GNUPGHOME" \ && mkdir -p /opt \ && tar -xzf yarn-v$YARN_VERSION.tar.gz -C /opt/ \ && ln -s /opt/yarn-v$YARN_VERSION/bin/yarn /usr/local/bin/yarn \ && ln -s /opt/yarn-v$YARN_VERSION/bin/yarnpkg /usr/local/bin/yarnpkg \ && rm yarn-v$YARN_VERSION.tar.gz.asc yarn-v$YARN_VERSION.tar.gz \ && apt-mark auto '.*' > /dev/null \ && { [ -z "$savedAptMark" ] || apt-mark manual $savedAptMark > /dev/null; } \ && find /usr/local -type f -executable -exec ldd '{}' ';' \ | awk '/=>/ { so = $(NF-1); if (index(so, "/usr/local/") == 1) { next }; gsub("^/(usr/)?", "", so); print so }' \ | sort -u \ | xargs -r dpkg-query --search \ | cut -d: -f1 \ | sort -u \ | xargs -r apt-mark manual \ && apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false \ # smoke test && yarn --version \ && rm -rf /tmp/* COPY docker-entrypoint.sh /usr/local/bin/ ENTRYPOINT ["docker-entrypoint.sh"] CMD [ "node" ] ================================================ FILE: 20/bookworm-slim/docker-entrypoint.sh ================================================ #!/bin/sh set -e # Run command with node if the first argument contains a "-" or is not a system command. The last # part inside the "{}" is a workaround for the following bug in ash/dash: # https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=874264 if [ "${1#-}" != "${1}" ] || [ -z "$(command -v "${1}")" ] || { [ -f "${1}" ] && ! [ -x "${1}" ]; }; then set -- node "$@" fi exec "$@" ================================================ FILE: 20/bullseye/Dockerfile ================================================ FROM buildpack-deps:bullseye RUN groupadd --gid 1000 node \ && useradd --uid 1000 --gid node --shell /bin/bash --create-home node ENV NODE_VERSION=20.20.1 RUN ARCH= && dpkgArch="$(dpkg --print-architecture)" \ && case "${dpkgArch##*-}" in \ amd64) ARCH='x64';; \ ppc64el) ARCH='ppc64le';; \ s390x) ARCH='s390x';; \ arm64) ARCH='arm64';; \ armhf) ARCH='armv7l';; \ i386) ARCH='x86';; \ *) echo "unsupported architecture"; exit 1 ;; \ esac \ # use pre-existing gpg directory, see https://github.com/nodejs/docker-node/pull/1895#issuecomment-1550389150 && export GNUPGHOME="$(mktemp -d)" \ # gpg keys listed at https://github.com/nodejs/node#release-keys && set -ex \ && for key in \ 5BE8A3F6C8A5C01D106C0AD820B1A390B168D356 \ DD792F5973C6DE52C432CBDAC77ABFA00DDBF2B7 \ CC68F5A3106FF448322E48ED27F5E38D5B0A215F \ 8FCCA13FEF1D0C2E91008E09770F7A9A5AE15600 \ 890C08DB8579162FEE0DF9DB8BEAB4DFCF555EF4 \ C82FA3AE1CBEDC6BE46B9360C43CEC45C17AB93C \ 108F52B48DB57BB0CC439B2997B01419BD92F80A \ A363A499291CBBC940DD62E41F10027AF002F8B0 \ ; do \ { gpg --batch --keyserver hkps://keys.openpgp.org --recv-keys "$key" && gpg --batch --fingerprint "$key"; } || \ { gpg --batch --keyserver keyserver.ubuntu.com --recv-keys "$key" && gpg --batch --fingerprint "$key"; } ; \ done \ && curl -fsSLO --compressed "https://nodejs.org/dist/v$NODE_VERSION/node-v$NODE_VERSION-linux-$ARCH.tar.xz" \ && curl -fsSLO --compressed "https://nodejs.org/dist/v$NODE_VERSION/SHASUMS256.txt.asc" \ && gpg --batch --decrypt --output SHASUMS256.txt SHASUMS256.txt.asc \ && gpgconf --kill all \ && rm -rf "$GNUPGHOME" \ && grep " node-v$NODE_VERSION-linux-$ARCH.tar.xz\$" SHASUMS256.txt | sha256sum -c - \ && tar -xJf "node-v$NODE_VERSION-linux-$ARCH.tar.xz" -C /usr/local --strip-components=1 --no-same-owner \ && rm "node-v$NODE_VERSION-linux-$ARCH.tar.xz" SHASUMS256.txt.asc SHASUMS256.txt \ && ln -s /usr/local/bin/node /usr/local/bin/nodejs \ # smoke tests && node --version \ && npm --version \ && rm -rf /tmp/* ENV YARN_VERSION=1.22.22 RUN set -ex \ # use pre-existing gpg directory, see https://github.com/nodejs/docker-node/pull/1895#issuecomment-1550389150 && export GNUPGHOME="$(mktemp -d)" \ && for key in \ 6A010C5166006599AA17F08146C2130DFD2497F5 \ ; do \ { gpg --batch --keyserver hkps://keys.openpgp.org --recv-keys "$key" && gpg --batch --fingerprint "$key"; } || \ { gpg --batch --keyserver keyserver.ubuntu.com --recv-keys "$key" && gpg --batch --fingerprint "$key"; } ; \ done \ && curl -fsSLO --compressed "https://yarnpkg.com/downloads/$YARN_VERSION/yarn-v$YARN_VERSION.tar.gz" \ && curl -fsSLO --compressed "https://yarnpkg.com/downloads/$YARN_VERSION/yarn-v$YARN_VERSION.tar.gz.asc" \ && gpg --batch --verify yarn-v$YARN_VERSION.tar.gz.asc yarn-v$YARN_VERSION.tar.gz \ && gpgconf --kill all \ && rm -rf "$GNUPGHOME" \ && mkdir -p /opt \ && tar -xzf yarn-v$YARN_VERSION.tar.gz -C /opt/ \ && ln -s /opt/yarn-v$YARN_VERSION/bin/yarn /usr/local/bin/yarn \ && ln -s /opt/yarn-v$YARN_VERSION/bin/yarnpkg /usr/local/bin/yarnpkg \ && rm yarn-v$YARN_VERSION.tar.gz.asc yarn-v$YARN_VERSION.tar.gz \ # smoke test && yarn --version \ && rm -rf /tmp/* COPY docker-entrypoint.sh /usr/local/bin/ ENTRYPOINT ["docker-entrypoint.sh"] CMD [ "node" ] ================================================ FILE: 20/bullseye/docker-entrypoint.sh ================================================ #!/bin/sh set -e # Run command with node if the first argument contains a "-" or is not a system command. The last # part inside the "{}" is a workaround for the following bug in ash/dash: # https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=874264 if [ "${1#-}" != "${1}" ] || [ -z "$(command -v "${1}")" ] || { [ -f "${1}" ] && ! [ -x "${1}" ]; }; then set -- node "$@" fi exec "$@" ================================================ FILE: 20/bullseye-slim/Dockerfile ================================================ FROM debian:bullseye-slim RUN groupadd --gid 1000 node \ && useradd --uid 1000 --gid node --shell /bin/bash --create-home node ENV NODE_VERSION=20.20.1 RUN ARCH= OPENSSL_ARCH= && dpkgArch="$(dpkg --print-architecture)" \ && case "${dpkgArch##*-}" in \ amd64) ARCH='x64' OPENSSL_ARCH='linux-x86_64';; \ ppc64el) ARCH='ppc64le' OPENSSL_ARCH='linux-ppc64le';; \ s390x) ARCH='s390x' OPENSSL_ARCH='linux*-s390x';; \ arm64) ARCH='arm64' OPENSSL_ARCH='linux-aarch64';; \ armhf) ARCH='armv7l' OPENSSL_ARCH='linux-armv4';; \ i386) ARCH='x86' OPENSSL_ARCH='linux-elf';; \ *) echo "unsupported architecture"; exit 1 ;; \ esac \ && set -ex \ # libatomic1 for arm && apt-get update && apt-get install -y ca-certificates curl wget gnupg dirmngr xz-utils libatomic1 --no-install-recommends \ && rm -rf /var/lib/apt/lists/* \ # use pre-existing gpg directory, see https://github.com/nodejs/docker-node/pull/1895#issuecomment-1550389150 && export GNUPGHOME="$(mktemp -d)" \ # gpg keys listed at https://github.com/nodejs/node#release-keys && for key in \ 5BE8A3F6C8A5C01D106C0AD820B1A390B168D356 \ DD792F5973C6DE52C432CBDAC77ABFA00DDBF2B7 \ CC68F5A3106FF448322E48ED27F5E38D5B0A215F \ 8FCCA13FEF1D0C2E91008E09770F7A9A5AE15600 \ 890C08DB8579162FEE0DF9DB8BEAB4DFCF555EF4 \ C82FA3AE1CBEDC6BE46B9360C43CEC45C17AB93C \ 108F52B48DB57BB0CC439B2997B01419BD92F80A \ A363A499291CBBC940DD62E41F10027AF002F8B0 \ ; do \ { gpg --batch --keyserver hkps://keys.openpgp.org --recv-keys "$key" && gpg --batch --fingerprint "$key"; } || \ { gpg --batch --keyserver keyserver.ubuntu.com --recv-keys "$key" && gpg --batch --fingerprint "$key"; } ; \ done \ && curl -fsSLO --compressed "https://nodejs.org/dist/v$NODE_VERSION/node-v$NODE_VERSION-linux-$ARCH.tar.xz" \ && curl -fsSLO --compressed "https://nodejs.org/dist/v$NODE_VERSION/SHASUMS256.txt.asc" \ && gpg --batch --decrypt --output SHASUMS256.txt SHASUMS256.txt.asc \ && gpgconf --kill all \ && rm -rf "$GNUPGHOME" \ && grep " node-v$NODE_VERSION-linux-$ARCH.tar.xz\$" SHASUMS256.txt | sha256sum -c - \ && tar -xJf "node-v$NODE_VERSION-linux-$ARCH.tar.xz" -C /usr/local --strip-components=1 --no-same-owner \ && rm "node-v$NODE_VERSION-linux-$ARCH.tar.xz" SHASUMS256.txt.asc SHASUMS256.txt \ # Remove unused OpenSSL headers to save ~34MB. See this NodeJS issue: https://github.com/nodejs/node/issues/46451 && find /usr/local/include/node/openssl/archs -mindepth 1 -maxdepth 1 ! -name "$OPENSSL_ARCH" -exec rm -rf {} \; \ && apt-mark auto '.*' > /dev/null \ && find /usr/local -type f -executable -exec ldd '{}' ';' \ | awk '/=>/ { so = $(NF-1); if (index(so, "/usr/local/") == 1) { next }; gsub("^/(usr/)?", "", so); print so }' \ | sort -u \ | xargs -r dpkg-query --search \ | cut -d: -f1 \ | sort -u \ | xargs -r apt-mark manual \ && apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false \ && ln -s /usr/local/bin/node /usr/local/bin/nodejs \ # smoke tests && node --version \ && npm --version \ && rm -rf /tmp/* ENV YARN_VERSION=1.22.22 RUN set -ex \ && savedAptMark="$(apt-mark showmanual)" \ && apt-get update && apt-get install -y ca-certificates curl wget gnupg dirmngr --no-install-recommends \ && rm -rf /var/lib/apt/lists/* \ # use pre-existing gpg directory, see https://github.com/nodejs/docker-node/pull/1895#issuecomment-1550389150 && export GNUPGHOME="$(mktemp -d)" \ && for key in \ 6A010C5166006599AA17F08146C2130DFD2497F5 \ ; do \ { gpg --batch --keyserver hkps://keys.openpgp.org --recv-keys "$key" && gpg --batch --fingerprint "$key"; } || \ { gpg --batch --keyserver keyserver.ubuntu.com --recv-keys "$key" && gpg --batch --fingerprint "$key"; } ; \ done \ && curl -fsSLO --compressed "https://yarnpkg.com/downloads/$YARN_VERSION/yarn-v$YARN_VERSION.tar.gz" \ && curl -fsSLO --compressed "https://yarnpkg.com/downloads/$YARN_VERSION/yarn-v$YARN_VERSION.tar.gz.asc" \ && gpg --batch --verify yarn-v$YARN_VERSION.tar.gz.asc yarn-v$YARN_VERSION.tar.gz \ && gpgconf --kill all \ && rm -rf "$GNUPGHOME" \ && mkdir -p /opt \ && tar -xzf yarn-v$YARN_VERSION.tar.gz -C /opt/ \ && ln -s /opt/yarn-v$YARN_VERSION/bin/yarn /usr/local/bin/yarn \ && ln -s /opt/yarn-v$YARN_VERSION/bin/yarnpkg /usr/local/bin/yarnpkg \ && rm yarn-v$YARN_VERSION.tar.gz.asc yarn-v$YARN_VERSION.tar.gz \ && apt-mark auto '.*' > /dev/null \ && { [ -z "$savedAptMark" ] || apt-mark manual $savedAptMark > /dev/null; } \ && find /usr/local -type f -executable -exec ldd '{}' ';' \ | awk '/=>/ { so = $(NF-1); if (index(so, "/usr/local/") == 1) { next }; gsub("^/(usr/)?", "", so); print so }' \ | sort -u \ | xargs -r dpkg-query --search \ | cut -d: -f1 \ | sort -u \ | xargs -r apt-mark manual \ && apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false \ # smoke test && yarn --version \ && rm -rf /tmp/* COPY docker-entrypoint.sh /usr/local/bin/ ENTRYPOINT ["docker-entrypoint.sh"] CMD [ "node" ] ================================================ FILE: 20/bullseye-slim/docker-entrypoint.sh ================================================ #!/bin/sh set -e # Run command with node if the first argument contains a "-" or is not a system command. The last # part inside the "{}" is a workaround for the following bug in ash/dash: # https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=874264 if [ "${1#-}" != "${1}" ] || [ -z "$(command -v "${1}")" ] || { [ -f "${1}" ] && ! [ -x "${1}" ]; }; then set -- node "$@" fi exec "$@" ================================================ FILE: 20/trixie/Dockerfile ================================================ FROM buildpack-deps:trixie RUN groupadd --gid 1000 node \ && useradd --uid 1000 --gid node --shell /bin/bash --create-home node ENV NODE_VERSION=20.20.1 RUN ARCH= && dpkgArch="$(dpkg --print-architecture)" \ && case "${dpkgArch##*-}" in \ amd64) ARCH='x64';; \ ppc64el) ARCH='ppc64le';; \ s390x) ARCH='s390x';; \ arm64) ARCH='arm64';; \ armhf) ARCH='armv7l';; \ i386) ARCH='x86';; \ *) echo "unsupported architecture"; exit 1 ;; \ esac \ # use pre-existing gpg directory, see https://github.com/nodejs/docker-node/pull/1895#issuecomment-1550389150 && export GNUPGHOME="$(mktemp -d)" \ # gpg keys listed at https://github.com/nodejs/node#release-keys && set -ex \ && for key in \ 5BE8A3F6C8A5C01D106C0AD820B1A390B168D356 \ DD792F5973C6DE52C432CBDAC77ABFA00DDBF2B7 \ CC68F5A3106FF448322E48ED27F5E38D5B0A215F \ 8FCCA13FEF1D0C2E91008E09770F7A9A5AE15600 \ 890C08DB8579162FEE0DF9DB8BEAB4DFCF555EF4 \ C82FA3AE1CBEDC6BE46B9360C43CEC45C17AB93C \ 108F52B48DB57BB0CC439B2997B01419BD92F80A \ A363A499291CBBC940DD62E41F10027AF002F8B0 \ ; do \ { gpg --batch --keyserver hkps://keys.openpgp.org --recv-keys "$key" && gpg --batch --fingerprint "$key"; } || \ { gpg --batch --keyserver keyserver.ubuntu.com --recv-keys "$key" && gpg --batch --fingerprint "$key"; } ; \ done \ && curl -fsSLO --compressed "https://nodejs.org/dist/v$NODE_VERSION/node-v$NODE_VERSION-linux-$ARCH.tar.xz" \ && curl -fsSLO --compressed "https://nodejs.org/dist/v$NODE_VERSION/SHASUMS256.txt.asc" \ && gpg --batch --decrypt --output SHASUMS256.txt SHASUMS256.txt.asc \ && gpgconf --kill all \ && rm -rf "$GNUPGHOME" \ && grep " node-v$NODE_VERSION-linux-$ARCH.tar.xz\$" SHASUMS256.txt | sha256sum -c - \ && tar -xJf "node-v$NODE_VERSION-linux-$ARCH.tar.xz" -C /usr/local --strip-components=1 --no-same-owner \ && rm "node-v$NODE_VERSION-linux-$ARCH.tar.xz" SHASUMS256.txt.asc SHASUMS256.txt \ && ln -s /usr/local/bin/node /usr/local/bin/nodejs \ # smoke tests && node --version \ && npm --version \ && rm -rf /tmp/* ENV YARN_VERSION=1.22.22 RUN set -ex \ # use pre-existing gpg directory, see https://github.com/nodejs/docker-node/pull/1895#issuecomment-1550389150 && export GNUPGHOME="$(mktemp -d)" \ && for key in \ 6A010C5166006599AA17F08146C2130DFD2497F5 \ ; do \ { gpg --batch --keyserver hkps://keys.openpgp.org --recv-keys "$key" && gpg --batch --fingerprint "$key"; } || \ { gpg --batch --keyserver keyserver.ubuntu.com --recv-keys "$key" && gpg --batch --fingerprint "$key"; } ; \ done \ && curl -fsSLO --compressed "https://yarnpkg.com/downloads/$YARN_VERSION/yarn-v$YARN_VERSION.tar.gz" \ && curl -fsSLO --compressed "https://yarnpkg.com/downloads/$YARN_VERSION/yarn-v$YARN_VERSION.tar.gz.asc" \ && gpg --batch --verify yarn-v$YARN_VERSION.tar.gz.asc yarn-v$YARN_VERSION.tar.gz \ && gpgconf --kill all \ && rm -rf "$GNUPGHOME" \ && mkdir -p /opt \ && tar -xzf yarn-v$YARN_VERSION.tar.gz -C /opt/ \ && ln -s /opt/yarn-v$YARN_VERSION/bin/yarn /usr/local/bin/yarn \ && ln -s /opt/yarn-v$YARN_VERSION/bin/yarnpkg /usr/local/bin/yarnpkg \ && rm yarn-v$YARN_VERSION.tar.gz.asc yarn-v$YARN_VERSION.tar.gz \ # smoke test && yarn --version \ && rm -rf /tmp/* COPY docker-entrypoint.sh /usr/local/bin/ ENTRYPOINT ["docker-entrypoint.sh"] CMD [ "node" ] ================================================ FILE: 20/trixie/docker-entrypoint.sh ================================================ #!/bin/sh set -e # Run command with node if the first argument contains a "-" or is not a system command. The last # part inside the "{}" is a workaround for the following bug in ash/dash: # https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=874264 if [ "${1#-}" != "${1}" ] || [ -z "$(command -v "${1}")" ] || { [ -f "${1}" ] && ! [ -x "${1}" ]; }; then set -- node "$@" fi exec "$@" ================================================ FILE: 20/trixie-slim/Dockerfile ================================================ FROM debian:trixie-slim RUN groupadd --gid 1000 node \ && useradd --uid 1000 --gid node --shell /bin/bash --create-home node ENV NODE_VERSION=20.20.1 RUN ARCH= OPENSSL_ARCH= && dpkgArch="$(dpkg --print-architecture)" \ && case "${dpkgArch##*-}" in \ amd64) ARCH='x64' OPENSSL_ARCH='linux-x86_64';; \ ppc64el) ARCH='ppc64le' OPENSSL_ARCH='linux-ppc64le';; \ s390x) ARCH='s390x' OPENSSL_ARCH='linux*-s390x';; \ arm64) ARCH='arm64' OPENSSL_ARCH='linux-aarch64';; \ armhf) ARCH='armv7l' OPENSSL_ARCH='linux-armv4';; \ i386) ARCH='x86' OPENSSL_ARCH='linux-elf';; \ *) echo "unsupported architecture"; exit 1 ;; \ esac \ && set -ex \ # libatomic1 for arm && apt-get update && apt-get install -y ca-certificates curl wget gnupg dirmngr xz-utils libatomic1 --no-install-recommends \ && rm -rf /var/lib/apt/lists/* \ # use pre-existing gpg directory, see https://github.com/nodejs/docker-node/pull/1895#issuecomment-1550389150 && export GNUPGHOME="$(mktemp -d)" \ # gpg keys listed at https://github.com/nodejs/node#release-keys && for key in \ 5BE8A3F6C8A5C01D106C0AD820B1A390B168D356 \ DD792F5973C6DE52C432CBDAC77ABFA00DDBF2B7 \ CC68F5A3106FF448322E48ED27F5E38D5B0A215F \ 8FCCA13FEF1D0C2E91008E09770F7A9A5AE15600 \ 890C08DB8579162FEE0DF9DB8BEAB4DFCF555EF4 \ C82FA3AE1CBEDC6BE46B9360C43CEC45C17AB93C \ 108F52B48DB57BB0CC439B2997B01419BD92F80A \ A363A499291CBBC940DD62E41F10027AF002F8B0 \ ; do \ { gpg --batch --keyserver hkps://keys.openpgp.org --recv-keys "$key" && gpg --batch --fingerprint "$key"; } || \ { gpg --batch --keyserver keyserver.ubuntu.com --recv-keys "$key" && gpg --batch --fingerprint "$key"; } ; \ done \ && curl -fsSLO --compressed "https://nodejs.org/dist/v$NODE_VERSION/node-v$NODE_VERSION-linux-$ARCH.tar.xz" \ && curl -fsSLO --compressed "https://nodejs.org/dist/v$NODE_VERSION/SHASUMS256.txt.asc" \ && gpg --batch --decrypt --output SHASUMS256.txt SHASUMS256.txt.asc \ && gpgconf --kill all \ && rm -rf "$GNUPGHOME" \ && grep " node-v$NODE_VERSION-linux-$ARCH.tar.xz\$" SHASUMS256.txt | sha256sum -c - \ && tar -xJf "node-v$NODE_VERSION-linux-$ARCH.tar.xz" -C /usr/local --strip-components=1 --no-same-owner \ && rm "node-v$NODE_VERSION-linux-$ARCH.tar.xz" SHASUMS256.txt.asc SHASUMS256.txt \ # Remove unused OpenSSL headers to save ~34MB. See this NodeJS issue: https://github.com/nodejs/node/issues/46451 && find /usr/local/include/node/openssl/archs -mindepth 1 -maxdepth 1 ! -name "$OPENSSL_ARCH" -exec rm -rf {} \; \ && apt-mark auto '.*' > /dev/null \ && find /usr/local -type f -executable -exec ldd '{}' ';' \ | awk '/=>/ { so = $(NF-1); if (index(so, "/usr/local/") == 1) { next }; gsub("^/(usr/)?", "", so); print so }' \ | sort -u \ | xargs -r dpkg-query --search \ | cut -d: -f1 \ | sort -u \ | xargs -r apt-mark manual \ && apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false \ && ln -s /usr/local/bin/node /usr/local/bin/nodejs \ # smoke tests && node --version \ && npm --version \ && rm -rf /tmp/* ENV YARN_VERSION=1.22.22 RUN set -ex \ && savedAptMark="$(apt-mark showmanual)" \ && apt-get update && apt-get install -y ca-certificates curl wget gnupg dirmngr --no-install-recommends \ && rm -rf /var/lib/apt/lists/* \ # use pre-existing gpg directory, see https://github.com/nodejs/docker-node/pull/1895#issuecomment-1550389150 && export GNUPGHOME="$(mktemp -d)" \ && for key in \ 6A010C5166006599AA17F08146C2130DFD2497F5 \ ; do \ { gpg --batch --keyserver hkps://keys.openpgp.org --recv-keys "$key" && gpg --batch --fingerprint "$key"; } || \ { gpg --batch --keyserver keyserver.ubuntu.com --recv-keys "$key" && gpg --batch --fingerprint "$key"; } ; \ done \ && curl -fsSLO --compressed "https://yarnpkg.com/downloads/$YARN_VERSION/yarn-v$YARN_VERSION.tar.gz" \ && curl -fsSLO --compressed "https://yarnpkg.com/downloads/$YARN_VERSION/yarn-v$YARN_VERSION.tar.gz.asc" \ && gpg --batch --verify yarn-v$YARN_VERSION.tar.gz.asc yarn-v$YARN_VERSION.tar.gz \ && gpgconf --kill all \ && rm -rf "$GNUPGHOME" \ && mkdir -p /opt \ && tar -xzf yarn-v$YARN_VERSION.tar.gz -C /opt/ \ && ln -s /opt/yarn-v$YARN_VERSION/bin/yarn /usr/local/bin/yarn \ && ln -s /opt/yarn-v$YARN_VERSION/bin/yarnpkg /usr/local/bin/yarnpkg \ && rm yarn-v$YARN_VERSION.tar.gz.asc yarn-v$YARN_VERSION.tar.gz \ && apt-mark auto '.*' > /dev/null \ && { [ -z "$savedAptMark" ] || apt-mark manual $savedAptMark > /dev/null; } \ && find /usr/local -type f -executable -exec ldd '{}' ';' \ | awk '/=>/ { so = $(NF-1); if (index(so, "/usr/local/") == 1) { next }; gsub("^/(usr/)?", "", so); print so }' \ | sort -u \ | xargs -r dpkg-query --search \ | cut -d: -f1 \ | sort -u \ | xargs -r apt-mark manual \ && apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false \ # smoke test && yarn --version \ && rm -rf /tmp/* COPY docker-entrypoint.sh /usr/local/bin/ ENTRYPOINT ["docker-entrypoint.sh"] CMD [ "node" ] ================================================ FILE: 20/trixie-slim/docker-entrypoint.sh ================================================ #!/bin/sh set -e # Run command with node if the first argument contains a "-" or is not a system command. The last # part inside the "{}" is a workaround for the following bug in ash/dash: # https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=874264 if [ "${1#-}" != "${1}" ] || [ -z "$(command -v "${1}")" ] || { [ -f "${1}" ] && ! [ -x "${1}" ]; }; then set -- node "$@" fi exec "$@" ================================================ FILE: 22/alpine3.22/Dockerfile ================================================ FROM alpine:3.22 ENV NODE_VERSION=22.22.1 RUN addgroup -g 1000 node \ && adduser -u 1000 -G node -s /bin/sh -D node \ && apk add --no-cache \ libstdc++ \ && apk add --no-cache --virtual .build-deps \ curl \ && ARCH= OPENSSL_ARCH='linux*' && alpineArch="$(apk --print-arch)" \ && case "${alpineArch##*-}" in \ x86_64) ARCH='x64' CHECKSUM="a06721f1566c89eb911546dba6309f7da6613dbcc67c0426588b1f39a7210a95" OPENSSL_ARCH=linux-x86_64;; \ x86) OPENSSL_ARCH=linux-elf;; \ aarch64) OPENSSL_ARCH=linux-aarch64;; \ arm*) OPENSSL_ARCH=linux-armv4;; \ ppc64le) OPENSSL_ARCH=linux-ppc64le;; \ s390x) OPENSSL_ARCH=linux-s390x;; \ *) ;; \ esac \ && if [ -n "${CHECKSUM}" ]; then \ set -eu; \ curl -fsSLO --compressed "https://unofficial-builds.nodejs.org/download/release/v$NODE_VERSION/node-v$NODE_VERSION-linux-$ARCH-musl.tar.xz"; \ echo "$CHECKSUM node-v$NODE_VERSION-linux-$ARCH-musl.tar.xz" | sha256sum -c - \ && tar -xJf "node-v$NODE_VERSION-linux-$ARCH-musl.tar.xz" -C /usr/local --strip-components=1 --no-same-owner \ && ln -s /usr/local/bin/node /usr/local/bin/nodejs; \ else \ echo "Building from source" \ # backup build && apk add --no-cache --virtual .build-deps-full \ binutils-gold \ g++ \ gcc \ gnupg \ libgcc \ linux-headers \ make \ python3 \ py-setuptools \ # use pre-existing gpg directory, see https://github.com/nodejs/docker-node/pull/1895#issuecomment-1550389150 && export GNUPGHOME="$(mktemp -d)" \ # gpg keys listed at https://github.com/nodejs/node#release-keys && for key in \ 5BE8A3F6C8A5C01D106C0AD820B1A390B168D356 \ DD792F5973C6DE52C432CBDAC77ABFA00DDBF2B7 \ CC68F5A3106FF448322E48ED27F5E38D5B0A215F \ 8FCCA13FEF1D0C2E91008E09770F7A9A5AE15600 \ 890C08DB8579162FEE0DF9DB8BEAB4DFCF555EF4 \ C82FA3AE1CBEDC6BE46B9360C43CEC45C17AB93C \ 108F52B48DB57BB0CC439B2997B01419BD92F80A \ A363A499291CBBC940DD62E41F10027AF002F8B0 \ ; do \ { gpg --batch --keyserver hkps://keys.openpgp.org --recv-keys "$key" && gpg --batch --fingerprint "$key"; } || \ { gpg --batch --keyserver keyserver.ubuntu.com --recv-keys "$key" && gpg --batch --fingerprint "$key"; } ; \ done \ && curl -fsSLO --compressed "https://nodejs.org/dist/v$NODE_VERSION/node-v$NODE_VERSION.tar.xz" \ && curl -fsSLO --compressed "https://nodejs.org/dist/v$NODE_VERSION/SHASUMS256.txt.asc" \ && gpg --batch --decrypt --output SHASUMS256.txt SHASUMS256.txt.asc \ && gpgconf --kill all \ && rm -rf "$GNUPGHOME" \ && grep " node-v$NODE_VERSION.tar.xz\$" SHASUMS256.txt | sha256sum -c - \ && tar -xf "node-v$NODE_VERSION.tar.xz" \ && cd "node-v$NODE_VERSION" \ && ./configure \ && make -j$(getconf _NPROCESSORS_ONLN) V= \ && make install \ && apk del .build-deps-full \ && cd .. \ && rm -Rf "node-v$NODE_VERSION" \ && rm "node-v$NODE_VERSION.tar.xz" SHASUMS256.txt.asc SHASUMS256.txt; \ fi \ && rm -f "node-v$NODE_VERSION-linux-$ARCH-musl.tar.xz" \ # Remove unused OpenSSL headers to save ~34MB. See this NodeJS issue: https://github.com/nodejs/node/issues/46451 && find /usr/local/include/node/openssl/archs -mindepth 1 -maxdepth 1 ! -name "$OPENSSL_ARCH" -exec rm -rf {} \; \ && apk del .build-deps \ # smoke tests && node --version \ && npm --version \ && rm -rf /tmp/* ENV YARN_VERSION=1.22.22 RUN apk add --no-cache --virtual .build-deps-yarn curl gnupg tar \ # use pre-existing gpg directory, see https://github.com/nodejs/docker-node/pull/1895#issuecomment-1550389150 && export GNUPGHOME="$(mktemp -d)" \ && for key in \ 6A010C5166006599AA17F08146C2130DFD2497F5 \ ; do \ { gpg --batch --keyserver hkps://keys.openpgp.org --recv-keys "$key" && gpg --batch --fingerprint "$key"; } || \ { gpg --batch --keyserver keyserver.ubuntu.com --recv-keys "$key" && gpg --batch --fingerprint "$key"; } ; \ done \ && curl -fsSLO --compressed "https://yarnpkg.com/downloads/$YARN_VERSION/yarn-v$YARN_VERSION.tar.gz" \ && curl -fsSLO --compressed "https://yarnpkg.com/downloads/$YARN_VERSION/yarn-v$YARN_VERSION.tar.gz.asc" \ && gpg --batch --verify yarn-v$YARN_VERSION.tar.gz.asc yarn-v$YARN_VERSION.tar.gz \ && gpgconf --kill all \ && rm -rf "$GNUPGHOME" \ && mkdir -p /opt \ && tar -xzf yarn-v$YARN_VERSION.tar.gz -C /opt/ \ && ln -s /opt/yarn-v$YARN_VERSION/bin/yarn /usr/local/bin/yarn \ && ln -s /opt/yarn-v$YARN_VERSION/bin/yarnpkg /usr/local/bin/yarnpkg \ && rm yarn-v$YARN_VERSION.tar.gz.asc yarn-v$YARN_VERSION.tar.gz \ && apk del .build-deps-yarn \ # smoke test && yarn --version \ && rm -rf /tmp/* COPY docker-entrypoint.sh /usr/local/bin/ ENTRYPOINT ["docker-entrypoint.sh"] CMD [ "node" ] ================================================ FILE: 22/alpine3.22/docker-entrypoint.sh ================================================ #!/bin/sh set -e # Run command with node if the first argument contains a "-" or is not a system command. The last # part inside the "{}" is a workaround for the following bug in ash/dash: # https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=874264 if [ "${1#-}" != "${1}" ] || [ -z "$(command -v "${1}")" ] || { [ -f "${1}" ] && ! [ -x "${1}" ]; }; then set -- node "$@" fi exec "$@" ================================================ FILE: 22/alpine3.23/Dockerfile ================================================ FROM alpine:3.23 ENV NODE_VERSION=22.22.1 RUN addgroup -g 1000 node \ && adduser -u 1000 -G node -s /bin/sh -D node \ && apk add --no-cache \ libstdc++ \ && apk add --no-cache --virtual .build-deps \ curl \ && ARCH= OPENSSL_ARCH='linux*' && alpineArch="$(apk --print-arch)" \ && case "${alpineArch##*-}" in \ x86_64) ARCH='x64' CHECKSUM="a06721f1566c89eb911546dba6309f7da6613dbcc67c0426588b1f39a7210a95" OPENSSL_ARCH=linux-x86_64;; \ x86) OPENSSL_ARCH=linux-elf;; \ aarch64) OPENSSL_ARCH=linux-aarch64;; \ arm*) OPENSSL_ARCH=linux-armv4;; \ ppc64le) OPENSSL_ARCH=linux-ppc64le;; \ s390x) OPENSSL_ARCH=linux-s390x;; \ *) ;; \ esac \ && if [ -n "${CHECKSUM}" ]; then \ set -eu; \ curl -fsSLO --compressed "https://unofficial-builds.nodejs.org/download/release/v$NODE_VERSION/node-v$NODE_VERSION-linux-$ARCH-musl.tar.xz"; \ echo "$CHECKSUM node-v$NODE_VERSION-linux-$ARCH-musl.tar.xz" | sha256sum -c - \ && tar -xJf "node-v$NODE_VERSION-linux-$ARCH-musl.tar.xz" -C /usr/local --strip-components=1 --no-same-owner \ && ln -s /usr/local/bin/node /usr/local/bin/nodejs; \ else \ echo "Building from source" \ # backup build && apk add --no-cache --virtual .build-deps-full \ binutils-gold \ g++ \ gcc \ gnupg \ libgcc \ linux-headers \ make \ python3 \ py-setuptools \ # use pre-existing gpg directory, see https://github.com/nodejs/docker-node/pull/1895#issuecomment-1550389150 && export GNUPGHOME="$(mktemp -d)" \ # gpg keys listed at https://github.com/nodejs/node#release-keys && for key in \ 5BE8A3F6C8A5C01D106C0AD820B1A390B168D356 \ DD792F5973C6DE52C432CBDAC77ABFA00DDBF2B7 \ CC68F5A3106FF448322E48ED27F5E38D5B0A215F \ 8FCCA13FEF1D0C2E91008E09770F7A9A5AE15600 \ 890C08DB8579162FEE0DF9DB8BEAB4DFCF555EF4 \ C82FA3AE1CBEDC6BE46B9360C43CEC45C17AB93C \ 108F52B48DB57BB0CC439B2997B01419BD92F80A \ A363A499291CBBC940DD62E41F10027AF002F8B0 \ ; do \ { gpg --batch --keyserver hkps://keys.openpgp.org --recv-keys "$key" && gpg --batch --fingerprint "$key"; } || \ { gpg --batch --keyserver keyserver.ubuntu.com --recv-keys "$key" && gpg --batch --fingerprint "$key"; } ; \ done \ && curl -fsSLO --compressed "https://nodejs.org/dist/v$NODE_VERSION/node-v$NODE_VERSION.tar.xz" \ && curl -fsSLO --compressed "https://nodejs.org/dist/v$NODE_VERSION/SHASUMS256.txt.asc" \ && gpg --batch --decrypt --output SHASUMS256.txt SHASUMS256.txt.asc \ && gpgconf --kill all \ && rm -rf "$GNUPGHOME" \ && grep " node-v$NODE_VERSION.tar.xz\$" SHASUMS256.txt | sha256sum -c - \ && tar -xf "node-v$NODE_VERSION.tar.xz" \ && cd "node-v$NODE_VERSION" \ && ./configure \ && make -j$(getconf _NPROCESSORS_ONLN) V= \ && make install \ && apk del .build-deps-full \ && cd .. \ && rm -Rf "node-v$NODE_VERSION" \ && rm "node-v$NODE_VERSION.tar.xz" SHASUMS256.txt.asc SHASUMS256.txt; \ fi \ && rm -f "node-v$NODE_VERSION-linux-$ARCH-musl.tar.xz" \ # Remove unused OpenSSL headers to save ~34MB. See this NodeJS issue: https://github.com/nodejs/node/issues/46451 && find /usr/local/include/node/openssl/archs -mindepth 1 -maxdepth 1 ! -name "$OPENSSL_ARCH" -exec rm -rf {} \; \ && apk del .build-deps \ # smoke tests && node --version \ && npm --version \ && rm -rf /tmp/* ENV YARN_VERSION=1.22.22 RUN apk add --no-cache --virtual .build-deps-yarn curl gnupg tar \ # use pre-existing gpg directory, see https://github.com/nodejs/docker-node/pull/1895#issuecomment-1550389150 && export GNUPGHOME="$(mktemp -d)" \ && for key in \ 6A010C5166006599AA17F08146C2130DFD2497F5 \ ; do \ { gpg --batch --keyserver hkps://keys.openpgp.org --recv-keys "$key" && gpg --batch --fingerprint "$key"; } || \ { gpg --batch --keyserver keyserver.ubuntu.com --recv-keys "$key" && gpg --batch --fingerprint "$key"; } ; \ done \ && curl -fsSLO --compressed "https://yarnpkg.com/downloads/$YARN_VERSION/yarn-v$YARN_VERSION.tar.gz" \ && curl -fsSLO --compressed "https://yarnpkg.com/downloads/$YARN_VERSION/yarn-v$YARN_VERSION.tar.gz.asc" \ && gpg --batch --verify yarn-v$YARN_VERSION.tar.gz.asc yarn-v$YARN_VERSION.tar.gz \ && gpgconf --kill all \ && rm -rf "$GNUPGHOME" \ && mkdir -p /opt \ && tar -xzf yarn-v$YARN_VERSION.tar.gz -C /opt/ \ && ln -s /opt/yarn-v$YARN_VERSION/bin/yarn /usr/local/bin/yarn \ && ln -s /opt/yarn-v$YARN_VERSION/bin/yarnpkg /usr/local/bin/yarnpkg \ && rm yarn-v$YARN_VERSION.tar.gz.asc yarn-v$YARN_VERSION.tar.gz \ && apk del .build-deps-yarn \ # smoke test && yarn --version \ && rm -rf /tmp/* COPY docker-entrypoint.sh /usr/local/bin/ ENTRYPOINT ["docker-entrypoint.sh"] CMD [ "node" ] ================================================ FILE: 22/alpine3.23/docker-entrypoint.sh ================================================ #!/bin/sh set -e # Run command with node if the first argument contains a "-" or is not a system command. The last # part inside the "{}" is a workaround for the following bug in ash/dash: # https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=874264 if [ "${1#-}" != "${1}" ] || [ -z "$(command -v "${1}")" ] || { [ -f "${1}" ] && ! [ -x "${1}" ]; }; then set -- node "$@" fi exec "$@" ================================================ FILE: 22/bookworm/Dockerfile ================================================ FROM buildpack-deps:bookworm RUN groupadd --gid 1000 node \ && useradd --uid 1000 --gid node --shell /bin/bash --create-home node ENV NODE_VERSION=22.22.1 RUN ARCH= && dpkgArch="$(dpkg --print-architecture)" \ && case "${dpkgArch##*-}" in \ amd64) ARCH='x64';; \ ppc64el) ARCH='ppc64le';; \ s390x) ARCH='s390x';; \ arm64) ARCH='arm64';; \ armhf) ARCH='armv7l';; \ i386) ARCH='x86';; \ *) echo "unsupported architecture"; exit 1 ;; \ esac \ # use pre-existing gpg directory, see https://github.com/nodejs/docker-node/pull/1895#issuecomment-1550389150 && export GNUPGHOME="$(mktemp -d)" \ # gpg keys listed at https://github.com/nodejs/node#release-keys && set -ex \ && for key in \ 5BE8A3F6C8A5C01D106C0AD820B1A390B168D356 \ DD792F5973C6DE52C432CBDAC77ABFA00DDBF2B7 \ CC68F5A3106FF448322E48ED27F5E38D5B0A215F \ 8FCCA13FEF1D0C2E91008E09770F7A9A5AE15600 \ 890C08DB8579162FEE0DF9DB8BEAB4DFCF555EF4 \ C82FA3AE1CBEDC6BE46B9360C43CEC45C17AB93C \ 108F52B48DB57BB0CC439B2997B01419BD92F80A \ A363A499291CBBC940DD62E41F10027AF002F8B0 \ ; do \ { gpg --batch --keyserver hkps://keys.openpgp.org --recv-keys "$key" && gpg --batch --fingerprint "$key"; } || \ { gpg --batch --keyserver keyserver.ubuntu.com --recv-keys "$key" && gpg --batch --fingerprint "$key"; } ; \ done \ && curl -fsSLO --compressed "https://nodejs.org/dist/v$NODE_VERSION/node-v$NODE_VERSION-linux-$ARCH.tar.xz" \ && curl -fsSLO --compressed "https://nodejs.org/dist/v$NODE_VERSION/SHASUMS256.txt.asc" \ && gpg --batch --decrypt --output SHASUMS256.txt SHASUMS256.txt.asc \ && gpgconf --kill all \ && rm -rf "$GNUPGHOME" \ && grep " node-v$NODE_VERSION-linux-$ARCH.tar.xz\$" SHASUMS256.txt | sha256sum -c - \ && tar -xJf "node-v$NODE_VERSION-linux-$ARCH.tar.xz" -C /usr/local --strip-components=1 --no-same-owner \ && rm "node-v$NODE_VERSION-linux-$ARCH.tar.xz" SHASUMS256.txt.asc SHASUMS256.txt \ && ln -s /usr/local/bin/node /usr/local/bin/nodejs \ # smoke tests && node --version \ && npm --version \ && rm -rf /tmp/* ENV YARN_VERSION=1.22.22 RUN set -ex \ # use pre-existing gpg directory, see https://github.com/nodejs/docker-node/pull/1895#issuecomment-1550389150 && export GNUPGHOME="$(mktemp -d)" \ && for key in \ 6A010C5166006599AA17F08146C2130DFD2497F5 \ ; do \ { gpg --batch --keyserver hkps://keys.openpgp.org --recv-keys "$key" && gpg --batch --fingerprint "$key"; } || \ { gpg --batch --keyserver keyserver.ubuntu.com --recv-keys "$key" && gpg --batch --fingerprint "$key"; } ; \ done \ && curl -fsSLO --compressed "https://yarnpkg.com/downloads/$YARN_VERSION/yarn-v$YARN_VERSION.tar.gz" \ && curl -fsSLO --compressed "https://yarnpkg.com/downloads/$YARN_VERSION/yarn-v$YARN_VERSION.tar.gz.asc" \ && gpg --batch --verify yarn-v$YARN_VERSION.tar.gz.asc yarn-v$YARN_VERSION.tar.gz \ && gpgconf --kill all \ && rm -rf "$GNUPGHOME" \ && mkdir -p /opt \ && tar -xzf yarn-v$YARN_VERSION.tar.gz -C /opt/ \ && ln -s /opt/yarn-v$YARN_VERSION/bin/yarn /usr/local/bin/yarn \ && ln -s /opt/yarn-v$YARN_VERSION/bin/yarnpkg /usr/local/bin/yarnpkg \ && rm yarn-v$YARN_VERSION.tar.gz.asc yarn-v$YARN_VERSION.tar.gz \ # smoke test && yarn --version \ && rm -rf /tmp/* COPY docker-entrypoint.sh /usr/local/bin/ ENTRYPOINT ["docker-entrypoint.sh"] CMD [ "node" ] ================================================ FILE: 22/bookworm/docker-entrypoint.sh ================================================ #!/bin/sh set -e # Run command with node if the first argument contains a "-" or is not a system command. The last # part inside the "{}" is a workaround for the following bug in ash/dash: # https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=874264 if [ "${1#-}" != "${1}" ] || [ -z "$(command -v "${1}")" ] || { [ -f "${1}" ] && ! [ -x "${1}" ]; }; then set -- node "$@" fi exec "$@" ================================================ FILE: 22/bookworm-slim/Dockerfile ================================================ FROM debian:bookworm-slim RUN groupadd --gid 1000 node \ && useradd --uid 1000 --gid node --shell /bin/bash --create-home node ENV NODE_VERSION=22.22.1 RUN ARCH= OPENSSL_ARCH= && dpkgArch="$(dpkg --print-architecture)" \ && case "${dpkgArch##*-}" in \ amd64) ARCH='x64' OPENSSL_ARCH='linux-x86_64';; \ ppc64el) ARCH='ppc64le' OPENSSL_ARCH='linux-ppc64le';; \ s390x) ARCH='s390x' OPENSSL_ARCH='linux*-s390x';; \ arm64) ARCH='arm64' OPENSSL_ARCH='linux-aarch64';; \ armhf) ARCH='armv7l' OPENSSL_ARCH='linux-armv4';; \ i386) ARCH='x86' OPENSSL_ARCH='linux-elf';; \ *) echo "unsupported architecture"; exit 1 ;; \ esac \ && set -ex \ # libatomic1 for arm && apt-get update && apt-get install -y ca-certificates curl wget gnupg dirmngr xz-utils libatomic1 --no-install-recommends \ && rm -rf /var/lib/apt/lists/* \ # use pre-existing gpg directory, see https://github.com/nodejs/docker-node/pull/1895#issuecomment-1550389150 && export GNUPGHOME="$(mktemp -d)" \ # gpg keys listed at https://github.com/nodejs/node#release-keys && for key in \ 5BE8A3F6C8A5C01D106C0AD820B1A390B168D356 \ DD792F5973C6DE52C432CBDAC77ABFA00DDBF2B7 \ CC68F5A3106FF448322E48ED27F5E38D5B0A215F \ 8FCCA13FEF1D0C2E91008E09770F7A9A5AE15600 \ 890C08DB8579162FEE0DF9DB8BEAB4DFCF555EF4 \ C82FA3AE1CBEDC6BE46B9360C43CEC45C17AB93C \ 108F52B48DB57BB0CC439B2997B01419BD92F80A \ A363A499291CBBC940DD62E41F10027AF002F8B0 \ ; do \ { gpg --batch --keyserver hkps://keys.openpgp.org --recv-keys "$key" && gpg --batch --fingerprint "$key"; } || \ { gpg --batch --keyserver keyserver.ubuntu.com --recv-keys "$key" && gpg --batch --fingerprint "$key"; } ; \ done \ && curl -fsSLO --compressed "https://nodejs.org/dist/v$NODE_VERSION/node-v$NODE_VERSION-linux-$ARCH.tar.xz" \ && curl -fsSLO --compressed "https://nodejs.org/dist/v$NODE_VERSION/SHASUMS256.txt.asc" \ && gpg --batch --decrypt --output SHASUMS256.txt SHASUMS256.txt.asc \ && gpgconf --kill all \ && rm -rf "$GNUPGHOME" \ && grep " node-v$NODE_VERSION-linux-$ARCH.tar.xz\$" SHASUMS256.txt | sha256sum -c - \ && tar -xJf "node-v$NODE_VERSION-linux-$ARCH.tar.xz" -C /usr/local --strip-components=1 --no-same-owner \ && rm "node-v$NODE_VERSION-linux-$ARCH.tar.xz" SHASUMS256.txt.asc SHASUMS256.txt \ # Remove unused OpenSSL headers to save ~34MB. See this NodeJS issue: https://github.com/nodejs/node/issues/46451 && find /usr/local/include/node/openssl/archs -mindepth 1 -maxdepth 1 ! -name "$OPENSSL_ARCH" -exec rm -rf {} \; \ && apt-mark auto '.*' > /dev/null \ && find /usr/local -type f -executable -exec ldd '{}' ';' \ | awk '/=>/ { so = $(NF-1); if (index(so, "/usr/local/") == 1) { next }; gsub("^/(usr/)?", "", so); print so }' \ | sort -u \ | xargs -r dpkg-query --search \ | cut -d: -f1 \ | sort -u \ | xargs -r apt-mark manual \ && apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false \ && ln -s /usr/local/bin/node /usr/local/bin/nodejs \ # smoke tests && node --version \ && npm --version \ && rm -rf /tmp/* ENV YARN_VERSION=1.22.22 RUN set -ex \ && savedAptMark="$(apt-mark showmanual)" \ && apt-get update && apt-get install -y ca-certificates curl wget gnupg dirmngr --no-install-recommends \ && rm -rf /var/lib/apt/lists/* \ # use pre-existing gpg directory, see https://github.com/nodejs/docker-node/pull/1895#issuecomment-1550389150 && export GNUPGHOME="$(mktemp -d)" \ && for key in \ 6A010C5166006599AA17F08146C2130DFD2497F5 \ ; do \ { gpg --batch --keyserver hkps://keys.openpgp.org --recv-keys "$key" && gpg --batch --fingerprint "$key"; } || \ { gpg --batch --keyserver keyserver.ubuntu.com --recv-keys "$key" && gpg --batch --fingerprint "$key"; } ; \ done \ && curl -fsSLO --compressed "https://yarnpkg.com/downloads/$YARN_VERSION/yarn-v$YARN_VERSION.tar.gz" \ && curl -fsSLO --compressed "https://yarnpkg.com/downloads/$YARN_VERSION/yarn-v$YARN_VERSION.tar.gz.asc" \ && gpg --batch --verify yarn-v$YARN_VERSION.tar.gz.asc yarn-v$YARN_VERSION.tar.gz \ && gpgconf --kill all \ && rm -rf "$GNUPGHOME" \ && mkdir -p /opt \ && tar -xzf yarn-v$YARN_VERSION.tar.gz -C /opt/ \ && ln -s /opt/yarn-v$YARN_VERSION/bin/yarn /usr/local/bin/yarn \ && ln -s /opt/yarn-v$YARN_VERSION/bin/yarnpkg /usr/local/bin/yarnpkg \ && rm yarn-v$YARN_VERSION.tar.gz.asc yarn-v$YARN_VERSION.tar.gz \ && apt-mark auto '.*' > /dev/null \ && { [ -z "$savedAptMark" ] || apt-mark manual $savedAptMark > /dev/null; } \ && find /usr/local -type f -executable -exec ldd '{}' ';' \ | awk '/=>/ { so = $(NF-1); if (index(so, "/usr/local/") == 1) { next }; gsub("^/(usr/)?", "", so); print so }' \ | sort -u \ | xargs -r dpkg-query --search \ | cut -d: -f1 \ | sort -u \ | xargs -r apt-mark manual \ && apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false \ # smoke test && yarn --version \ && rm -rf /tmp/* COPY docker-entrypoint.sh /usr/local/bin/ ENTRYPOINT ["docker-entrypoint.sh"] CMD [ "node" ] ================================================ FILE: 22/bookworm-slim/docker-entrypoint.sh ================================================ #!/bin/sh set -e # Run command with node if the first argument contains a "-" or is not a system command. The last # part inside the "{}" is a workaround for the following bug in ash/dash: # https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=874264 if [ "${1#-}" != "${1}" ] || [ -z "$(command -v "${1}")" ] || { [ -f "${1}" ] && ! [ -x "${1}" ]; }; then set -- node "$@" fi exec "$@" ================================================ FILE: 22/bullseye/Dockerfile ================================================ FROM buildpack-deps:bullseye RUN groupadd --gid 1000 node \ && useradd --uid 1000 --gid node --shell /bin/bash --create-home node ENV NODE_VERSION=22.22.1 RUN ARCH= && dpkgArch="$(dpkg --print-architecture)" \ && case "${dpkgArch##*-}" in \ amd64) ARCH='x64';; \ ppc64el) ARCH='ppc64le';; \ s390x) ARCH='s390x';; \ arm64) ARCH='arm64';; \ armhf) ARCH='armv7l';; \ i386) ARCH='x86';; \ *) echo "unsupported architecture"; exit 1 ;; \ esac \ # use pre-existing gpg directory, see https://github.com/nodejs/docker-node/pull/1895#issuecomment-1550389150 && export GNUPGHOME="$(mktemp -d)" \ # gpg keys listed at https://github.com/nodejs/node#release-keys && set -ex \ && for key in \ 5BE8A3F6C8A5C01D106C0AD820B1A390B168D356 \ DD792F5973C6DE52C432CBDAC77ABFA00DDBF2B7 \ CC68F5A3106FF448322E48ED27F5E38D5B0A215F \ 8FCCA13FEF1D0C2E91008E09770F7A9A5AE15600 \ 890C08DB8579162FEE0DF9DB8BEAB4DFCF555EF4 \ C82FA3AE1CBEDC6BE46B9360C43CEC45C17AB93C \ 108F52B48DB57BB0CC439B2997B01419BD92F80A \ A363A499291CBBC940DD62E41F10027AF002F8B0 \ ; do \ { gpg --batch --keyserver hkps://keys.openpgp.org --recv-keys "$key" && gpg --batch --fingerprint "$key"; } || \ { gpg --batch --keyserver keyserver.ubuntu.com --recv-keys "$key" && gpg --batch --fingerprint "$key"; } ; \ done \ && curl -fsSLO --compressed "https://nodejs.org/dist/v$NODE_VERSION/node-v$NODE_VERSION-linux-$ARCH.tar.xz" \ && curl -fsSLO --compressed "https://nodejs.org/dist/v$NODE_VERSION/SHASUMS256.txt.asc" \ && gpg --batch --decrypt --output SHASUMS256.txt SHASUMS256.txt.asc \ && gpgconf --kill all \ && rm -rf "$GNUPGHOME" \ && grep " node-v$NODE_VERSION-linux-$ARCH.tar.xz\$" SHASUMS256.txt | sha256sum -c - \ && tar -xJf "node-v$NODE_VERSION-linux-$ARCH.tar.xz" -C /usr/local --strip-components=1 --no-same-owner \ && rm "node-v$NODE_VERSION-linux-$ARCH.tar.xz" SHASUMS256.txt.asc SHASUMS256.txt \ && ln -s /usr/local/bin/node /usr/local/bin/nodejs \ # smoke tests && node --version \ && npm --version \ && rm -rf /tmp/* ENV YARN_VERSION=1.22.22 RUN set -ex \ # use pre-existing gpg directory, see https://github.com/nodejs/docker-node/pull/1895#issuecomment-1550389150 && export GNUPGHOME="$(mktemp -d)" \ && for key in \ 6A010C5166006599AA17F08146C2130DFD2497F5 \ ; do \ { gpg --batch --keyserver hkps://keys.openpgp.org --recv-keys "$key" && gpg --batch --fingerprint "$key"; } || \ { gpg --batch --keyserver keyserver.ubuntu.com --recv-keys "$key" && gpg --batch --fingerprint "$key"; } ; \ done \ && curl -fsSLO --compressed "https://yarnpkg.com/downloads/$YARN_VERSION/yarn-v$YARN_VERSION.tar.gz" \ && curl -fsSLO --compressed "https://yarnpkg.com/downloads/$YARN_VERSION/yarn-v$YARN_VERSION.tar.gz.asc" \ && gpg --batch --verify yarn-v$YARN_VERSION.tar.gz.asc yarn-v$YARN_VERSION.tar.gz \ && gpgconf --kill all \ && rm -rf "$GNUPGHOME" \ && mkdir -p /opt \ && tar -xzf yarn-v$YARN_VERSION.tar.gz -C /opt/ \ && ln -s /opt/yarn-v$YARN_VERSION/bin/yarn /usr/local/bin/yarn \ && ln -s /opt/yarn-v$YARN_VERSION/bin/yarnpkg /usr/local/bin/yarnpkg \ && rm yarn-v$YARN_VERSION.tar.gz.asc yarn-v$YARN_VERSION.tar.gz \ # smoke test && yarn --version \ && rm -rf /tmp/* COPY docker-entrypoint.sh /usr/local/bin/ ENTRYPOINT ["docker-entrypoint.sh"] CMD [ "node" ] ================================================ FILE: 22/bullseye/docker-entrypoint.sh ================================================ #!/bin/sh set -e # Run command with node if the first argument contains a "-" or is not a system command. The last # part inside the "{}" is a workaround for the following bug in ash/dash: # https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=874264 if [ "${1#-}" != "${1}" ] || [ -z "$(command -v "${1}")" ] || { [ -f "${1}" ] && ! [ -x "${1}" ]; }; then set -- node "$@" fi exec "$@" ================================================ FILE: 22/bullseye-slim/Dockerfile ================================================ FROM debian:bullseye-slim RUN groupadd --gid 1000 node \ && useradd --uid 1000 --gid node --shell /bin/bash --create-home node ENV NODE_VERSION=22.22.1 RUN ARCH= OPENSSL_ARCH= && dpkgArch="$(dpkg --print-architecture)" \ && case "${dpkgArch##*-}" in \ amd64) ARCH='x64' OPENSSL_ARCH='linux-x86_64';; \ ppc64el) ARCH='ppc64le' OPENSSL_ARCH='linux-ppc64le';; \ s390x) ARCH='s390x' OPENSSL_ARCH='linux*-s390x';; \ arm64) ARCH='arm64' OPENSSL_ARCH='linux-aarch64';; \ armhf) ARCH='armv7l' OPENSSL_ARCH='linux-armv4';; \ i386) ARCH='x86' OPENSSL_ARCH='linux-elf';; \ *) echo "unsupported architecture"; exit 1 ;; \ esac \ && set -ex \ # libatomic1 for arm && apt-get update && apt-get install -y ca-certificates curl wget gnupg dirmngr xz-utils libatomic1 --no-install-recommends \ && rm -rf /var/lib/apt/lists/* \ # use pre-existing gpg directory, see https://github.com/nodejs/docker-node/pull/1895#issuecomment-1550389150 && export GNUPGHOME="$(mktemp -d)" \ # gpg keys listed at https://github.com/nodejs/node#release-keys && for key in \ 5BE8A3F6C8A5C01D106C0AD820B1A390B168D356 \ DD792F5973C6DE52C432CBDAC77ABFA00DDBF2B7 \ CC68F5A3106FF448322E48ED27F5E38D5B0A215F \ 8FCCA13FEF1D0C2E91008E09770F7A9A5AE15600 \ 890C08DB8579162FEE0DF9DB8BEAB4DFCF555EF4 \ C82FA3AE1CBEDC6BE46B9360C43CEC45C17AB93C \ 108F52B48DB57BB0CC439B2997B01419BD92F80A \ A363A499291CBBC940DD62E41F10027AF002F8B0 \ ; do \ { gpg --batch --keyserver hkps://keys.openpgp.org --recv-keys "$key" && gpg --batch --fingerprint "$key"; } || \ { gpg --batch --keyserver keyserver.ubuntu.com --recv-keys "$key" && gpg --batch --fingerprint "$key"; } ; \ done \ && curl -fsSLO --compressed "https://nodejs.org/dist/v$NODE_VERSION/node-v$NODE_VERSION-linux-$ARCH.tar.xz" \ && curl -fsSLO --compressed "https://nodejs.org/dist/v$NODE_VERSION/SHASUMS256.txt.asc" \ && gpg --batch --decrypt --output SHASUMS256.txt SHASUMS256.txt.asc \ && gpgconf --kill all \ && rm -rf "$GNUPGHOME" \ && grep " node-v$NODE_VERSION-linux-$ARCH.tar.xz\$" SHASUMS256.txt | sha256sum -c - \ && tar -xJf "node-v$NODE_VERSION-linux-$ARCH.tar.xz" -C /usr/local --strip-components=1 --no-same-owner \ && rm "node-v$NODE_VERSION-linux-$ARCH.tar.xz" SHASUMS256.txt.asc SHASUMS256.txt \ # Remove unused OpenSSL headers to save ~34MB. See this NodeJS issue: https://github.com/nodejs/node/issues/46451 && find /usr/local/include/node/openssl/archs -mindepth 1 -maxdepth 1 ! -name "$OPENSSL_ARCH" -exec rm -rf {} \; \ && apt-mark auto '.*' > /dev/null \ && find /usr/local -type f -executable -exec ldd '{}' ';' \ | awk '/=>/ { so = $(NF-1); if (index(so, "/usr/local/") == 1) { next }; gsub("^/(usr/)?", "", so); print so }' \ | sort -u \ | xargs -r dpkg-query --search \ | cut -d: -f1 \ | sort -u \ | xargs -r apt-mark manual \ && apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false \ && ln -s /usr/local/bin/node /usr/local/bin/nodejs \ # smoke tests && node --version \ && npm --version \ && rm -rf /tmp/* ENV YARN_VERSION=1.22.22 RUN set -ex \ && savedAptMark="$(apt-mark showmanual)" \ && apt-get update && apt-get install -y ca-certificates curl wget gnupg dirmngr --no-install-recommends \ && rm -rf /var/lib/apt/lists/* \ # use pre-existing gpg directory, see https://github.com/nodejs/docker-node/pull/1895#issuecomment-1550389150 && export GNUPGHOME="$(mktemp -d)" \ && for key in \ 6A010C5166006599AA17F08146C2130DFD2497F5 \ ; do \ { gpg --batch --keyserver hkps://keys.openpgp.org --recv-keys "$key" && gpg --batch --fingerprint "$key"; } || \ { gpg --batch --keyserver keyserver.ubuntu.com --recv-keys "$key" && gpg --batch --fingerprint "$key"; } ; \ done \ && curl -fsSLO --compressed "https://yarnpkg.com/downloads/$YARN_VERSION/yarn-v$YARN_VERSION.tar.gz" \ && curl -fsSLO --compressed "https://yarnpkg.com/downloads/$YARN_VERSION/yarn-v$YARN_VERSION.tar.gz.asc" \ && gpg --batch --verify yarn-v$YARN_VERSION.tar.gz.asc yarn-v$YARN_VERSION.tar.gz \ && gpgconf --kill all \ && rm -rf "$GNUPGHOME" \ && mkdir -p /opt \ && tar -xzf yarn-v$YARN_VERSION.tar.gz -C /opt/ \ && ln -s /opt/yarn-v$YARN_VERSION/bin/yarn /usr/local/bin/yarn \ && ln -s /opt/yarn-v$YARN_VERSION/bin/yarnpkg /usr/local/bin/yarnpkg \ && rm yarn-v$YARN_VERSION.tar.gz.asc yarn-v$YARN_VERSION.tar.gz \ && apt-mark auto '.*' > /dev/null \ && { [ -z "$savedAptMark" ] || apt-mark manual $savedAptMark > /dev/null; } \ && find /usr/local -type f -executable -exec ldd '{}' ';' \ | awk '/=>/ { so = $(NF-1); if (index(so, "/usr/local/") == 1) { next }; gsub("^/(usr/)?", "", so); print so }' \ | sort -u \ | xargs -r dpkg-query --search \ | cut -d: -f1 \ | sort -u \ | xargs -r apt-mark manual \ && apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false \ # smoke test && yarn --version \ && rm -rf /tmp/* COPY docker-entrypoint.sh /usr/local/bin/ ENTRYPOINT ["docker-entrypoint.sh"] CMD [ "node" ] ================================================ FILE: 22/bullseye-slim/docker-entrypoint.sh ================================================ #!/bin/sh set -e # Run command with node if the first argument contains a "-" or is not a system command. The last # part inside the "{}" is a workaround for the following bug in ash/dash: # https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=874264 if [ "${1#-}" != "${1}" ] || [ -z "$(command -v "${1}")" ] || { [ -f "${1}" ] && ! [ -x "${1}" ]; }; then set -- node "$@" fi exec "$@" ================================================ FILE: 22/trixie/Dockerfile ================================================ FROM buildpack-deps:trixie RUN groupadd --gid 1000 node \ && useradd --uid 1000 --gid node --shell /bin/bash --create-home node ENV NODE_VERSION=22.22.1 RUN ARCH= && dpkgArch="$(dpkg --print-architecture)" \ && case "${dpkgArch##*-}" in \ amd64) ARCH='x64';; \ ppc64el) ARCH='ppc64le';; \ s390x) ARCH='s390x';; \ arm64) ARCH='arm64';; \ armhf) ARCH='armv7l';; \ i386) ARCH='x86';; \ *) echo "unsupported architecture"; exit 1 ;; \ esac \ # use pre-existing gpg directory, see https://github.com/nodejs/docker-node/pull/1895#issuecomment-1550389150 && export GNUPGHOME="$(mktemp -d)" \ # gpg keys listed at https://github.com/nodejs/node#release-keys && set -ex \ && for key in \ 5BE8A3F6C8A5C01D106C0AD820B1A390B168D356 \ DD792F5973C6DE52C432CBDAC77ABFA00DDBF2B7 \ CC68F5A3106FF448322E48ED27F5E38D5B0A215F \ 8FCCA13FEF1D0C2E91008E09770F7A9A5AE15600 \ 890C08DB8579162FEE0DF9DB8BEAB4DFCF555EF4 \ C82FA3AE1CBEDC6BE46B9360C43CEC45C17AB93C \ 108F52B48DB57BB0CC439B2997B01419BD92F80A \ A363A499291CBBC940DD62E41F10027AF002F8B0 \ ; do \ { gpg --batch --keyserver hkps://keys.openpgp.org --recv-keys "$key" && gpg --batch --fingerprint "$key"; } || \ { gpg --batch --keyserver keyserver.ubuntu.com --recv-keys "$key" && gpg --batch --fingerprint "$key"; } ; \ done \ && curl -fsSLO --compressed "https://nodejs.org/dist/v$NODE_VERSION/node-v$NODE_VERSION-linux-$ARCH.tar.xz" \ && curl -fsSLO --compressed "https://nodejs.org/dist/v$NODE_VERSION/SHASUMS256.txt.asc" \ && gpg --batch --decrypt --output SHASUMS256.txt SHASUMS256.txt.asc \ && gpgconf --kill all \ && rm -rf "$GNUPGHOME" \ && grep " node-v$NODE_VERSION-linux-$ARCH.tar.xz\$" SHASUMS256.txt | sha256sum -c - \ && tar -xJf "node-v$NODE_VERSION-linux-$ARCH.tar.xz" -C /usr/local --strip-components=1 --no-same-owner \ && rm "node-v$NODE_VERSION-linux-$ARCH.tar.xz" SHASUMS256.txt.asc SHASUMS256.txt \ && ln -s /usr/local/bin/node /usr/local/bin/nodejs \ # smoke tests && node --version \ && npm --version \ && rm -rf /tmp/* ENV YARN_VERSION=1.22.22 RUN set -ex \ # use pre-existing gpg directory, see https://github.com/nodejs/docker-node/pull/1895#issuecomment-1550389150 && export GNUPGHOME="$(mktemp -d)" \ && for key in \ 6A010C5166006599AA17F08146C2130DFD2497F5 \ ; do \ { gpg --batch --keyserver hkps://keys.openpgp.org --recv-keys "$key" && gpg --batch --fingerprint "$key"; } || \ { gpg --batch --keyserver keyserver.ubuntu.com --recv-keys "$key" && gpg --batch --fingerprint "$key"; } ; \ done \ && curl -fsSLO --compressed "https://yarnpkg.com/downloads/$YARN_VERSION/yarn-v$YARN_VERSION.tar.gz" \ && curl -fsSLO --compressed "https://yarnpkg.com/downloads/$YARN_VERSION/yarn-v$YARN_VERSION.tar.gz.asc" \ && gpg --batch --verify yarn-v$YARN_VERSION.tar.gz.asc yarn-v$YARN_VERSION.tar.gz \ && gpgconf --kill all \ && rm -rf "$GNUPGHOME" \ && mkdir -p /opt \ && tar -xzf yarn-v$YARN_VERSION.tar.gz -C /opt/ \ && ln -s /opt/yarn-v$YARN_VERSION/bin/yarn /usr/local/bin/yarn \ && ln -s /opt/yarn-v$YARN_VERSION/bin/yarnpkg /usr/local/bin/yarnpkg \ && rm yarn-v$YARN_VERSION.tar.gz.asc yarn-v$YARN_VERSION.tar.gz \ # smoke test && yarn --version \ && rm -rf /tmp/* COPY docker-entrypoint.sh /usr/local/bin/ ENTRYPOINT ["docker-entrypoint.sh"] CMD [ "node" ] ================================================ FILE: 22/trixie/docker-entrypoint.sh ================================================ #!/bin/sh set -e # Run command with node if the first argument contains a "-" or is not a system command. The last # part inside the "{}" is a workaround for the following bug in ash/dash: # https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=874264 if [ "${1#-}" != "${1}" ] || [ -z "$(command -v "${1}")" ] || { [ -f "${1}" ] && ! [ -x "${1}" ]; }; then set -- node "$@" fi exec "$@" ================================================ FILE: 22/trixie-slim/Dockerfile ================================================ FROM debian:trixie-slim RUN groupadd --gid 1000 node \ && useradd --uid 1000 --gid node --shell /bin/bash --create-home node ENV NODE_VERSION=22.22.1 RUN ARCH= OPENSSL_ARCH= && dpkgArch="$(dpkg --print-architecture)" \ && case "${dpkgArch##*-}" in \ amd64) ARCH='x64' OPENSSL_ARCH='linux-x86_64';; \ ppc64el) ARCH='ppc64le' OPENSSL_ARCH='linux-ppc64le';; \ s390x) ARCH='s390x' OPENSSL_ARCH='linux*-s390x';; \ arm64) ARCH='arm64' OPENSSL_ARCH='linux-aarch64';; \ armhf) ARCH='armv7l' OPENSSL_ARCH='linux-armv4';; \ i386) ARCH='x86' OPENSSL_ARCH='linux-elf';; \ *) echo "unsupported architecture"; exit 1 ;; \ esac \ && set -ex \ # libatomic1 for arm && apt-get update && apt-get install -y ca-certificates curl wget gnupg dirmngr xz-utils libatomic1 --no-install-recommends \ && rm -rf /var/lib/apt/lists/* \ # use pre-existing gpg directory, see https://github.com/nodejs/docker-node/pull/1895#issuecomment-1550389150 && export GNUPGHOME="$(mktemp -d)" \ # gpg keys listed at https://github.com/nodejs/node#release-keys && for key in \ 5BE8A3F6C8A5C01D106C0AD820B1A390B168D356 \ DD792F5973C6DE52C432CBDAC77ABFA00DDBF2B7 \ CC68F5A3106FF448322E48ED27F5E38D5B0A215F \ 8FCCA13FEF1D0C2E91008E09770F7A9A5AE15600 \ 890C08DB8579162FEE0DF9DB8BEAB4DFCF555EF4 \ C82FA3AE1CBEDC6BE46B9360C43CEC45C17AB93C \ 108F52B48DB57BB0CC439B2997B01419BD92F80A \ A363A499291CBBC940DD62E41F10027AF002F8B0 \ ; do \ { gpg --batch --keyserver hkps://keys.openpgp.org --recv-keys "$key" && gpg --batch --fingerprint "$key"; } || \ { gpg --batch --keyserver keyserver.ubuntu.com --recv-keys "$key" && gpg --batch --fingerprint "$key"; } ; \ done \ && curl -fsSLO --compressed "https://nodejs.org/dist/v$NODE_VERSION/node-v$NODE_VERSION-linux-$ARCH.tar.xz" \ && curl -fsSLO --compressed "https://nodejs.org/dist/v$NODE_VERSION/SHASUMS256.txt.asc" \ && gpg --batch --decrypt --output SHASUMS256.txt SHASUMS256.txt.asc \ && gpgconf --kill all \ && rm -rf "$GNUPGHOME" \ && grep " node-v$NODE_VERSION-linux-$ARCH.tar.xz\$" SHASUMS256.txt | sha256sum -c - \ && tar -xJf "node-v$NODE_VERSION-linux-$ARCH.tar.xz" -C /usr/local --strip-components=1 --no-same-owner \ && rm "node-v$NODE_VERSION-linux-$ARCH.tar.xz" SHASUMS256.txt.asc SHASUMS256.txt \ # Remove unused OpenSSL headers to save ~34MB. See this NodeJS issue: https://github.com/nodejs/node/issues/46451 && find /usr/local/include/node/openssl/archs -mindepth 1 -maxdepth 1 ! -name "$OPENSSL_ARCH" -exec rm -rf {} \; \ && apt-mark auto '.*' > /dev/null \ && find /usr/local -type f -executable -exec ldd '{}' ';' \ | awk '/=>/ { so = $(NF-1); if (index(so, "/usr/local/") == 1) { next }; gsub("^/(usr/)?", "", so); print so }' \ | sort -u \ | xargs -r dpkg-query --search \ | cut -d: -f1 \ | sort -u \ | xargs -r apt-mark manual \ && apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false \ && ln -s /usr/local/bin/node /usr/local/bin/nodejs \ # smoke tests && node --version \ && npm --version \ && rm -rf /tmp/* ENV YARN_VERSION=1.22.22 RUN set -ex \ && savedAptMark="$(apt-mark showmanual)" \ && apt-get update && apt-get install -y ca-certificates curl wget gnupg dirmngr --no-install-recommends \ && rm -rf /var/lib/apt/lists/* \ # use pre-existing gpg directory, see https://github.com/nodejs/docker-node/pull/1895#issuecomment-1550389150 && export GNUPGHOME="$(mktemp -d)" \ && for key in \ 6A010C5166006599AA17F08146C2130DFD2497F5 \ ; do \ { gpg --batch --keyserver hkps://keys.openpgp.org --recv-keys "$key" && gpg --batch --fingerprint "$key"; } || \ { gpg --batch --keyserver keyserver.ubuntu.com --recv-keys "$key" && gpg --batch --fingerprint "$key"; } ; \ done \ && curl -fsSLO --compressed "https://yarnpkg.com/downloads/$YARN_VERSION/yarn-v$YARN_VERSION.tar.gz" \ && curl -fsSLO --compressed "https://yarnpkg.com/downloads/$YARN_VERSION/yarn-v$YARN_VERSION.tar.gz.asc" \ && gpg --batch --verify yarn-v$YARN_VERSION.tar.gz.asc yarn-v$YARN_VERSION.tar.gz \ && gpgconf --kill all \ && rm -rf "$GNUPGHOME" \ && mkdir -p /opt \ && tar -xzf yarn-v$YARN_VERSION.tar.gz -C /opt/ \ && ln -s /opt/yarn-v$YARN_VERSION/bin/yarn /usr/local/bin/yarn \ && ln -s /opt/yarn-v$YARN_VERSION/bin/yarnpkg /usr/local/bin/yarnpkg \ && rm yarn-v$YARN_VERSION.tar.gz.asc yarn-v$YARN_VERSION.tar.gz \ && apt-mark auto '.*' > /dev/null \ && { [ -z "$savedAptMark" ] || apt-mark manual $savedAptMark > /dev/null; } \ && find /usr/local -type f -executable -exec ldd '{}' ';' \ | awk '/=>/ { so = $(NF-1); if (index(so, "/usr/local/") == 1) { next }; gsub("^/(usr/)?", "", so); print so }' \ | sort -u \ | xargs -r dpkg-query --search \ | cut -d: -f1 \ | sort -u \ | xargs -r apt-mark manual \ && apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false \ # smoke test && yarn --version \ && rm -rf /tmp/* COPY docker-entrypoint.sh /usr/local/bin/ ENTRYPOINT ["docker-entrypoint.sh"] CMD [ "node" ] ================================================ FILE: 22/trixie-slim/docker-entrypoint.sh ================================================ #!/bin/sh set -e # Run command with node if the first argument contains a "-" or is not a system command. The last # part inside the "{}" is a workaround for the following bug in ash/dash: # https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=874264 if [ "${1#-}" != "${1}" ] || [ -z "$(command -v "${1}")" ] || { [ -f "${1}" ] && ! [ -x "${1}" ]; }; then set -- node "$@" fi exec "$@" ================================================ FILE: 24/alpine3.22/Dockerfile ================================================ FROM alpine:3.22 ENV NODE_VERSION=24.14.0 RUN addgroup -g 1000 node \ && adduser -u 1000 -G node -s /bin/sh -D node \ && apk add --no-cache \ libstdc++ \ && apk add --no-cache --virtual .build-deps \ curl \ && ARCH= OPENSSL_ARCH='linux*' && alpineArch="$(apk --print-arch)" \ && case "${alpineArch##*-}" in \ x86_64) ARCH='x64' CHECKSUM="13f20e78c40b543be47dc9597da06447c5d56282f8ffe10852d2a4dd86b63731" OPENSSL_ARCH=linux-x86_64;; \ x86) OPENSSL_ARCH=linux-elf;; \ aarch64) OPENSSL_ARCH=linux-aarch64;; \ arm*) OPENSSL_ARCH=linux-armv4;; \ ppc64le) OPENSSL_ARCH=linux-ppc64le;; \ s390x) OPENSSL_ARCH=linux-s390x;; \ *) ;; \ esac \ && if [ -n "${CHECKSUM}" ]; then \ set -eu; \ curl -fsSLO --compressed "https://unofficial-builds.nodejs.org/download/release/v$NODE_VERSION/node-v$NODE_VERSION-linux-$ARCH-musl.tar.xz"; \ echo "$CHECKSUM node-v$NODE_VERSION-linux-$ARCH-musl.tar.xz" | sha256sum -c - \ && tar -xJf "node-v$NODE_VERSION-linux-$ARCH-musl.tar.xz" -C /usr/local --strip-components=1 --no-same-owner \ && ln -s /usr/local/bin/node /usr/local/bin/nodejs; \ else \ echo "Building from source" \ # backup build && apk add --no-cache --virtual .build-deps-full \ binutils-gold \ g++ \ gcc \ gnupg \ libgcc \ linux-headers \ make \ python3 \ py-setuptools \ # use pre-existing gpg directory, see https://github.com/nodejs/docker-node/pull/1895#issuecomment-1550389150 && export GNUPGHOME="$(mktemp -d)" \ # gpg keys listed at https://github.com/nodejs/node#release-keys && for key in \ 5BE8A3F6C8A5C01D106C0AD820B1A390B168D356 \ DD792F5973C6DE52C432CBDAC77ABFA00DDBF2B7 \ CC68F5A3106FF448322E48ED27F5E38D5B0A215F \ 8FCCA13FEF1D0C2E91008E09770F7A9A5AE15600 \ 890C08DB8579162FEE0DF9DB8BEAB4DFCF555EF4 \ C82FA3AE1CBEDC6BE46B9360C43CEC45C17AB93C \ 108F52B48DB57BB0CC439B2997B01419BD92F80A \ A363A499291CBBC940DD62E41F10027AF002F8B0 \ ; do \ { gpg --batch --keyserver hkps://keys.openpgp.org --recv-keys "$key" && gpg --batch --fingerprint "$key"; } || \ { gpg --batch --keyserver keyserver.ubuntu.com --recv-keys "$key" && gpg --batch --fingerprint "$key"; } ; \ done \ && curl -fsSLO --compressed "https://nodejs.org/dist/v$NODE_VERSION/node-v$NODE_VERSION.tar.xz" \ && curl -fsSLO --compressed "https://nodejs.org/dist/v$NODE_VERSION/SHASUMS256.txt.asc" \ && gpg --batch --decrypt --output SHASUMS256.txt SHASUMS256.txt.asc \ && gpgconf --kill all \ && rm -rf "$GNUPGHOME" \ && grep " node-v$NODE_VERSION.tar.xz\$" SHASUMS256.txt | sha256sum -c - \ && tar -xf "node-v$NODE_VERSION.tar.xz" \ && cd "node-v$NODE_VERSION" \ && ./configure \ && make -j$(getconf _NPROCESSORS_ONLN) V= \ && make install \ && apk del .build-deps-full \ && cd .. \ && rm -Rf "node-v$NODE_VERSION" \ && rm "node-v$NODE_VERSION.tar.xz" SHASUMS256.txt.asc SHASUMS256.txt; \ fi \ && rm -f "node-v$NODE_VERSION-linux-$ARCH-musl.tar.xz" \ # Remove unused OpenSSL headers to save ~34MB. See this NodeJS issue: https://github.com/nodejs/node/issues/46451 && find /usr/local/include/node/openssl/archs -mindepth 1 -maxdepth 1 ! -name "$OPENSSL_ARCH" -exec rm -rf {} \; \ && apk del .build-deps \ # smoke tests && node --version \ && npm --version \ && rm -rf /tmp/* ENV YARN_VERSION=1.22.22 RUN apk add --no-cache --virtual .build-deps-yarn curl gnupg tar \ # use pre-existing gpg directory, see https://github.com/nodejs/docker-node/pull/1895#issuecomment-1550389150 && export GNUPGHOME="$(mktemp -d)" \ && for key in \ 6A010C5166006599AA17F08146C2130DFD2497F5 \ ; do \ { gpg --batch --keyserver hkps://keys.openpgp.org --recv-keys "$key" && gpg --batch --fingerprint "$key"; } || \ { gpg --batch --keyserver keyserver.ubuntu.com --recv-keys "$key" && gpg --batch --fingerprint "$key"; } ; \ done \ && curl -fsSLO --compressed "https://yarnpkg.com/downloads/$YARN_VERSION/yarn-v$YARN_VERSION.tar.gz" \ && curl -fsSLO --compressed "https://yarnpkg.com/downloads/$YARN_VERSION/yarn-v$YARN_VERSION.tar.gz.asc" \ && gpg --batch --verify yarn-v$YARN_VERSION.tar.gz.asc yarn-v$YARN_VERSION.tar.gz \ && gpgconf --kill all \ && rm -rf "$GNUPGHOME" \ && mkdir -p /opt \ && tar -xzf yarn-v$YARN_VERSION.tar.gz -C /opt/ \ && ln -s /opt/yarn-v$YARN_VERSION/bin/yarn /usr/local/bin/yarn \ && ln -s /opt/yarn-v$YARN_VERSION/bin/yarnpkg /usr/local/bin/yarnpkg \ && rm yarn-v$YARN_VERSION.tar.gz.asc yarn-v$YARN_VERSION.tar.gz \ && apk del .build-deps-yarn \ # smoke test && yarn --version \ && rm -rf /tmp/* COPY docker-entrypoint.sh /usr/local/bin/ ENTRYPOINT ["docker-entrypoint.sh"] CMD [ "node" ] ================================================ FILE: 24/alpine3.22/docker-entrypoint.sh ================================================ #!/bin/sh set -e # Run command with node if the first argument contains a "-" or is not a system command. The last # part inside the "{}" is a workaround for the following bug in ash/dash: # https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=874264 if [ "${1#-}" != "${1}" ] || [ -z "$(command -v "${1}")" ] || { [ -f "${1}" ] && ! [ -x "${1}" ]; }; then set -- node "$@" fi exec "$@" ================================================ FILE: 24/alpine3.23/Dockerfile ================================================ FROM alpine:3.23 ENV NODE_VERSION=24.14.0 RUN addgroup -g 1000 node \ && adduser -u 1000 -G node -s /bin/sh -D node \ && apk add --no-cache \ libstdc++ \ && apk add --no-cache --virtual .build-deps \ curl \ && ARCH= OPENSSL_ARCH='linux*' && alpineArch="$(apk --print-arch)" \ && case "${alpineArch##*-}" in \ x86_64) ARCH='x64' CHECKSUM="13f20e78c40b543be47dc9597da06447c5d56282f8ffe10852d2a4dd86b63731" OPENSSL_ARCH=linux-x86_64;; \ x86) OPENSSL_ARCH=linux-elf;; \ aarch64) OPENSSL_ARCH=linux-aarch64;; \ arm*) OPENSSL_ARCH=linux-armv4;; \ ppc64le) OPENSSL_ARCH=linux-ppc64le;; \ s390x) OPENSSL_ARCH=linux-s390x;; \ *) ;; \ esac \ && if [ -n "${CHECKSUM}" ]; then \ set -eu; \ curl -fsSLO --compressed "https://unofficial-builds.nodejs.org/download/release/v$NODE_VERSION/node-v$NODE_VERSION-linux-$ARCH-musl.tar.xz"; \ echo "$CHECKSUM node-v$NODE_VERSION-linux-$ARCH-musl.tar.xz" | sha256sum -c - \ && tar -xJf "node-v$NODE_VERSION-linux-$ARCH-musl.tar.xz" -C /usr/local --strip-components=1 --no-same-owner \ && ln -s /usr/local/bin/node /usr/local/bin/nodejs; \ else \ echo "Building from source" \ # backup build && apk add --no-cache --virtual .build-deps-full \ binutils-gold \ g++ \ gcc \ gnupg \ libgcc \ linux-headers \ make \ python3 \ py-setuptools \ # use pre-existing gpg directory, see https://github.com/nodejs/docker-node/pull/1895#issuecomment-1550389150 && export GNUPGHOME="$(mktemp -d)" \ # gpg keys listed at https://github.com/nodejs/node#release-keys && for key in \ 5BE8A3F6C8A5C01D106C0AD820B1A390B168D356 \ DD792F5973C6DE52C432CBDAC77ABFA00DDBF2B7 \ CC68F5A3106FF448322E48ED27F5E38D5B0A215F \ 8FCCA13FEF1D0C2E91008E09770F7A9A5AE15600 \ 890C08DB8579162FEE0DF9DB8BEAB4DFCF555EF4 \ C82FA3AE1CBEDC6BE46B9360C43CEC45C17AB93C \ 108F52B48DB57BB0CC439B2997B01419BD92F80A \ A363A499291CBBC940DD62E41F10027AF002F8B0 \ ; do \ { gpg --batch --keyserver hkps://keys.openpgp.org --recv-keys "$key" && gpg --batch --fingerprint "$key"; } || \ { gpg --batch --keyserver keyserver.ubuntu.com --recv-keys "$key" && gpg --batch --fingerprint "$key"; } ; \ done \ && curl -fsSLO --compressed "https://nodejs.org/dist/v$NODE_VERSION/node-v$NODE_VERSION.tar.xz" \ && curl -fsSLO --compressed "https://nodejs.org/dist/v$NODE_VERSION/SHASUMS256.txt.asc" \ && gpg --batch --decrypt --output SHASUMS256.txt SHASUMS256.txt.asc \ && gpgconf --kill all \ && rm -rf "$GNUPGHOME" \ && grep " node-v$NODE_VERSION.tar.xz\$" SHASUMS256.txt | sha256sum -c - \ && tar -xf "node-v$NODE_VERSION.tar.xz" \ && cd "node-v$NODE_VERSION" \ && ./configure \ && make -j$(getconf _NPROCESSORS_ONLN) V= \ && make install \ && apk del .build-deps-full \ && cd .. \ && rm -Rf "node-v$NODE_VERSION" \ && rm "node-v$NODE_VERSION.tar.xz" SHASUMS256.txt.asc SHASUMS256.txt; \ fi \ && rm -f "node-v$NODE_VERSION-linux-$ARCH-musl.tar.xz" \ # Remove unused OpenSSL headers to save ~34MB. See this NodeJS issue: https://github.com/nodejs/node/issues/46451 && find /usr/local/include/node/openssl/archs -mindepth 1 -maxdepth 1 ! -name "$OPENSSL_ARCH" -exec rm -rf {} \; \ && apk del .build-deps \ # smoke tests && node --version \ && npm --version \ && rm -rf /tmp/* ENV YARN_VERSION=1.22.22 RUN apk add --no-cache --virtual .build-deps-yarn curl gnupg tar \ # use pre-existing gpg directory, see https://github.com/nodejs/docker-node/pull/1895#issuecomment-1550389150 && export GNUPGHOME="$(mktemp -d)" \ && for key in \ 6A010C5166006599AA17F08146C2130DFD2497F5 \ ; do \ { gpg --batch --keyserver hkps://keys.openpgp.org --recv-keys "$key" && gpg --batch --fingerprint "$key"; } || \ { gpg --batch --keyserver keyserver.ubuntu.com --recv-keys "$key" && gpg --batch --fingerprint "$key"; } ; \ done \ && curl -fsSLO --compressed "https://yarnpkg.com/downloads/$YARN_VERSION/yarn-v$YARN_VERSION.tar.gz" \ && curl -fsSLO --compressed "https://yarnpkg.com/downloads/$YARN_VERSION/yarn-v$YARN_VERSION.tar.gz.asc" \ && gpg --batch --verify yarn-v$YARN_VERSION.tar.gz.asc yarn-v$YARN_VERSION.tar.gz \ && gpgconf --kill all \ && rm -rf "$GNUPGHOME" \ && mkdir -p /opt \ && tar -xzf yarn-v$YARN_VERSION.tar.gz -C /opt/ \ && ln -s /opt/yarn-v$YARN_VERSION/bin/yarn /usr/local/bin/yarn \ && ln -s /opt/yarn-v$YARN_VERSION/bin/yarnpkg /usr/local/bin/yarnpkg \ && rm yarn-v$YARN_VERSION.tar.gz.asc yarn-v$YARN_VERSION.tar.gz \ && apk del .build-deps-yarn \ # smoke test && yarn --version \ && rm -rf /tmp/* COPY docker-entrypoint.sh /usr/local/bin/ ENTRYPOINT ["docker-entrypoint.sh"] CMD [ "node" ] ================================================ FILE: 24/alpine3.23/docker-entrypoint.sh ================================================ #!/bin/sh set -e # Run command with node if the first argument contains a "-" or is not a system command. The last # part inside the "{}" is a workaround for the following bug in ash/dash: # https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=874264 if [ "${1#-}" != "${1}" ] || [ -z "$(command -v "${1}")" ] || { [ -f "${1}" ] && ! [ -x "${1}" ]; }; then set -- node "$@" fi exec "$@" ================================================ FILE: 24/bookworm/Dockerfile ================================================ FROM buildpack-deps:bookworm RUN groupadd --gid 1000 node \ && useradd --uid 1000 --gid node --shell /bin/bash --create-home node ENV NODE_VERSION=24.14.0 RUN ARCH= && dpkgArch="$(dpkg --print-architecture)" \ && case "${dpkgArch##*-}" in \ amd64) ARCH='x64';; \ ppc64el) ARCH='ppc64le';; \ s390x) ARCH='s390x';; \ arm64) ARCH='arm64';; \ armhf) ARCH='armv7l';; \ i386) ARCH='x86';; \ *) echo "unsupported architecture"; exit 1 ;; \ esac \ # use pre-existing gpg directory, see https://github.com/nodejs/docker-node/pull/1895#issuecomment-1550389150 && export GNUPGHOME="$(mktemp -d)" \ # gpg keys listed at https://github.com/nodejs/node#release-keys && set -ex \ && for key in \ 5BE8A3F6C8A5C01D106C0AD820B1A390B168D356 \ DD792F5973C6DE52C432CBDAC77ABFA00DDBF2B7 \ CC68F5A3106FF448322E48ED27F5E38D5B0A215F \ 8FCCA13FEF1D0C2E91008E09770F7A9A5AE15600 \ 890C08DB8579162FEE0DF9DB8BEAB4DFCF555EF4 \ C82FA3AE1CBEDC6BE46B9360C43CEC45C17AB93C \ 108F52B48DB57BB0CC439B2997B01419BD92F80A \ A363A499291CBBC940DD62E41F10027AF002F8B0 \ ; do \ { gpg --batch --keyserver hkps://keys.openpgp.org --recv-keys "$key" && gpg --batch --fingerprint "$key"; } || \ { gpg --batch --keyserver keyserver.ubuntu.com --recv-keys "$key" && gpg --batch --fingerprint "$key"; } ; \ done \ && curl -fsSLO --compressed "https://nodejs.org/dist/v$NODE_VERSION/node-v$NODE_VERSION-linux-$ARCH.tar.xz" \ && curl -fsSLO --compressed "https://nodejs.org/dist/v$NODE_VERSION/SHASUMS256.txt.asc" \ && gpg --batch --decrypt --output SHASUMS256.txt SHASUMS256.txt.asc \ && gpgconf --kill all \ && rm -rf "$GNUPGHOME" \ && grep " node-v$NODE_VERSION-linux-$ARCH.tar.xz\$" SHASUMS256.txt | sha256sum -c - \ && tar -xJf "node-v$NODE_VERSION-linux-$ARCH.tar.xz" -C /usr/local --strip-components=1 --no-same-owner \ && rm "node-v$NODE_VERSION-linux-$ARCH.tar.xz" SHASUMS256.txt.asc SHASUMS256.txt \ && ln -s /usr/local/bin/node /usr/local/bin/nodejs \ # smoke tests && node --version \ && npm --version \ && rm -rf /tmp/* ENV YARN_VERSION=1.22.22 RUN set -ex \ # use pre-existing gpg directory, see https://github.com/nodejs/docker-node/pull/1895#issuecomment-1550389150 && export GNUPGHOME="$(mktemp -d)" \ && for key in \ 6A010C5166006599AA17F08146C2130DFD2497F5 \ ; do \ { gpg --batch --keyserver hkps://keys.openpgp.org --recv-keys "$key" && gpg --batch --fingerprint "$key"; } || \ { gpg --batch --keyserver keyserver.ubuntu.com --recv-keys "$key" && gpg --batch --fingerprint "$key"; } ; \ done \ && curl -fsSLO --compressed "https://yarnpkg.com/downloads/$YARN_VERSION/yarn-v$YARN_VERSION.tar.gz" \ && curl -fsSLO --compressed "https://yarnpkg.com/downloads/$YARN_VERSION/yarn-v$YARN_VERSION.tar.gz.asc" \ && gpg --batch --verify yarn-v$YARN_VERSION.tar.gz.asc yarn-v$YARN_VERSION.tar.gz \ && gpgconf --kill all \ && rm -rf "$GNUPGHOME" \ && mkdir -p /opt \ && tar -xzf yarn-v$YARN_VERSION.tar.gz -C /opt/ \ && ln -s /opt/yarn-v$YARN_VERSION/bin/yarn /usr/local/bin/yarn \ && ln -s /opt/yarn-v$YARN_VERSION/bin/yarnpkg /usr/local/bin/yarnpkg \ && rm yarn-v$YARN_VERSION.tar.gz.asc yarn-v$YARN_VERSION.tar.gz \ # smoke test && yarn --version \ && rm -rf /tmp/* COPY docker-entrypoint.sh /usr/local/bin/ ENTRYPOINT ["docker-entrypoint.sh"] CMD [ "node" ] ================================================ FILE: 24/bookworm/docker-entrypoint.sh ================================================ #!/bin/sh set -e # Run command with node if the first argument contains a "-" or is not a system command. The last # part inside the "{}" is a workaround for the following bug in ash/dash: # https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=874264 if [ "${1#-}" != "${1}" ] || [ -z "$(command -v "${1}")" ] || { [ -f "${1}" ] && ! [ -x "${1}" ]; }; then set -- node "$@" fi exec "$@" ================================================ FILE: 24/bookworm-slim/Dockerfile ================================================ FROM debian:bookworm-slim RUN groupadd --gid 1000 node \ && useradd --uid 1000 --gid node --shell /bin/bash --create-home node ENV NODE_VERSION=24.14.0 RUN ARCH= OPENSSL_ARCH= && dpkgArch="$(dpkg --print-architecture)" \ && case "${dpkgArch##*-}" in \ amd64) ARCH='x64' OPENSSL_ARCH='linux-x86_64';; \ ppc64el) ARCH='ppc64le' OPENSSL_ARCH='linux-ppc64le';; \ s390x) ARCH='s390x' OPENSSL_ARCH='linux*-s390x';; \ arm64) ARCH='arm64' OPENSSL_ARCH='linux-aarch64';; \ armhf) ARCH='armv7l' OPENSSL_ARCH='linux-armv4';; \ i386) ARCH='x86' OPENSSL_ARCH='linux-elf';; \ *) echo "unsupported architecture"; exit 1 ;; \ esac \ && set -ex \ # libatomic1 for arm && apt-get update && apt-get install -y ca-certificates curl wget gnupg dirmngr xz-utils libatomic1 --no-install-recommends \ && rm -rf /var/lib/apt/lists/* \ # use pre-existing gpg directory, see https://github.com/nodejs/docker-node/pull/1895#issuecomment-1550389150 && export GNUPGHOME="$(mktemp -d)" \ # gpg keys listed at https://github.com/nodejs/node#release-keys && for key in \ 5BE8A3F6C8A5C01D106C0AD820B1A390B168D356 \ DD792F5973C6DE52C432CBDAC77ABFA00DDBF2B7 \ CC68F5A3106FF448322E48ED27F5E38D5B0A215F \ 8FCCA13FEF1D0C2E91008E09770F7A9A5AE15600 \ 890C08DB8579162FEE0DF9DB8BEAB4DFCF555EF4 \ C82FA3AE1CBEDC6BE46B9360C43CEC45C17AB93C \ 108F52B48DB57BB0CC439B2997B01419BD92F80A \ A363A499291CBBC940DD62E41F10027AF002F8B0 \ ; do \ { gpg --batch --keyserver hkps://keys.openpgp.org --recv-keys "$key" && gpg --batch --fingerprint "$key"; } || \ { gpg --batch --keyserver keyserver.ubuntu.com --recv-keys "$key" && gpg --batch --fingerprint "$key"; } ; \ done \ && curl -fsSLO --compressed "https://nodejs.org/dist/v$NODE_VERSION/node-v$NODE_VERSION-linux-$ARCH.tar.xz" \ && curl -fsSLO --compressed "https://nodejs.org/dist/v$NODE_VERSION/SHASUMS256.txt.asc" \ && gpg --batch --decrypt --output SHASUMS256.txt SHASUMS256.txt.asc \ && gpgconf --kill all \ && rm -rf "$GNUPGHOME" \ && grep " node-v$NODE_VERSION-linux-$ARCH.tar.xz\$" SHASUMS256.txt | sha256sum -c - \ && tar -xJf "node-v$NODE_VERSION-linux-$ARCH.tar.xz" -C /usr/local --strip-components=1 --no-same-owner \ && rm "node-v$NODE_VERSION-linux-$ARCH.tar.xz" SHASUMS256.txt.asc SHASUMS256.txt \ # Remove unused OpenSSL headers to save ~34MB. See this NodeJS issue: https://github.com/nodejs/node/issues/46451 && find /usr/local/include/node/openssl/archs -mindepth 1 -maxdepth 1 ! -name "$OPENSSL_ARCH" -exec rm -rf {} \; \ && apt-mark auto '.*' > /dev/null \ && find /usr/local -type f -executable -exec ldd '{}' ';' \ | awk '/=>/ { so = $(NF-1); if (index(so, "/usr/local/") == 1) { next }; gsub("^/(usr/)?", "", so); print so }' \ | sort -u \ | xargs -r dpkg-query --search \ | cut -d: -f1 \ | sort -u \ | xargs -r apt-mark manual \ && apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false \ && ln -s /usr/local/bin/node /usr/local/bin/nodejs \ # smoke tests && node --version \ && npm --version \ && rm -rf /tmp/* ENV YARN_VERSION=1.22.22 RUN set -ex \ && savedAptMark="$(apt-mark showmanual)" \ && apt-get update && apt-get install -y ca-certificates curl wget gnupg dirmngr --no-install-recommends \ && rm -rf /var/lib/apt/lists/* \ # use pre-existing gpg directory, see https://github.com/nodejs/docker-node/pull/1895#issuecomment-1550389150 && export GNUPGHOME="$(mktemp -d)" \ && for key in \ 6A010C5166006599AA17F08146C2130DFD2497F5 \ ; do \ { gpg --batch --keyserver hkps://keys.openpgp.org --recv-keys "$key" && gpg --batch --fingerprint "$key"; } || \ { gpg --batch --keyserver keyserver.ubuntu.com --recv-keys "$key" && gpg --batch --fingerprint "$key"; } ; \ done \ && curl -fsSLO --compressed "https://yarnpkg.com/downloads/$YARN_VERSION/yarn-v$YARN_VERSION.tar.gz" \ && curl -fsSLO --compressed "https://yarnpkg.com/downloads/$YARN_VERSION/yarn-v$YARN_VERSION.tar.gz.asc" \ && gpg --batch --verify yarn-v$YARN_VERSION.tar.gz.asc yarn-v$YARN_VERSION.tar.gz \ && gpgconf --kill all \ && rm -rf "$GNUPGHOME" \ && mkdir -p /opt \ && tar -xzf yarn-v$YARN_VERSION.tar.gz -C /opt/ \ && ln -s /opt/yarn-v$YARN_VERSION/bin/yarn /usr/local/bin/yarn \ && ln -s /opt/yarn-v$YARN_VERSION/bin/yarnpkg /usr/local/bin/yarnpkg \ && rm yarn-v$YARN_VERSION.tar.gz.asc yarn-v$YARN_VERSION.tar.gz \ && apt-mark auto '.*' > /dev/null \ && { [ -z "$savedAptMark" ] || apt-mark manual $savedAptMark > /dev/null; } \ && find /usr/local -type f -executable -exec ldd '{}' ';' \ | awk '/=>/ { so = $(NF-1); if (index(so, "/usr/local/") == 1) { next }; gsub("^/(usr/)?", "", so); print so }' \ | sort -u \ | xargs -r dpkg-query --search \ | cut -d: -f1 \ | sort -u \ | xargs -r apt-mark manual \ && apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false \ # smoke test && yarn --version \ && rm -rf /tmp/* COPY docker-entrypoint.sh /usr/local/bin/ ENTRYPOINT ["docker-entrypoint.sh"] CMD [ "node" ] ================================================ FILE: 24/bookworm-slim/docker-entrypoint.sh ================================================ #!/bin/sh set -e # Run command with node if the first argument contains a "-" or is not a system command. The last # part inside the "{}" is a workaround for the following bug in ash/dash: # https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=874264 if [ "${1#-}" != "${1}" ] || [ -z "$(command -v "${1}")" ] || { [ -f "${1}" ] && ! [ -x "${1}" ]; }; then set -- node "$@" fi exec "$@" ================================================ FILE: 24/bullseye/Dockerfile ================================================ FROM buildpack-deps:bullseye RUN groupadd --gid 1000 node \ && useradd --uid 1000 --gid node --shell /bin/bash --create-home node ENV NODE_VERSION=24.14.0 RUN ARCH= && dpkgArch="$(dpkg --print-architecture)" \ && case "${dpkgArch##*-}" in \ amd64) ARCH='x64';; \ ppc64el) ARCH='ppc64le';; \ s390x) ARCH='s390x';; \ arm64) ARCH='arm64';; \ armhf) ARCH='armv7l';; \ i386) ARCH='x86';; \ *) echo "unsupported architecture"; exit 1 ;; \ esac \ # use pre-existing gpg directory, see https://github.com/nodejs/docker-node/pull/1895#issuecomment-1550389150 && export GNUPGHOME="$(mktemp -d)" \ # gpg keys listed at https://github.com/nodejs/node#release-keys && set -ex \ && for key in \ 5BE8A3F6C8A5C01D106C0AD820B1A390B168D356 \ DD792F5973C6DE52C432CBDAC77ABFA00DDBF2B7 \ CC68F5A3106FF448322E48ED27F5E38D5B0A215F \ 8FCCA13FEF1D0C2E91008E09770F7A9A5AE15600 \ 890C08DB8579162FEE0DF9DB8BEAB4DFCF555EF4 \ C82FA3AE1CBEDC6BE46B9360C43CEC45C17AB93C \ 108F52B48DB57BB0CC439B2997B01419BD92F80A \ A363A499291CBBC940DD62E41F10027AF002F8B0 \ ; do \ { gpg --batch --keyserver hkps://keys.openpgp.org --recv-keys "$key" && gpg --batch --fingerprint "$key"; } || \ { gpg --batch --keyserver keyserver.ubuntu.com --recv-keys "$key" && gpg --batch --fingerprint "$key"; } ; \ done \ && curl -fsSLO --compressed "https://nodejs.org/dist/v$NODE_VERSION/node-v$NODE_VERSION-linux-$ARCH.tar.xz" \ && curl -fsSLO --compressed "https://nodejs.org/dist/v$NODE_VERSION/SHASUMS256.txt.asc" \ && gpg --batch --decrypt --output SHASUMS256.txt SHASUMS256.txt.asc \ && gpgconf --kill all \ && rm -rf "$GNUPGHOME" \ && grep " node-v$NODE_VERSION-linux-$ARCH.tar.xz\$" SHASUMS256.txt | sha256sum -c - \ && tar -xJf "node-v$NODE_VERSION-linux-$ARCH.tar.xz" -C /usr/local --strip-components=1 --no-same-owner \ && rm "node-v$NODE_VERSION-linux-$ARCH.tar.xz" SHASUMS256.txt.asc SHASUMS256.txt \ && ln -s /usr/local/bin/node /usr/local/bin/nodejs \ # smoke tests && node --version \ && npm --version \ && rm -rf /tmp/* ENV YARN_VERSION=1.22.22 RUN set -ex \ # use pre-existing gpg directory, see https://github.com/nodejs/docker-node/pull/1895#issuecomment-1550389150 && export GNUPGHOME="$(mktemp -d)" \ && for key in \ 6A010C5166006599AA17F08146C2130DFD2497F5 \ ; do \ { gpg --batch --keyserver hkps://keys.openpgp.org --recv-keys "$key" && gpg --batch --fingerprint "$key"; } || \ { gpg --batch --keyserver keyserver.ubuntu.com --recv-keys "$key" && gpg --batch --fingerprint "$key"; } ; \ done \ && curl -fsSLO --compressed "https://yarnpkg.com/downloads/$YARN_VERSION/yarn-v$YARN_VERSION.tar.gz" \ && curl -fsSLO --compressed "https://yarnpkg.com/downloads/$YARN_VERSION/yarn-v$YARN_VERSION.tar.gz.asc" \ && gpg --batch --verify yarn-v$YARN_VERSION.tar.gz.asc yarn-v$YARN_VERSION.tar.gz \ && gpgconf --kill all \ && rm -rf "$GNUPGHOME" \ && mkdir -p /opt \ && tar -xzf yarn-v$YARN_VERSION.tar.gz -C /opt/ \ && ln -s /opt/yarn-v$YARN_VERSION/bin/yarn /usr/local/bin/yarn \ && ln -s /opt/yarn-v$YARN_VERSION/bin/yarnpkg /usr/local/bin/yarnpkg \ && rm yarn-v$YARN_VERSION.tar.gz.asc yarn-v$YARN_VERSION.tar.gz \ # smoke test && yarn --version \ && rm -rf /tmp/* COPY docker-entrypoint.sh /usr/local/bin/ ENTRYPOINT ["docker-entrypoint.sh"] CMD [ "node" ] ================================================ FILE: 24/bullseye/docker-entrypoint.sh ================================================ #!/bin/sh set -e # Run command with node if the first argument contains a "-" or is not a system command. The last # part inside the "{}" is a workaround for the following bug in ash/dash: # https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=874264 if [ "${1#-}" != "${1}" ] || [ -z "$(command -v "${1}")" ] || { [ -f "${1}" ] && ! [ -x "${1}" ]; }; then set -- node "$@" fi exec "$@" ================================================ FILE: 24/bullseye-slim/Dockerfile ================================================ FROM debian:bullseye-slim RUN groupadd --gid 1000 node \ && useradd --uid 1000 --gid node --shell /bin/bash --create-home node ENV NODE_VERSION=24.14.0 RUN ARCH= OPENSSL_ARCH= && dpkgArch="$(dpkg --print-architecture)" \ && case "${dpkgArch##*-}" in \ amd64) ARCH='x64' OPENSSL_ARCH='linux-x86_64';; \ ppc64el) ARCH='ppc64le' OPENSSL_ARCH='linux-ppc64le';; \ s390x) ARCH='s390x' OPENSSL_ARCH='linux*-s390x';; \ arm64) ARCH='arm64' OPENSSL_ARCH='linux-aarch64';; \ armhf) ARCH='armv7l' OPENSSL_ARCH='linux-armv4';; \ i386) ARCH='x86' OPENSSL_ARCH='linux-elf';; \ *) echo "unsupported architecture"; exit 1 ;; \ esac \ && set -ex \ # libatomic1 for arm && apt-get update && apt-get install -y ca-certificates curl wget gnupg dirmngr xz-utils libatomic1 --no-install-recommends \ && rm -rf /var/lib/apt/lists/* \ # use pre-existing gpg directory, see https://github.com/nodejs/docker-node/pull/1895#issuecomment-1550389150 && export GNUPGHOME="$(mktemp -d)" \ # gpg keys listed at https://github.com/nodejs/node#release-keys && for key in \ 5BE8A3F6C8A5C01D106C0AD820B1A390B168D356 \ DD792F5973C6DE52C432CBDAC77ABFA00DDBF2B7 \ CC68F5A3106FF448322E48ED27F5E38D5B0A215F \ 8FCCA13FEF1D0C2E91008E09770F7A9A5AE15600 \ 890C08DB8579162FEE0DF9DB8BEAB4DFCF555EF4 \ C82FA3AE1CBEDC6BE46B9360C43CEC45C17AB93C \ 108F52B48DB57BB0CC439B2997B01419BD92F80A \ A363A499291CBBC940DD62E41F10027AF002F8B0 \ ; do \ { gpg --batch --keyserver hkps://keys.openpgp.org --recv-keys "$key" && gpg --batch --fingerprint "$key"; } || \ { gpg --batch --keyserver keyserver.ubuntu.com --recv-keys "$key" && gpg --batch --fingerprint "$key"; } ; \ done \ && curl -fsSLO --compressed "https://nodejs.org/dist/v$NODE_VERSION/node-v$NODE_VERSION-linux-$ARCH.tar.xz" \ && curl -fsSLO --compressed "https://nodejs.org/dist/v$NODE_VERSION/SHASUMS256.txt.asc" \ && gpg --batch --decrypt --output SHASUMS256.txt SHASUMS256.txt.asc \ && gpgconf --kill all \ && rm -rf "$GNUPGHOME" \ && grep " node-v$NODE_VERSION-linux-$ARCH.tar.xz\$" SHASUMS256.txt | sha256sum -c - \ && tar -xJf "node-v$NODE_VERSION-linux-$ARCH.tar.xz" -C /usr/local --strip-components=1 --no-same-owner \ && rm "node-v$NODE_VERSION-linux-$ARCH.tar.xz" SHASUMS256.txt.asc SHASUMS256.txt \ # Remove unused OpenSSL headers to save ~34MB. See this NodeJS issue: https://github.com/nodejs/node/issues/46451 && find /usr/local/include/node/openssl/archs -mindepth 1 -maxdepth 1 ! -name "$OPENSSL_ARCH" -exec rm -rf {} \; \ && apt-mark auto '.*' > /dev/null \ && find /usr/local -type f -executable -exec ldd '{}' ';' \ | awk '/=>/ { so = $(NF-1); if (index(so, "/usr/local/") == 1) { next }; gsub("^/(usr/)?", "", so); print so }' \ | sort -u \ | xargs -r dpkg-query --search \ | cut -d: -f1 \ | sort -u \ | xargs -r apt-mark manual \ && apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false \ && ln -s /usr/local/bin/node /usr/local/bin/nodejs \ # smoke tests && node --version \ && npm --version \ && rm -rf /tmp/* ENV YARN_VERSION=1.22.22 RUN set -ex \ && savedAptMark="$(apt-mark showmanual)" \ && apt-get update && apt-get install -y ca-certificates curl wget gnupg dirmngr --no-install-recommends \ && rm -rf /var/lib/apt/lists/* \ # use pre-existing gpg directory, see https://github.com/nodejs/docker-node/pull/1895#issuecomment-1550389150 && export GNUPGHOME="$(mktemp -d)" \ && for key in \ 6A010C5166006599AA17F08146C2130DFD2497F5 \ ; do \ { gpg --batch --keyserver hkps://keys.openpgp.org --recv-keys "$key" && gpg --batch --fingerprint "$key"; } || \ { gpg --batch --keyserver keyserver.ubuntu.com --recv-keys "$key" && gpg --batch --fingerprint "$key"; } ; \ done \ && curl -fsSLO --compressed "https://yarnpkg.com/downloads/$YARN_VERSION/yarn-v$YARN_VERSION.tar.gz" \ && curl -fsSLO --compressed "https://yarnpkg.com/downloads/$YARN_VERSION/yarn-v$YARN_VERSION.tar.gz.asc" \ && gpg --batch --verify yarn-v$YARN_VERSION.tar.gz.asc yarn-v$YARN_VERSION.tar.gz \ && gpgconf --kill all \ && rm -rf "$GNUPGHOME" \ && mkdir -p /opt \ && tar -xzf yarn-v$YARN_VERSION.tar.gz -C /opt/ \ && ln -s /opt/yarn-v$YARN_VERSION/bin/yarn /usr/local/bin/yarn \ && ln -s /opt/yarn-v$YARN_VERSION/bin/yarnpkg /usr/local/bin/yarnpkg \ && rm yarn-v$YARN_VERSION.tar.gz.asc yarn-v$YARN_VERSION.tar.gz \ && apt-mark auto '.*' > /dev/null \ && { [ -z "$savedAptMark" ] || apt-mark manual $savedAptMark > /dev/null; } \ && find /usr/local -type f -executable -exec ldd '{}' ';' \ | awk '/=>/ { so = $(NF-1); if (index(so, "/usr/local/") == 1) { next }; gsub("^/(usr/)?", "", so); print so }' \ | sort -u \ | xargs -r dpkg-query --search \ | cut -d: -f1 \ | sort -u \ | xargs -r apt-mark manual \ && apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false \ # smoke test && yarn --version \ && rm -rf /tmp/* COPY docker-entrypoint.sh /usr/local/bin/ ENTRYPOINT ["docker-entrypoint.sh"] CMD [ "node" ] ================================================ FILE: 24/bullseye-slim/docker-entrypoint.sh ================================================ #!/bin/sh set -e # Run command with node if the first argument contains a "-" or is not a system command. The last # part inside the "{}" is a workaround for the following bug in ash/dash: # https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=874264 if [ "${1#-}" != "${1}" ] || [ -z "$(command -v "${1}")" ] || { [ -f "${1}" ] && ! [ -x "${1}" ]; }; then set -- node "$@" fi exec "$@" ================================================ FILE: 24/trixie/Dockerfile ================================================ FROM buildpack-deps:trixie RUN groupadd --gid 1000 node \ && useradd --uid 1000 --gid node --shell /bin/bash --create-home node ENV NODE_VERSION=24.14.0 RUN ARCH= && dpkgArch="$(dpkg --print-architecture)" \ && case "${dpkgArch##*-}" in \ amd64) ARCH='x64';; \ ppc64el) ARCH='ppc64le';; \ s390x) ARCH='s390x';; \ arm64) ARCH='arm64';; \ armhf) ARCH='armv7l';; \ i386) ARCH='x86';; \ *) echo "unsupported architecture"; exit 1 ;; \ esac \ # use pre-existing gpg directory, see https://github.com/nodejs/docker-node/pull/1895#issuecomment-1550389150 && export GNUPGHOME="$(mktemp -d)" \ # gpg keys listed at https://github.com/nodejs/node#release-keys && set -ex \ && for key in \ 5BE8A3F6C8A5C01D106C0AD820B1A390B168D356 \ DD792F5973C6DE52C432CBDAC77ABFA00DDBF2B7 \ CC68F5A3106FF448322E48ED27F5E38D5B0A215F \ 8FCCA13FEF1D0C2E91008E09770F7A9A5AE15600 \ 890C08DB8579162FEE0DF9DB8BEAB4DFCF555EF4 \ C82FA3AE1CBEDC6BE46B9360C43CEC45C17AB93C \ 108F52B48DB57BB0CC439B2997B01419BD92F80A \ A363A499291CBBC940DD62E41F10027AF002F8B0 \ ; do \ { gpg --batch --keyserver hkps://keys.openpgp.org --recv-keys "$key" && gpg --batch --fingerprint "$key"; } || \ { gpg --batch --keyserver keyserver.ubuntu.com --recv-keys "$key" && gpg --batch --fingerprint "$key"; } ; \ done \ && curl -fsSLO --compressed "https://nodejs.org/dist/v$NODE_VERSION/node-v$NODE_VERSION-linux-$ARCH.tar.xz" \ && curl -fsSLO --compressed "https://nodejs.org/dist/v$NODE_VERSION/SHASUMS256.txt.asc" \ && gpg --batch --decrypt --output SHASUMS256.txt SHASUMS256.txt.asc \ && gpgconf --kill all \ && rm -rf "$GNUPGHOME" \ && grep " node-v$NODE_VERSION-linux-$ARCH.tar.xz\$" SHASUMS256.txt | sha256sum -c - \ && tar -xJf "node-v$NODE_VERSION-linux-$ARCH.tar.xz" -C /usr/local --strip-components=1 --no-same-owner \ && rm "node-v$NODE_VERSION-linux-$ARCH.tar.xz" SHASUMS256.txt.asc SHASUMS256.txt \ && ln -s /usr/local/bin/node /usr/local/bin/nodejs \ # smoke tests && node --version \ && npm --version \ && rm -rf /tmp/* ENV YARN_VERSION=1.22.22 RUN set -ex \ # use pre-existing gpg directory, see https://github.com/nodejs/docker-node/pull/1895#issuecomment-1550389150 && export GNUPGHOME="$(mktemp -d)" \ && for key in \ 6A010C5166006599AA17F08146C2130DFD2497F5 \ ; do \ { gpg --batch --keyserver hkps://keys.openpgp.org --recv-keys "$key" && gpg --batch --fingerprint "$key"; } || \ { gpg --batch --keyserver keyserver.ubuntu.com --recv-keys "$key" && gpg --batch --fingerprint "$key"; } ; \ done \ && curl -fsSLO --compressed "https://yarnpkg.com/downloads/$YARN_VERSION/yarn-v$YARN_VERSION.tar.gz" \ && curl -fsSLO --compressed "https://yarnpkg.com/downloads/$YARN_VERSION/yarn-v$YARN_VERSION.tar.gz.asc" \ && gpg --batch --verify yarn-v$YARN_VERSION.tar.gz.asc yarn-v$YARN_VERSION.tar.gz \ && gpgconf --kill all \ && rm -rf "$GNUPGHOME" \ && mkdir -p /opt \ && tar -xzf yarn-v$YARN_VERSION.tar.gz -C /opt/ \ && ln -s /opt/yarn-v$YARN_VERSION/bin/yarn /usr/local/bin/yarn \ && ln -s /opt/yarn-v$YARN_VERSION/bin/yarnpkg /usr/local/bin/yarnpkg \ && rm yarn-v$YARN_VERSION.tar.gz.asc yarn-v$YARN_VERSION.tar.gz \ # smoke test && yarn --version \ && rm -rf /tmp/* COPY docker-entrypoint.sh /usr/local/bin/ ENTRYPOINT ["docker-entrypoint.sh"] CMD [ "node" ] ================================================ FILE: 24/trixie/docker-entrypoint.sh ================================================ #!/bin/sh set -e # Run command with node if the first argument contains a "-" or is not a system command. The last # part inside the "{}" is a workaround for the following bug in ash/dash: # https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=874264 if [ "${1#-}" != "${1}" ] || [ -z "$(command -v "${1}")" ] || { [ -f "${1}" ] && ! [ -x "${1}" ]; }; then set -- node "$@" fi exec "$@" ================================================ FILE: 24/trixie-slim/Dockerfile ================================================ FROM debian:trixie-slim RUN groupadd --gid 1000 node \ && useradd --uid 1000 --gid node --shell /bin/bash --create-home node ENV NODE_VERSION=24.14.0 RUN ARCH= OPENSSL_ARCH= && dpkgArch="$(dpkg --print-architecture)" \ && case "${dpkgArch##*-}" in \ amd64) ARCH='x64' OPENSSL_ARCH='linux-x86_64';; \ ppc64el) ARCH='ppc64le' OPENSSL_ARCH='linux-ppc64le';; \ s390x) ARCH='s390x' OPENSSL_ARCH='linux*-s390x';; \ arm64) ARCH='arm64' OPENSSL_ARCH='linux-aarch64';; \ armhf) ARCH='armv7l' OPENSSL_ARCH='linux-armv4';; \ i386) ARCH='x86' OPENSSL_ARCH='linux-elf';; \ *) echo "unsupported architecture"; exit 1 ;; \ esac \ && set -ex \ # libatomic1 for arm && apt-get update && apt-get install -y ca-certificates curl wget gnupg dirmngr xz-utils libatomic1 --no-install-recommends \ && rm -rf /var/lib/apt/lists/* \ # use pre-existing gpg directory, see https://github.com/nodejs/docker-node/pull/1895#issuecomment-1550389150 && export GNUPGHOME="$(mktemp -d)" \ # gpg keys listed at https://github.com/nodejs/node#release-keys && for key in \ 5BE8A3F6C8A5C01D106C0AD820B1A390B168D356 \ DD792F5973C6DE52C432CBDAC77ABFA00DDBF2B7 \ CC68F5A3106FF448322E48ED27F5E38D5B0A215F \ 8FCCA13FEF1D0C2E91008E09770F7A9A5AE15600 \ 890C08DB8579162FEE0DF9DB8BEAB4DFCF555EF4 \ C82FA3AE1CBEDC6BE46B9360C43CEC45C17AB93C \ 108F52B48DB57BB0CC439B2997B01419BD92F80A \ A363A499291CBBC940DD62E41F10027AF002F8B0 \ ; do \ { gpg --batch --keyserver hkps://keys.openpgp.org --recv-keys "$key" && gpg --batch --fingerprint "$key"; } || \ { gpg --batch --keyserver keyserver.ubuntu.com --recv-keys "$key" && gpg --batch --fingerprint "$key"; } ; \ done \ && curl -fsSLO --compressed "https://nodejs.org/dist/v$NODE_VERSION/node-v$NODE_VERSION-linux-$ARCH.tar.xz" \ && curl -fsSLO --compressed "https://nodejs.org/dist/v$NODE_VERSION/SHASUMS256.txt.asc" \ && gpg --batch --decrypt --output SHASUMS256.txt SHASUMS256.txt.asc \ && gpgconf --kill all \ && rm -rf "$GNUPGHOME" \ && grep " node-v$NODE_VERSION-linux-$ARCH.tar.xz\$" SHASUMS256.txt | sha256sum -c - \ && tar -xJf "node-v$NODE_VERSION-linux-$ARCH.tar.xz" -C /usr/local --strip-components=1 --no-same-owner \ && rm "node-v$NODE_VERSION-linux-$ARCH.tar.xz" SHASUMS256.txt.asc SHASUMS256.txt \ # Remove unused OpenSSL headers to save ~34MB. See this NodeJS issue: https://github.com/nodejs/node/issues/46451 && find /usr/local/include/node/openssl/archs -mindepth 1 -maxdepth 1 ! -name "$OPENSSL_ARCH" -exec rm -rf {} \; \ && apt-mark auto '.*' > /dev/null \ && find /usr/local -type f -executable -exec ldd '{}' ';' \ | awk '/=>/ { so = $(NF-1); if (index(so, "/usr/local/") == 1) { next }; gsub("^/(usr/)?", "", so); print so }' \ | sort -u \ | xargs -r dpkg-query --search \ | cut -d: -f1 \ | sort -u \ | xargs -r apt-mark manual \ && apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false \ && ln -s /usr/local/bin/node /usr/local/bin/nodejs \ # smoke tests && node --version \ && npm --version \ && rm -rf /tmp/* ENV YARN_VERSION=1.22.22 RUN set -ex \ && savedAptMark="$(apt-mark showmanual)" \ && apt-get update && apt-get install -y ca-certificates curl wget gnupg dirmngr --no-install-recommends \ && rm -rf /var/lib/apt/lists/* \ # use pre-existing gpg directory, see https://github.com/nodejs/docker-node/pull/1895#issuecomment-1550389150 && export GNUPGHOME="$(mktemp -d)" \ && for key in \ 6A010C5166006599AA17F08146C2130DFD2497F5 \ ; do \ { gpg --batch --keyserver hkps://keys.openpgp.org --recv-keys "$key" && gpg --batch --fingerprint "$key"; } || \ { gpg --batch --keyserver keyserver.ubuntu.com --recv-keys "$key" && gpg --batch --fingerprint "$key"; } ; \ done \ && curl -fsSLO --compressed "https://yarnpkg.com/downloads/$YARN_VERSION/yarn-v$YARN_VERSION.tar.gz" \ && curl -fsSLO --compressed "https://yarnpkg.com/downloads/$YARN_VERSION/yarn-v$YARN_VERSION.tar.gz.asc" \ && gpg --batch --verify yarn-v$YARN_VERSION.tar.gz.asc yarn-v$YARN_VERSION.tar.gz \ && gpgconf --kill all \ && rm -rf "$GNUPGHOME" \ && mkdir -p /opt \ && tar -xzf yarn-v$YARN_VERSION.tar.gz -C /opt/ \ && ln -s /opt/yarn-v$YARN_VERSION/bin/yarn /usr/local/bin/yarn \ && ln -s /opt/yarn-v$YARN_VERSION/bin/yarnpkg /usr/local/bin/yarnpkg \ && rm yarn-v$YARN_VERSION.tar.gz.asc yarn-v$YARN_VERSION.tar.gz \ && apt-mark auto '.*' > /dev/null \ && { [ -z "$savedAptMark" ] || apt-mark manual $savedAptMark > /dev/null; } \ && find /usr/local -type f -executable -exec ldd '{}' ';' \ | awk '/=>/ { so = $(NF-1); if (index(so, "/usr/local/") == 1) { next }; gsub("^/(usr/)?", "", so); print so }' \ | sort -u \ | xargs -r dpkg-query --search \ | cut -d: -f1 \ | sort -u \ | xargs -r apt-mark manual \ && apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false \ # smoke test && yarn --version \ && rm -rf /tmp/* COPY docker-entrypoint.sh /usr/local/bin/ ENTRYPOINT ["docker-entrypoint.sh"] CMD [ "node" ] ================================================ FILE: 24/trixie-slim/docker-entrypoint.sh ================================================ #!/bin/sh set -e # Run command with node if the first argument contains a "-" or is not a system command. The last # part inside the "{}" is a workaround for the following bug in ash/dash: # https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=874264 if [ "${1#-}" != "${1}" ] || [ -z "$(command -v "${1}")" ] || { [ -f "${1}" ] && ! [ -x "${1}" ]; }; then set -- node "$@" fi exec "$@" ================================================ FILE: 25/alpine3.22/Dockerfile ================================================ FROM alpine:3.22 ENV NODE_VERSION=25.8.1 RUN addgroup -g 1000 node \ && adduser -u 1000 -G node -s /bin/sh -D node \ && apk add --no-cache \ libstdc++ \ && apk add --no-cache --virtual .build-deps \ curl \ && ARCH= OPENSSL_ARCH='linux*' && alpineArch="$(apk --print-arch)" \ && case "${alpineArch##*-}" in \ x86_64) ARCH='x64' CHECKSUM="f056db4cc177c28d1809fb5bdd72ce058088ab5bd7d800af24b20e2580034028" OPENSSL_ARCH=linux-x86_64;; \ x86) OPENSSL_ARCH=linux-elf;; \ aarch64) OPENSSL_ARCH=linux-aarch64;; \ arm*) OPENSSL_ARCH=linux-armv4;; \ ppc64le) OPENSSL_ARCH=linux-ppc64le;; \ s390x) OPENSSL_ARCH=linux-s390x;; \ *) ;; \ esac \ && if [ -n "${CHECKSUM}" ]; then \ set -eu; \ curl -fsSLO --compressed "https://unofficial-builds.nodejs.org/download/release/v$NODE_VERSION/node-v$NODE_VERSION-linux-$ARCH-musl.tar.xz"; \ echo "$CHECKSUM node-v$NODE_VERSION-linux-$ARCH-musl.tar.xz" | sha256sum -c - \ && tar -xJf "node-v$NODE_VERSION-linux-$ARCH-musl.tar.xz" -C /usr/local --strip-components=1 --no-same-owner \ && ln -s /usr/local/bin/node /usr/local/bin/nodejs; \ else \ echo "Building from source" \ # backup build && apk add --no-cache --virtual .build-deps-full \ binutils-gold \ g++ \ gcc \ gnupg \ libgcc \ linux-headers \ make \ python3 \ py-setuptools \ # use pre-existing gpg directory, see https://github.com/nodejs/docker-node/pull/1895#issuecomment-1550389150 && export GNUPGHOME="$(mktemp -d)" \ # gpg keys listed at https://github.com/nodejs/node#release-keys && for key in \ 5BE8A3F6C8A5C01D106C0AD820B1A390B168D356 \ DD792F5973C6DE52C432CBDAC77ABFA00DDBF2B7 \ CC68F5A3106FF448322E48ED27F5E38D5B0A215F \ 8FCCA13FEF1D0C2E91008E09770F7A9A5AE15600 \ 890C08DB8579162FEE0DF9DB8BEAB4DFCF555EF4 \ C82FA3AE1CBEDC6BE46B9360C43CEC45C17AB93C \ 108F52B48DB57BB0CC439B2997B01419BD92F80A \ A363A499291CBBC940DD62E41F10027AF002F8B0 \ ; do \ { gpg --batch --keyserver hkps://keys.openpgp.org --recv-keys "$key" && gpg --batch --fingerprint "$key"; } || \ { gpg --batch --keyserver keyserver.ubuntu.com --recv-keys "$key" && gpg --batch --fingerprint "$key"; } ; \ done \ && curl -fsSLO --compressed "https://nodejs.org/dist/v$NODE_VERSION/node-v$NODE_VERSION.tar.xz" \ && curl -fsSLO --compressed "https://nodejs.org/dist/v$NODE_VERSION/SHASUMS256.txt.asc" \ && gpg --batch --decrypt --output SHASUMS256.txt SHASUMS256.txt.asc \ && gpgconf --kill all \ && rm -rf "$GNUPGHOME" \ && grep " node-v$NODE_VERSION.tar.xz\$" SHASUMS256.txt | sha256sum -c - \ && tar -xf "node-v$NODE_VERSION.tar.xz" \ && cd "node-v$NODE_VERSION" \ && ./configure \ && make -j$(getconf _NPROCESSORS_ONLN) V= \ && make install \ && apk del .build-deps-full \ && cd .. \ && rm -Rf "node-v$NODE_VERSION" \ && rm "node-v$NODE_VERSION.tar.xz" SHASUMS256.txt.asc SHASUMS256.txt; \ fi \ && rm -f "node-v$NODE_VERSION-linux-$ARCH-musl.tar.xz" \ # Remove unused OpenSSL headers to save ~34MB. See this NodeJS issue: https://github.com/nodejs/node/issues/46451 && find /usr/local/include/node/openssl/archs -mindepth 1 -maxdepth 1 ! -name "$OPENSSL_ARCH" -exec rm -rf {} \; \ && apk del .build-deps \ # smoke tests && node --version \ && npm --version \ && rm -rf /tmp/* ENV YARN_VERSION=1.22.22 RUN apk add --no-cache --virtual .build-deps-yarn curl gnupg tar \ # use pre-existing gpg directory, see https://github.com/nodejs/docker-node/pull/1895#issuecomment-1550389150 && export GNUPGHOME="$(mktemp -d)" \ && for key in \ 6A010C5166006599AA17F08146C2130DFD2497F5 \ ; do \ { gpg --batch --keyserver hkps://keys.openpgp.org --recv-keys "$key" && gpg --batch --fingerprint "$key"; } || \ { gpg --batch --keyserver keyserver.ubuntu.com --recv-keys "$key" && gpg --batch --fingerprint "$key"; } ; \ done \ && curl -fsSLO --compressed "https://yarnpkg.com/downloads/$YARN_VERSION/yarn-v$YARN_VERSION.tar.gz" \ && curl -fsSLO --compressed "https://yarnpkg.com/downloads/$YARN_VERSION/yarn-v$YARN_VERSION.tar.gz.asc" \ && gpg --batch --verify yarn-v$YARN_VERSION.tar.gz.asc yarn-v$YARN_VERSION.tar.gz \ && gpgconf --kill all \ && rm -rf "$GNUPGHOME" \ && mkdir -p /opt \ && tar -xzf yarn-v$YARN_VERSION.tar.gz -C /opt/ \ && ln -s /opt/yarn-v$YARN_VERSION/bin/yarn /usr/local/bin/yarn \ && ln -s /opt/yarn-v$YARN_VERSION/bin/yarnpkg /usr/local/bin/yarnpkg \ && rm yarn-v$YARN_VERSION.tar.gz.asc yarn-v$YARN_VERSION.tar.gz \ && apk del .build-deps-yarn \ # smoke test && yarn --version \ && rm -rf /tmp/* COPY docker-entrypoint.sh /usr/local/bin/ ENTRYPOINT ["docker-entrypoint.sh"] CMD [ "node" ] ================================================ FILE: 25/alpine3.22/docker-entrypoint.sh ================================================ #!/bin/sh set -e # Run command with node if the first argument contains a "-" or is not a system command. The last # part inside the "{}" is a workaround for the following bug in ash/dash: # https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=874264 if [ "${1#-}" != "${1}" ] || [ -z "$(command -v "${1}")" ] || { [ -f "${1}" ] && ! [ -x "${1}" ]; }; then set -- node "$@" fi exec "$@" ================================================ FILE: 25/alpine3.23/Dockerfile ================================================ FROM alpine:3.23 ENV NODE_VERSION=25.8.1 RUN addgroup -g 1000 node \ && adduser -u 1000 -G node -s /bin/sh -D node \ && apk add --no-cache \ libstdc++ \ && apk add --no-cache --virtual .build-deps \ curl \ && ARCH= OPENSSL_ARCH='linux*' && alpineArch="$(apk --print-arch)" \ && case "${alpineArch##*-}" in \ x86_64) ARCH='x64' CHECKSUM="f056db4cc177c28d1809fb5bdd72ce058088ab5bd7d800af24b20e2580034028" OPENSSL_ARCH=linux-x86_64;; \ x86) OPENSSL_ARCH=linux-elf;; \ aarch64) OPENSSL_ARCH=linux-aarch64;; \ arm*) OPENSSL_ARCH=linux-armv4;; \ ppc64le) OPENSSL_ARCH=linux-ppc64le;; \ s390x) OPENSSL_ARCH=linux-s390x;; \ *) ;; \ esac \ && if [ -n "${CHECKSUM}" ]; then \ set -eu; \ curl -fsSLO --compressed "https://unofficial-builds.nodejs.org/download/release/v$NODE_VERSION/node-v$NODE_VERSION-linux-$ARCH-musl.tar.xz"; \ echo "$CHECKSUM node-v$NODE_VERSION-linux-$ARCH-musl.tar.xz" | sha256sum -c - \ && tar -xJf "node-v$NODE_VERSION-linux-$ARCH-musl.tar.xz" -C /usr/local --strip-components=1 --no-same-owner \ && ln -s /usr/local/bin/node /usr/local/bin/nodejs; \ else \ echo "Building from source" \ # backup build && apk add --no-cache --virtual .build-deps-full \ binutils-gold \ g++ \ gcc \ gnupg \ libgcc \ linux-headers \ make \ python3 \ py-setuptools \ # use pre-existing gpg directory, see https://github.com/nodejs/docker-node/pull/1895#issuecomment-1550389150 && export GNUPGHOME="$(mktemp -d)" \ # gpg keys listed at https://github.com/nodejs/node#release-keys && for key in \ 5BE8A3F6C8A5C01D106C0AD820B1A390B168D356 \ DD792F5973C6DE52C432CBDAC77ABFA00DDBF2B7 \ CC68F5A3106FF448322E48ED27F5E38D5B0A215F \ 8FCCA13FEF1D0C2E91008E09770F7A9A5AE15600 \ 890C08DB8579162FEE0DF9DB8BEAB4DFCF555EF4 \ C82FA3AE1CBEDC6BE46B9360C43CEC45C17AB93C \ 108F52B48DB57BB0CC439B2997B01419BD92F80A \ A363A499291CBBC940DD62E41F10027AF002F8B0 \ ; do \ { gpg --batch --keyserver hkps://keys.openpgp.org --recv-keys "$key" && gpg --batch --fingerprint "$key"; } || \ { gpg --batch --keyserver keyserver.ubuntu.com --recv-keys "$key" && gpg --batch --fingerprint "$key"; } ; \ done \ && curl -fsSLO --compressed "https://nodejs.org/dist/v$NODE_VERSION/node-v$NODE_VERSION.tar.xz" \ && curl -fsSLO --compressed "https://nodejs.org/dist/v$NODE_VERSION/SHASUMS256.txt.asc" \ && gpg --batch --decrypt --output SHASUMS256.txt SHASUMS256.txt.asc \ && gpgconf --kill all \ && rm -rf "$GNUPGHOME" \ && grep " node-v$NODE_VERSION.tar.xz\$" SHASUMS256.txt | sha256sum -c - \ && tar -xf "node-v$NODE_VERSION.tar.xz" \ && cd "node-v$NODE_VERSION" \ && ./configure \ && make -j$(getconf _NPROCESSORS_ONLN) V= \ && make install \ && apk del .build-deps-full \ && cd .. \ && rm -Rf "node-v$NODE_VERSION" \ && rm "node-v$NODE_VERSION.tar.xz" SHASUMS256.txt.asc SHASUMS256.txt; \ fi \ && rm -f "node-v$NODE_VERSION-linux-$ARCH-musl.tar.xz" \ # Remove unused OpenSSL headers to save ~34MB. See this NodeJS issue: https://github.com/nodejs/node/issues/46451 && find /usr/local/include/node/openssl/archs -mindepth 1 -maxdepth 1 ! -name "$OPENSSL_ARCH" -exec rm -rf {} \; \ && apk del .build-deps \ # smoke tests && node --version \ && npm --version \ && rm -rf /tmp/* ENV YARN_VERSION=1.22.22 RUN apk add --no-cache --virtual .build-deps-yarn curl gnupg tar \ # use pre-existing gpg directory, see https://github.com/nodejs/docker-node/pull/1895#issuecomment-1550389150 && export GNUPGHOME="$(mktemp -d)" \ && for key in \ 6A010C5166006599AA17F08146C2130DFD2497F5 \ ; do \ { gpg --batch --keyserver hkps://keys.openpgp.org --recv-keys "$key" && gpg --batch --fingerprint "$key"; } || \ { gpg --batch --keyserver keyserver.ubuntu.com --recv-keys "$key" && gpg --batch --fingerprint "$key"; } ; \ done \ && curl -fsSLO --compressed "https://yarnpkg.com/downloads/$YARN_VERSION/yarn-v$YARN_VERSION.tar.gz" \ && curl -fsSLO --compressed "https://yarnpkg.com/downloads/$YARN_VERSION/yarn-v$YARN_VERSION.tar.gz.asc" \ && gpg --batch --verify yarn-v$YARN_VERSION.tar.gz.asc yarn-v$YARN_VERSION.tar.gz \ && gpgconf --kill all \ && rm -rf "$GNUPGHOME" \ && mkdir -p /opt \ && tar -xzf yarn-v$YARN_VERSION.tar.gz -C /opt/ \ && ln -s /opt/yarn-v$YARN_VERSION/bin/yarn /usr/local/bin/yarn \ && ln -s /opt/yarn-v$YARN_VERSION/bin/yarnpkg /usr/local/bin/yarnpkg \ && rm yarn-v$YARN_VERSION.tar.gz.asc yarn-v$YARN_VERSION.tar.gz \ && apk del .build-deps-yarn \ # smoke test && yarn --version \ && rm -rf /tmp/* COPY docker-entrypoint.sh /usr/local/bin/ ENTRYPOINT ["docker-entrypoint.sh"] CMD [ "node" ] ================================================ FILE: 25/alpine3.23/docker-entrypoint.sh ================================================ #!/bin/sh set -e # Run command with node if the first argument contains a "-" or is not a system command. The last # part inside the "{}" is a workaround for the following bug in ash/dash: # https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=874264 if [ "${1#-}" != "${1}" ] || [ -z "$(command -v "${1}")" ] || { [ -f "${1}" ] && ! [ -x "${1}" ]; }; then set -- node "$@" fi exec "$@" ================================================ FILE: 25/bookworm/Dockerfile ================================================ FROM buildpack-deps:bookworm RUN groupadd --gid 1000 node \ && useradd --uid 1000 --gid node --shell /bin/bash --create-home node ENV NODE_VERSION=25.8.1 RUN ARCH= && dpkgArch="$(dpkg --print-architecture)" \ && case "${dpkgArch##*-}" in \ amd64) ARCH='x64';; \ ppc64el) ARCH='ppc64le';; \ s390x) ARCH='s390x';; \ arm64) ARCH='arm64';; \ armhf) ARCH='armv7l';; \ i386) ARCH='x86';; \ *) echo "unsupported architecture"; exit 1 ;; \ esac \ # use pre-existing gpg directory, see https://github.com/nodejs/docker-node/pull/1895#issuecomment-1550389150 && export GNUPGHOME="$(mktemp -d)" \ # gpg keys listed at https://github.com/nodejs/node#release-keys && set -ex \ && for key in \ 5BE8A3F6C8A5C01D106C0AD820B1A390B168D356 \ DD792F5973C6DE52C432CBDAC77ABFA00DDBF2B7 \ CC68F5A3106FF448322E48ED27F5E38D5B0A215F \ 8FCCA13FEF1D0C2E91008E09770F7A9A5AE15600 \ 890C08DB8579162FEE0DF9DB8BEAB4DFCF555EF4 \ C82FA3AE1CBEDC6BE46B9360C43CEC45C17AB93C \ 108F52B48DB57BB0CC439B2997B01419BD92F80A \ A363A499291CBBC940DD62E41F10027AF002F8B0 \ ; do \ { gpg --batch --keyserver hkps://keys.openpgp.org --recv-keys "$key" && gpg --batch --fingerprint "$key"; } || \ { gpg --batch --keyserver keyserver.ubuntu.com --recv-keys "$key" && gpg --batch --fingerprint "$key"; } ; \ done \ && curl -fsSLO --compressed "https://nodejs.org/dist/v$NODE_VERSION/node-v$NODE_VERSION-linux-$ARCH.tar.xz" \ && curl -fsSLO --compressed "https://nodejs.org/dist/v$NODE_VERSION/SHASUMS256.txt.asc" \ && gpg --batch --decrypt --output SHASUMS256.txt SHASUMS256.txt.asc \ && gpgconf --kill all \ && rm -rf "$GNUPGHOME" \ && grep " node-v$NODE_VERSION-linux-$ARCH.tar.xz\$" SHASUMS256.txt | sha256sum -c - \ && tar -xJf "node-v$NODE_VERSION-linux-$ARCH.tar.xz" -C /usr/local --strip-components=1 --no-same-owner \ && rm "node-v$NODE_VERSION-linux-$ARCH.tar.xz" SHASUMS256.txt.asc SHASUMS256.txt \ && ln -s /usr/local/bin/node /usr/local/bin/nodejs \ # smoke tests && node --version \ && npm --version \ && rm -rf /tmp/* ENV YARN_VERSION=1.22.22 RUN set -ex \ # use pre-existing gpg directory, see https://github.com/nodejs/docker-node/pull/1895#issuecomment-1550389150 && export GNUPGHOME="$(mktemp -d)" \ && for key in \ 6A010C5166006599AA17F08146C2130DFD2497F5 \ ; do \ { gpg --batch --keyserver hkps://keys.openpgp.org --recv-keys "$key" && gpg --batch --fingerprint "$key"; } || \ { gpg --batch --keyserver keyserver.ubuntu.com --recv-keys "$key" && gpg --batch --fingerprint "$key"; } ; \ done \ && curl -fsSLO --compressed "https://yarnpkg.com/downloads/$YARN_VERSION/yarn-v$YARN_VERSION.tar.gz" \ && curl -fsSLO --compressed "https://yarnpkg.com/downloads/$YARN_VERSION/yarn-v$YARN_VERSION.tar.gz.asc" \ && gpg --batch --verify yarn-v$YARN_VERSION.tar.gz.asc yarn-v$YARN_VERSION.tar.gz \ && gpgconf --kill all \ && rm -rf "$GNUPGHOME" \ && mkdir -p /opt \ && tar -xzf yarn-v$YARN_VERSION.tar.gz -C /opt/ \ && ln -s /opt/yarn-v$YARN_VERSION/bin/yarn /usr/local/bin/yarn \ && ln -s /opt/yarn-v$YARN_VERSION/bin/yarnpkg /usr/local/bin/yarnpkg \ && rm yarn-v$YARN_VERSION.tar.gz.asc yarn-v$YARN_VERSION.tar.gz \ # smoke test && yarn --version \ && rm -rf /tmp/* COPY docker-entrypoint.sh /usr/local/bin/ ENTRYPOINT ["docker-entrypoint.sh"] CMD [ "node" ] ================================================ FILE: 25/bookworm/docker-entrypoint.sh ================================================ #!/bin/sh set -e # Run command with node if the first argument contains a "-" or is not a system command. The last # part inside the "{}" is a workaround for the following bug in ash/dash: # https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=874264 if [ "${1#-}" != "${1}" ] || [ -z "$(command -v "${1}")" ] || { [ -f "${1}" ] && ! [ -x "${1}" ]; }; then set -- node "$@" fi exec "$@" ================================================ FILE: 25/bookworm-slim/Dockerfile ================================================ FROM debian:bookworm-slim RUN groupadd --gid 1000 node \ && useradd --uid 1000 --gid node --shell /bin/bash --create-home node ENV NODE_VERSION=25.8.1 RUN ARCH= OPENSSL_ARCH= && dpkgArch="$(dpkg --print-architecture)" \ && case "${dpkgArch##*-}" in \ amd64) ARCH='x64' OPENSSL_ARCH='linux-x86_64';; \ ppc64el) ARCH='ppc64le' OPENSSL_ARCH='linux-ppc64le';; \ s390x) ARCH='s390x' OPENSSL_ARCH='linux*-s390x';; \ arm64) ARCH='arm64' OPENSSL_ARCH='linux-aarch64';; \ armhf) ARCH='armv7l' OPENSSL_ARCH='linux-armv4';; \ i386) ARCH='x86' OPENSSL_ARCH='linux-elf';; \ *) echo "unsupported architecture"; exit 1 ;; \ esac \ && set -ex \ # libatomic1 for arm && apt-get update && apt-get install -y ca-certificates curl wget gnupg dirmngr xz-utils libatomic1 --no-install-recommends \ && rm -rf /var/lib/apt/lists/* \ # use pre-existing gpg directory, see https://github.com/nodejs/docker-node/pull/1895#issuecomment-1550389150 && export GNUPGHOME="$(mktemp -d)" \ # gpg keys listed at https://github.com/nodejs/node#release-keys && for key in \ 5BE8A3F6C8A5C01D106C0AD820B1A390B168D356 \ DD792F5973C6DE52C432CBDAC77ABFA00DDBF2B7 \ CC68F5A3106FF448322E48ED27F5E38D5B0A215F \ 8FCCA13FEF1D0C2E91008E09770F7A9A5AE15600 \ 890C08DB8579162FEE0DF9DB8BEAB4DFCF555EF4 \ C82FA3AE1CBEDC6BE46B9360C43CEC45C17AB93C \ 108F52B48DB57BB0CC439B2997B01419BD92F80A \ A363A499291CBBC940DD62E41F10027AF002F8B0 \ ; do \ { gpg --batch --keyserver hkps://keys.openpgp.org --recv-keys "$key" && gpg --batch --fingerprint "$key"; } || \ { gpg --batch --keyserver keyserver.ubuntu.com --recv-keys "$key" && gpg --batch --fingerprint "$key"; } ; \ done \ && curl -fsSLO --compressed "https://nodejs.org/dist/v$NODE_VERSION/node-v$NODE_VERSION-linux-$ARCH.tar.xz" \ && curl -fsSLO --compressed "https://nodejs.org/dist/v$NODE_VERSION/SHASUMS256.txt.asc" \ && gpg --batch --decrypt --output SHASUMS256.txt SHASUMS256.txt.asc \ && gpgconf --kill all \ && rm -rf "$GNUPGHOME" \ && grep " node-v$NODE_VERSION-linux-$ARCH.tar.xz\$" SHASUMS256.txt | sha256sum -c - \ && tar -xJf "node-v$NODE_VERSION-linux-$ARCH.tar.xz" -C /usr/local --strip-components=1 --no-same-owner \ && rm "node-v$NODE_VERSION-linux-$ARCH.tar.xz" SHASUMS256.txt.asc SHASUMS256.txt \ # Remove unused OpenSSL headers to save ~34MB. See this NodeJS issue: https://github.com/nodejs/node/issues/46451 && find /usr/local/include/node/openssl/archs -mindepth 1 -maxdepth 1 ! -name "$OPENSSL_ARCH" -exec rm -rf {} \; \ && apt-mark auto '.*' > /dev/null \ && find /usr/local -type f -executable -exec ldd '{}' ';' \ | awk '/=>/ { so = $(NF-1); if (index(so, "/usr/local/") == 1) { next }; gsub("^/(usr/)?", "", so); print so }' \ | sort -u \ | xargs -r dpkg-query --search \ | cut -d: -f1 \ | sort -u \ | xargs -r apt-mark manual \ && apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false \ && ln -s /usr/local/bin/node /usr/local/bin/nodejs \ # smoke tests && node --version \ && npm --version \ && rm -rf /tmp/* ENV YARN_VERSION=1.22.22 RUN set -ex \ && savedAptMark="$(apt-mark showmanual)" \ && apt-get update && apt-get install -y ca-certificates curl wget gnupg dirmngr --no-install-recommends \ && rm -rf /var/lib/apt/lists/* \ # use pre-existing gpg directory, see https://github.com/nodejs/docker-node/pull/1895#issuecomment-1550389150 && export GNUPGHOME="$(mktemp -d)" \ && for key in \ 6A010C5166006599AA17F08146C2130DFD2497F5 \ ; do \ { gpg --batch --keyserver hkps://keys.openpgp.org --recv-keys "$key" && gpg --batch --fingerprint "$key"; } || \ { gpg --batch --keyserver keyserver.ubuntu.com --recv-keys "$key" && gpg --batch --fingerprint "$key"; } ; \ done \ && curl -fsSLO --compressed "https://yarnpkg.com/downloads/$YARN_VERSION/yarn-v$YARN_VERSION.tar.gz" \ && curl -fsSLO --compressed "https://yarnpkg.com/downloads/$YARN_VERSION/yarn-v$YARN_VERSION.tar.gz.asc" \ && gpg --batch --verify yarn-v$YARN_VERSION.tar.gz.asc yarn-v$YARN_VERSION.tar.gz \ && gpgconf --kill all \ && rm -rf "$GNUPGHOME" \ && mkdir -p /opt \ && tar -xzf yarn-v$YARN_VERSION.tar.gz -C /opt/ \ && ln -s /opt/yarn-v$YARN_VERSION/bin/yarn /usr/local/bin/yarn \ && ln -s /opt/yarn-v$YARN_VERSION/bin/yarnpkg /usr/local/bin/yarnpkg \ && rm yarn-v$YARN_VERSION.tar.gz.asc yarn-v$YARN_VERSION.tar.gz \ && apt-mark auto '.*' > /dev/null \ && { [ -z "$savedAptMark" ] || apt-mark manual $savedAptMark > /dev/null; } \ && find /usr/local -type f -executable -exec ldd '{}' ';' \ | awk '/=>/ { so = $(NF-1); if (index(so, "/usr/local/") == 1) { next }; gsub("^/(usr/)?", "", so); print so }' \ | sort -u \ | xargs -r dpkg-query --search \ | cut -d: -f1 \ | sort -u \ | xargs -r apt-mark manual \ && apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false \ # smoke test && yarn --version \ && rm -rf /tmp/* COPY docker-entrypoint.sh /usr/local/bin/ ENTRYPOINT ["docker-entrypoint.sh"] CMD [ "node" ] ================================================ FILE: 25/bookworm-slim/docker-entrypoint.sh ================================================ #!/bin/sh set -e # Run command with node if the first argument contains a "-" or is not a system command. The last # part inside the "{}" is a workaround for the following bug in ash/dash: # https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=874264 if [ "${1#-}" != "${1}" ] || [ -z "$(command -v "${1}")" ] || { [ -f "${1}" ] && ! [ -x "${1}" ]; }; then set -- node "$@" fi exec "$@" ================================================ FILE: 25/bullseye/Dockerfile ================================================ FROM buildpack-deps:bullseye RUN groupadd --gid 1000 node \ && useradd --uid 1000 --gid node --shell /bin/bash --create-home node ENV NODE_VERSION=25.8.1 RUN ARCH= && dpkgArch="$(dpkg --print-architecture)" \ && case "${dpkgArch##*-}" in \ amd64) ARCH='x64';; \ ppc64el) ARCH='ppc64le';; \ s390x) ARCH='s390x';; \ arm64) ARCH='arm64';; \ armhf) ARCH='armv7l';; \ i386) ARCH='x86';; \ *) echo "unsupported architecture"; exit 1 ;; \ esac \ # use pre-existing gpg directory, see https://github.com/nodejs/docker-node/pull/1895#issuecomment-1550389150 && export GNUPGHOME="$(mktemp -d)" \ # gpg keys listed at https://github.com/nodejs/node#release-keys && set -ex \ && for key in \ 5BE8A3F6C8A5C01D106C0AD820B1A390B168D356 \ DD792F5973C6DE52C432CBDAC77ABFA00DDBF2B7 \ CC68F5A3106FF448322E48ED27F5E38D5B0A215F \ 8FCCA13FEF1D0C2E91008E09770F7A9A5AE15600 \ 890C08DB8579162FEE0DF9DB8BEAB4DFCF555EF4 \ C82FA3AE1CBEDC6BE46B9360C43CEC45C17AB93C \ 108F52B48DB57BB0CC439B2997B01419BD92F80A \ A363A499291CBBC940DD62E41F10027AF002F8B0 \ ; do \ { gpg --batch --keyserver hkps://keys.openpgp.org --recv-keys "$key" && gpg --batch --fingerprint "$key"; } || \ { gpg --batch --keyserver keyserver.ubuntu.com --recv-keys "$key" && gpg --batch --fingerprint "$key"; } ; \ done \ && curl -fsSLO --compressed "https://nodejs.org/dist/v$NODE_VERSION/node-v$NODE_VERSION-linux-$ARCH.tar.xz" \ && curl -fsSLO --compressed "https://nodejs.org/dist/v$NODE_VERSION/SHASUMS256.txt.asc" \ && gpg --batch --decrypt --output SHASUMS256.txt SHASUMS256.txt.asc \ && gpgconf --kill all \ && rm -rf "$GNUPGHOME" \ && grep " node-v$NODE_VERSION-linux-$ARCH.tar.xz\$" SHASUMS256.txt | sha256sum -c - \ && tar -xJf "node-v$NODE_VERSION-linux-$ARCH.tar.xz" -C /usr/local --strip-components=1 --no-same-owner \ && rm "node-v$NODE_VERSION-linux-$ARCH.tar.xz" SHASUMS256.txt.asc SHASUMS256.txt \ && ln -s /usr/local/bin/node /usr/local/bin/nodejs \ # smoke tests && node --version \ && npm --version \ && rm -rf /tmp/* ENV YARN_VERSION=1.22.22 RUN set -ex \ # use pre-existing gpg directory, see https://github.com/nodejs/docker-node/pull/1895#issuecomment-1550389150 && export GNUPGHOME="$(mktemp -d)" \ && for key in \ 6A010C5166006599AA17F08146C2130DFD2497F5 \ ; do \ { gpg --batch --keyserver hkps://keys.openpgp.org --recv-keys "$key" && gpg --batch --fingerprint "$key"; } || \ { gpg --batch --keyserver keyserver.ubuntu.com --recv-keys "$key" && gpg --batch --fingerprint "$key"; } ; \ done \ && curl -fsSLO --compressed "https://yarnpkg.com/downloads/$YARN_VERSION/yarn-v$YARN_VERSION.tar.gz" \ && curl -fsSLO --compressed "https://yarnpkg.com/downloads/$YARN_VERSION/yarn-v$YARN_VERSION.tar.gz.asc" \ && gpg --batch --verify yarn-v$YARN_VERSION.tar.gz.asc yarn-v$YARN_VERSION.tar.gz \ && gpgconf --kill all \ && rm -rf "$GNUPGHOME" \ && mkdir -p /opt \ && tar -xzf yarn-v$YARN_VERSION.tar.gz -C /opt/ \ && ln -s /opt/yarn-v$YARN_VERSION/bin/yarn /usr/local/bin/yarn \ && ln -s /opt/yarn-v$YARN_VERSION/bin/yarnpkg /usr/local/bin/yarnpkg \ && rm yarn-v$YARN_VERSION.tar.gz.asc yarn-v$YARN_VERSION.tar.gz \ # smoke test && yarn --version \ && rm -rf /tmp/* COPY docker-entrypoint.sh /usr/local/bin/ ENTRYPOINT ["docker-entrypoint.sh"] CMD [ "node" ] ================================================ FILE: 25/bullseye/docker-entrypoint.sh ================================================ #!/bin/sh set -e # Run command with node if the first argument contains a "-" or is not a system command. The last # part inside the "{}" is a workaround for the following bug in ash/dash: # https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=874264 if [ "${1#-}" != "${1}" ] || [ -z "$(command -v "${1}")" ] || { [ -f "${1}" ] && ! [ -x "${1}" ]; }; then set -- node "$@" fi exec "$@" ================================================ FILE: 25/bullseye-slim/Dockerfile ================================================ FROM debian:bullseye-slim RUN groupadd --gid 1000 node \ && useradd --uid 1000 --gid node --shell /bin/bash --create-home node ENV NODE_VERSION=25.8.1 RUN ARCH= OPENSSL_ARCH= && dpkgArch="$(dpkg --print-architecture)" \ && case "${dpkgArch##*-}" in \ amd64) ARCH='x64' OPENSSL_ARCH='linux-x86_64';; \ ppc64el) ARCH='ppc64le' OPENSSL_ARCH='linux-ppc64le';; \ s390x) ARCH='s390x' OPENSSL_ARCH='linux*-s390x';; \ arm64) ARCH='arm64' OPENSSL_ARCH='linux-aarch64';; \ armhf) ARCH='armv7l' OPENSSL_ARCH='linux-armv4';; \ i386) ARCH='x86' OPENSSL_ARCH='linux-elf';; \ *) echo "unsupported architecture"; exit 1 ;; \ esac \ && set -ex \ # libatomic1 for arm && apt-get update && apt-get install -y ca-certificates curl wget gnupg dirmngr xz-utils libatomic1 --no-install-recommends \ && rm -rf /var/lib/apt/lists/* \ # use pre-existing gpg directory, see https://github.com/nodejs/docker-node/pull/1895#issuecomment-1550389150 && export GNUPGHOME="$(mktemp -d)" \ # gpg keys listed at https://github.com/nodejs/node#release-keys && for key in \ 5BE8A3F6C8A5C01D106C0AD820B1A390B168D356 \ DD792F5973C6DE52C432CBDAC77ABFA00DDBF2B7 \ CC68F5A3106FF448322E48ED27F5E38D5B0A215F \ 8FCCA13FEF1D0C2E91008E09770F7A9A5AE15600 \ 890C08DB8579162FEE0DF9DB8BEAB4DFCF555EF4 \ C82FA3AE1CBEDC6BE46B9360C43CEC45C17AB93C \ 108F52B48DB57BB0CC439B2997B01419BD92F80A \ A363A499291CBBC940DD62E41F10027AF002F8B0 \ ; do \ { gpg --batch --keyserver hkps://keys.openpgp.org --recv-keys "$key" && gpg --batch --fingerprint "$key"; } || \ { gpg --batch --keyserver keyserver.ubuntu.com --recv-keys "$key" && gpg --batch --fingerprint "$key"; } ; \ done \ && curl -fsSLO --compressed "https://nodejs.org/dist/v$NODE_VERSION/node-v$NODE_VERSION-linux-$ARCH.tar.xz" \ && curl -fsSLO --compressed "https://nodejs.org/dist/v$NODE_VERSION/SHASUMS256.txt.asc" \ && gpg --batch --decrypt --output SHASUMS256.txt SHASUMS256.txt.asc \ && gpgconf --kill all \ && rm -rf "$GNUPGHOME" \ && grep " node-v$NODE_VERSION-linux-$ARCH.tar.xz\$" SHASUMS256.txt | sha256sum -c - \ && tar -xJf "node-v$NODE_VERSION-linux-$ARCH.tar.xz" -C /usr/local --strip-components=1 --no-same-owner \ && rm "node-v$NODE_VERSION-linux-$ARCH.tar.xz" SHASUMS256.txt.asc SHASUMS256.txt \ # Remove unused OpenSSL headers to save ~34MB. See this NodeJS issue: https://github.com/nodejs/node/issues/46451 && find /usr/local/include/node/openssl/archs -mindepth 1 -maxdepth 1 ! -name "$OPENSSL_ARCH" -exec rm -rf {} \; \ && apt-mark auto '.*' > /dev/null \ && find /usr/local -type f -executable -exec ldd '{}' ';' \ | awk '/=>/ { so = $(NF-1); if (index(so, "/usr/local/") == 1) { next }; gsub("^/(usr/)?", "", so); print so }' \ | sort -u \ | xargs -r dpkg-query --search \ | cut -d: -f1 \ | sort -u \ | xargs -r apt-mark manual \ && apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false \ && ln -s /usr/local/bin/node /usr/local/bin/nodejs \ # smoke tests && node --version \ && npm --version \ && rm -rf /tmp/* ENV YARN_VERSION=1.22.22 RUN set -ex \ && savedAptMark="$(apt-mark showmanual)" \ && apt-get update && apt-get install -y ca-certificates curl wget gnupg dirmngr --no-install-recommends \ && rm -rf /var/lib/apt/lists/* \ # use pre-existing gpg directory, see https://github.com/nodejs/docker-node/pull/1895#issuecomment-1550389150 && export GNUPGHOME="$(mktemp -d)" \ && for key in \ 6A010C5166006599AA17F08146C2130DFD2497F5 \ ; do \ { gpg --batch --keyserver hkps://keys.openpgp.org --recv-keys "$key" && gpg --batch --fingerprint "$key"; } || \ { gpg --batch --keyserver keyserver.ubuntu.com --recv-keys "$key" && gpg --batch --fingerprint "$key"; } ; \ done \ && curl -fsSLO --compressed "https://yarnpkg.com/downloads/$YARN_VERSION/yarn-v$YARN_VERSION.tar.gz" \ && curl -fsSLO --compressed "https://yarnpkg.com/downloads/$YARN_VERSION/yarn-v$YARN_VERSION.tar.gz.asc" \ && gpg --batch --verify yarn-v$YARN_VERSION.tar.gz.asc yarn-v$YARN_VERSION.tar.gz \ && gpgconf --kill all \ && rm -rf "$GNUPGHOME" \ && mkdir -p /opt \ && tar -xzf yarn-v$YARN_VERSION.tar.gz -C /opt/ \ && ln -s /opt/yarn-v$YARN_VERSION/bin/yarn /usr/local/bin/yarn \ && ln -s /opt/yarn-v$YARN_VERSION/bin/yarnpkg /usr/local/bin/yarnpkg \ && rm yarn-v$YARN_VERSION.tar.gz.asc yarn-v$YARN_VERSION.tar.gz \ && apt-mark auto '.*' > /dev/null \ && { [ -z "$savedAptMark" ] || apt-mark manual $savedAptMark > /dev/null; } \ && find /usr/local -type f -executable -exec ldd '{}' ';' \ | awk '/=>/ { so = $(NF-1); if (index(so, "/usr/local/") == 1) { next }; gsub("^/(usr/)?", "", so); print so }' \ | sort -u \ | xargs -r dpkg-query --search \ | cut -d: -f1 \ | sort -u \ | xargs -r apt-mark manual \ && apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false \ # smoke test && yarn --version \ && rm -rf /tmp/* COPY docker-entrypoint.sh /usr/local/bin/ ENTRYPOINT ["docker-entrypoint.sh"] CMD [ "node" ] ================================================ FILE: 25/bullseye-slim/docker-entrypoint.sh ================================================ #!/bin/sh set -e # Run command with node if the first argument contains a "-" or is not a system command. The last # part inside the "{}" is a workaround for the following bug in ash/dash: # https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=874264 if [ "${1#-}" != "${1}" ] || [ -z "$(command -v "${1}")" ] || { [ -f "${1}" ] && ! [ -x "${1}" ]; }; then set -- node "$@" fi exec "$@" ================================================ FILE: 25/trixie/Dockerfile ================================================ FROM buildpack-deps:trixie RUN groupadd --gid 1000 node \ && useradd --uid 1000 --gid node --shell /bin/bash --create-home node ENV NODE_VERSION=25.8.1 RUN ARCH= && dpkgArch="$(dpkg --print-architecture)" \ && case "${dpkgArch##*-}" in \ amd64) ARCH='x64';; \ ppc64el) ARCH='ppc64le';; \ s390x) ARCH='s390x';; \ arm64) ARCH='arm64';; \ armhf) ARCH='armv7l';; \ i386) ARCH='x86';; \ *) echo "unsupported architecture"; exit 1 ;; \ esac \ # use pre-existing gpg directory, see https://github.com/nodejs/docker-node/pull/1895#issuecomment-1550389150 && export GNUPGHOME="$(mktemp -d)" \ # gpg keys listed at https://github.com/nodejs/node#release-keys && set -ex \ && for key in \ 5BE8A3F6C8A5C01D106C0AD820B1A390B168D356 \ DD792F5973C6DE52C432CBDAC77ABFA00DDBF2B7 \ CC68F5A3106FF448322E48ED27F5E38D5B0A215F \ 8FCCA13FEF1D0C2E91008E09770F7A9A5AE15600 \ 890C08DB8579162FEE0DF9DB8BEAB4DFCF555EF4 \ C82FA3AE1CBEDC6BE46B9360C43CEC45C17AB93C \ 108F52B48DB57BB0CC439B2997B01419BD92F80A \ A363A499291CBBC940DD62E41F10027AF002F8B0 \ ; do \ { gpg --batch --keyserver hkps://keys.openpgp.org --recv-keys "$key" && gpg --batch --fingerprint "$key"; } || \ { gpg --batch --keyserver keyserver.ubuntu.com --recv-keys "$key" && gpg --batch --fingerprint "$key"; } ; \ done \ && curl -fsSLO --compressed "https://nodejs.org/dist/v$NODE_VERSION/node-v$NODE_VERSION-linux-$ARCH.tar.xz" \ && curl -fsSLO --compressed "https://nodejs.org/dist/v$NODE_VERSION/SHASUMS256.txt.asc" \ && gpg --batch --decrypt --output SHASUMS256.txt SHASUMS256.txt.asc \ && gpgconf --kill all \ && rm -rf "$GNUPGHOME" \ && grep " node-v$NODE_VERSION-linux-$ARCH.tar.xz\$" SHASUMS256.txt | sha256sum -c - \ && tar -xJf "node-v$NODE_VERSION-linux-$ARCH.tar.xz" -C /usr/local --strip-components=1 --no-same-owner \ && rm "node-v$NODE_VERSION-linux-$ARCH.tar.xz" SHASUMS256.txt.asc SHASUMS256.txt \ && ln -s /usr/local/bin/node /usr/local/bin/nodejs \ # smoke tests && node --version \ && npm --version \ && rm -rf /tmp/* ENV YARN_VERSION=1.22.22 RUN set -ex \ # use pre-existing gpg directory, see https://github.com/nodejs/docker-node/pull/1895#issuecomment-1550389150 && export GNUPGHOME="$(mktemp -d)" \ && for key in \ 6A010C5166006599AA17F08146C2130DFD2497F5 \ ; do \ { gpg --batch --keyserver hkps://keys.openpgp.org --recv-keys "$key" && gpg --batch --fingerprint "$key"; } || \ { gpg --batch --keyserver keyserver.ubuntu.com --recv-keys "$key" && gpg --batch --fingerprint "$key"; } ; \ done \ && curl -fsSLO --compressed "https://yarnpkg.com/downloads/$YARN_VERSION/yarn-v$YARN_VERSION.tar.gz" \ && curl -fsSLO --compressed "https://yarnpkg.com/downloads/$YARN_VERSION/yarn-v$YARN_VERSION.tar.gz.asc" \ && gpg --batch --verify yarn-v$YARN_VERSION.tar.gz.asc yarn-v$YARN_VERSION.tar.gz \ && gpgconf --kill all \ && rm -rf "$GNUPGHOME" \ && mkdir -p /opt \ && tar -xzf yarn-v$YARN_VERSION.tar.gz -C /opt/ \ && ln -s /opt/yarn-v$YARN_VERSION/bin/yarn /usr/local/bin/yarn \ && ln -s /opt/yarn-v$YARN_VERSION/bin/yarnpkg /usr/local/bin/yarnpkg \ && rm yarn-v$YARN_VERSION.tar.gz.asc yarn-v$YARN_VERSION.tar.gz \ # smoke test && yarn --version \ && rm -rf /tmp/* COPY docker-entrypoint.sh /usr/local/bin/ ENTRYPOINT ["docker-entrypoint.sh"] CMD [ "node" ] ================================================ FILE: 25/trixie/docker-entrypoint.sh ================================================ #!/bin/sh set -e # Run command with node if the first argument contains a "-" or is not a system command. The last # part inside the "{}" is a workaround for the following bug in ash/dash: # https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=874264 if [ "${1#-}" != "${1}" ] || [ -z "$(command -v "${1}")" ] || { [ -f "${1}" ] && ! [ -x "${1}" ]; }; then set -- node "$@" fi exec "$@" ================================================ FILE: 25/trixie-slim/Dockerfile ================================================ FROM debian:trixie-slim RUN groupadd --gid 1000 node \ && useradd --uid 1000 --gid node --shell /bin/bash --create-home node ENV NODE_VERSION=25.8.1 RUN ARCH= OPENSSL_ARCH= && dpkgArch="$(dpkg --print-architecture)" \ && case "${dpkgArch##*-}" in \ amd64) ARCH='x64' OPENSSL_ARCH='linux-x86_64';; \ ppc64el) ARCH='ppc64le' OPENSSL_ARCH='linux-ppc64le';; \ s390x) ARCH='s390x' OPENSSL_ARCH='linux*-s390x';; \ arm64) ARCH='arm64' OPENSSL_ARCH='linux-aarch64';; \ armhf) ARCH='armv7l' OPENSSL_ARCH='linux-armv4';; \ i386) ARCH='x86' OPENSSL_ARCH='linux-elf';; \ *) echo "unsupported architecture"; exit 1 ;; \ esac \ && set -ex \ # libatomic1 for arm && apt-get update && apt-get install -y ca-certificates curl wget gnupg dirmngr xz-utils libatomic1 --no-install-recommends \ && rm -rf /var/lib/apt/lists/* \ # use pre-existing gpg directory, see https://github.com/nodejs/docker-node/pull/1895#issuecomment-1550389150 && export GNUPGHOME="$(mktemp -d)" \ # gpg keys listed at https://github.com/nodejs/node#release-keys && for key in \ 5BE8A3F6C8A5C01D106C0AD820B1A390B168D356 \ DD792F5973C6DE52C432CBDAC77ABFA00DDBF2B7 \ CC68F5A3106FF448322E48ED27F5E38D5B0A215F \ 8FCCA13FEF1D0C2E91008E09770F7A9A5AE15600 \ 890C08DB8579162FEE0DF9DB8BEAB4DFCF555EF4 \ C82FA3AE1CBEDC6BE46B9360C43CEC45C17AB93C \ 108F52B48DB57BB0CC439B2997B01419BD92F80A \ A363A499291CBBC940DD62E41F10027AF002F8B0 \ ; do \ { gpg --batch --keyserver hkps://keys.openpgp.org --recv-keys "$key" && gpg --batch --fingerprint "$key"; } || \ { gpg --batch --keyserver keyserver.ubuntu.com --recv-keys "$key" && gpg --batch --fingerprint "$key"; } ; \ done \ && curl -fsSLO --compressed "https://nodejs.org/dist/v$NODE_VERSION/node-v$NODE_VERSION-linux-$ARCH.tar.xz" \ && curl -fsSLO --compressed "https://nodejs.org/dist/v$NODE_VERSION/SHASUMS256.txt.asc" \ && gpg --batch --decrypt --output SHASUMS256.txt SHASUMS256.txt.asc \ && gpgconf --kill all \ && rm -rf "$GNUPGHOME" \ && grep " node-v$NODE_VERSION-linux-$ARCH.tar.xz\$" SHASUMS256.txt | sha256sum -c - \ && tar -xJf "node-v$NODE_VERSION-linux-$ARCH.tar.xz" -C /usr/local --strip-components=1 --no-same-owner \ && rm "node-v$NODE_VERSION-linux-$ARCH.tar.xz" SHASUMS256.txt.asc SHASUMS256.txt \ # Remove unused OpenSSL headers to save ~34MB. See this NodeJS issue: https://github.com/nodejs/node/issues/46451 && find /usr/local/include/node/openssl/archs -mindepth 1 -maxdepth 1 ! -name "$OPENSSL_ARCH" -exec rm -rf {} \; \ && apt-mark auto '.*' > /dev/null \ && find /usr/local -type f -executable -exec ldd '{}' ';' \ | awk '/=>/ { so = $(NF-1); if (index(so, "/usr/local/") == 1) { next }; gsub("^/(usr/)?", "", so); print so }' \ | sort -u \ | xargs -r dpkg-query --search \ | cut -d: -f1 \ | sort -u \ | xargs -r apt-mark manual \ && apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false \ && ln -s /usr/local/bin/node /usr/local/bin/nodejs \ # smoke tests && node --version \ && npm --version \ && rm -rf /tmp/* ENV YARN_VERSION=1.22.22 RUN set -ex \ && savedAptMark="$(apt-mark showmanual)" \ && apt-get update && apt-get install -y ca-certificates curl wget gnupg dirmngr --no-install-recommends \ && rm -rf /var/lib/apt/lists/* \ # use pre-existing gpg directory, see https://github.com/nodejs/docker-node/pull/1895#issuecomment-1550389150 && export GNUPGHOME="$(mktemp -d)" \ && for key in \ 6A010C5166006599AA17F08146C2130DFD2497F5 \ ; do \ { gpg --batch --keyserver hkps://keys.openpgp.org --recv-keys "$key" && gpg --batch --fingerprint "$key"; } || \ { gpg --batch --keyserver keyserver.ubuntu.com --recv-keys "$key" && gpg --batch --fingerprint "$key"; } ; \ done \ && curl -fsSLO --compressed "https://yarnpkg.com/downloads/$YARN_VERSION/yarn-v$YARN_VERSION.tar.gz" \ && curl -fsSLO --compressed "https://yarnpkg.com/downloads/$YARN_VERSION/yarn-v$YARN_VERSION.tar.gz.asc" \ && gpg --batch --verify yarn-v$YARN_VERSION.tar.gz.asc yarn-v$YARN_VERSION.tar.gz \ && gpgconf --kill all \ && rm -rf "$GNUPGHOME" \ && mkdir -p /opt \ && tar -xzf yarn-v$YARN_VERSION.tar.gz -C /opt/ \ && ln -s /opt/yarn-v$YARN_VERSION/bin/yarn /usr/local/bin/yarn \ && ln -s /opt/yarn-v$YARN_VERSION/bin/yarnpkg /usr/local/bin/yarnpkg \ && rm yarn-v$YARN_VERSION.tar.gz.asc yarn-v$YARN_VERSION.tar.gz \ && apt-mark auto '.*' > /dev/null \ && { [ -z "$savedAptMark" ] || apt-mark manual $savedAptMark > /dev/null; } \ && find /usr/local -type f -executable -exec ldd '{}' ';' \ | awk '/=>/ { so = $(NF-1); if (index(so, "/usr/local/") == 1) { next }; gsub("^/(usr/)?", "", so); print so }' \ | sort -u \ | xargs -r dpkg-query --search \ | cut -d: -f1 \ | sort -u \ | xargs -r apt-mark manual \ && apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false \ # smoke test && yarn --version \ && rm -rf /tmp/* COPY docker-entrypoint.sh /usr/local/bin/ ENTRYPOINT ["docker-entrypoint.sh"] CMD [ "node" ] ================================================ FILE: 25/trixie-slim/docker-entrypoint.sh ================================================ #!/bin/sh set -e # Run command with node if the first argument contains a "-" or is not a system command. The last # part inside the "{}" is a workaround for the following bug in ash/dash: # https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=874264 if [ "${1#-}" != "${1}" ] || [ -z "$(command -v "${1}")" ] || { [ -f "${1}" ] && ! [ -x "${1}" ]; }; then set -- node "$@" fi exec "$@" ================================================ FILE: CONTRIBUTING.md ================================================ # Contributing to docker-node Thank you for your contribution. Here are a set of guidelines for contributing to the docker-node project. ## Governance and decision making Project governance uses consensus seeking. See [GOVERNANCE.md](./GOVERNANCE.md) for roles and the decision process. For governance-sensitive or potentially contentious changes, open a PR (or issue) with rationale and allow time for async feedback. If a final decision cannot be reached via consensus seeking, escalation goes to the Node.js TSC as final arbiter. ## Discussion Areas You can use Node.js channels (prefixed by `#nodejs-`) in the [OpenJSF Slack](https://slack-invite.openjsf.org/) workspace for discussions. - [#nodejs-distributions](https://openjs-foundation.slack.com/archives/C0ALS3UDE8G) covers discussions for this repo (`docker-node`). - [#nodejs-release](https://openjs-foundation.slack.com/archives/C019MGJQ8RH) is linked to the [Node.js Release Working Group](https://github.com/nodejs/release#readme) responsible for the upstream releases of Node.js used by this repo. ## Version Updates New **Node.js** releases are released as soon as possible. New **npm** releases are not tracked. We simply use the npm version bundled in the corresponding Node.js release. **[Yarn v1 Classic](https://classic.yarnpkg.com/)** is no longer maintained upstream, and will be removed starting with the Node 26 images. ### Submitting a PR for a version update If you'd like to help us by submitting a PR for a version update, please do the following: 1. [Fork this project.](https://docs.github.com/en/get-started/quickstart/fork-a-repo) 1. [Clone the forked repository.](https://docs.github.com/en/github/creating-cloning-and-archiving-repositories/cloning-a-repository) 1. Create a branch for the update PR. For example, `git checkout main; git checkout -b version-update`. 1. Run `./update.sh`. You can see additional options by using accessing the built-in help documentation with `./update.sh -h`. This script will automatically update the appropriate files with the latest versions and checksums. 1. Commit the modified files to the `version-update` branch and push the branch to your fork. 1. [Create a PR to merge the branch from your fork into this project's default branch.](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/creating-a-pull-request-from-a-fork). ## Adding dependencies to the base images NodeJS is a big ecosystem with a variety of different use cases. The docker images for node are designed to provide the minimum for running core node. Additional dependencies (including dependencies for npm or yarn such as git) will not be included in these base images and will need to be included in descendent image. ================================================ FILE: Dockerfile-alpine.template ================================================ FROM alpine:0.0 ENV NODE_VERSION=0.0.0 RUN addgroup -g 1000 node \ && adduser -u 1000 -G node -s /bin/sh -D node \ && apk add --no-cache \ libstdc++ \ && apk add --no-cache --virtual .build-deps \ curl \ && ARCH= OPENSSL_ARCH='linux*' && alpineArch="$(apk --print-arch)" \ && case "${alpineArch##*-}" in \ x86_64) ARCH='x64' CHECKSUM=CHECKSUM_x64 OPENSSL_ARCH=linux-x86_64;; \ x86) OPENSSL_ARCH=linux-elf;; \ aarch64) OPENSSL_ARCH=linux-aarch64;; \ arm*) OPENSSL_ARCH=linux-armv4;; \ ppc64le) OPENSSL_ARCH=linux-ppc64le;; \ s390x) OPENSSL_ARCH=linux-s390x;; \ *) ;; \ esac \ && if [ -n "${CHECKSUM}" ]; then \ set -eu; \ curl -fsSLO --compressed "https://unofficial-builds.nodejs.org/download/release/v$NODE_VERSION/node-v$NODE_VERSION-linux-$ARCH-musl.tar.xz"; \ echo "$CHECKSUM node-v$NODE_VERSION-linux-$ARCH-musl.tar.xz" | sha256sum -c - \ && tar -xJf "node-v$NODE_VERSION-linux-$ARCH-musl.tar.xz" -C /usr/local --strip-components=1 --no-same-owner \ && ln -s /usr/local/bin/node /usr/local/bin/nodejs; \ else \ echo "Building from source" \ # backup build && apk add --no-cache --virtual .build-deps-full \ binutils-gold \ g++ \ gcc \ gnupg \ libgcc \ linux-headers \ make \ python3 \ py-setuptools \ # use pre-existing gpg directory, see https://github.com/nodejs/docker-node/pull/1895#issuecomment-1550389150 && export GNUPGHOME="$(mktemp -d)" \ # gpg keys listed at https://github.com/nodejs/node#release-keys && for key in \ "${NODE_KEYS[@]}" ; do \ { gpg --batch --keyserver hkps://keys.openpgp.org --recv-keys "$key" && gpg --batch --fingerprint "$key"; } || \ { gpg --batch --keyserver keyserver.ubuntu.com --recv-keys "$key" && gpg --batch --fingerprint "$key"; } ; \ done \ && curl -fsSLO --compressed "https://nodejs.org/dist/v$NODE_VERSION/node-v$NODE_VERSION.tar.xz" \ && curl -fsSLO --compressed "https://nodejs.org/dist/v$NODE_VERSION/SHASUMS256.txt.asc" \ && gpg --batch --decrypt --output SHASUMS256.txt SHASUMS256.txt.asc \ && gpgconf --kill all \ && rm -rf "$GNUPGHOME" \ && grep " node-v$NODE_VERSION.tar.xz\$" SHASUMS256.txt | sha256sum -c - \ && tar -xf "node-v$NODE_VERSION.tar.xz" \ && cd "node-v$NODE_VERSION" \ && ./configure \ && make -j$(getconf _NPROCESSORS_ONLN) V= \ && make install \ && apk del .build-deps-full \ && cd .. \ && rm -Rf "node-v$NODE_VERSION" \ && rm "node-v$NODE_VERSION.tar.xz" SHASUMS256.txt.asc SHASUMS256.txt; \ fi \ && rm -f "node-v$NODE_VERSION-linux-$ARCH-musl.tar.xz" \ # Remove unused OpenSSL headers to save ~34MB. See this NodeJS issue: https://github.com/nodejs/node/issues/46451 && find /usr/local/include/node/openssl/archs -mindepth 1 -maxdepth 1 ! -name "$OPENSSL_ARCH" -exec rm -rf {} \; \ && apk del .build-deps \ # smoke tests && node --version \ && npm --version \ && rm -rf /tmp/* ENV YARN_VERSION=1.22.22 RUN apk add --no-cache --virtual .build-deps-yarn curl gnupg tar \ # use pre-existing gpg directory, see https://github.com/nodejs/docker-node/pull/1895#issuecomment-1550389150 && export GNUPGHOME="$(mktemp -d)" \ && for key in \ 6A010C5166006599AA17F08146C2130DFD2497F5 \ ; do \ { gpg --batch --keyserver hkps://keys.openpgp.org --recv-keys "$key" && gpg --batch --fingerprint "$key"; } || \ { gpg --batch --keyserver keyserver.ubuntu.com --recv-keys "$key" && gpg --batch --fingerprint "$key"; } ; \ done \ && curl -fsSLO --compressed "https://yarnpkg.com/downloads/$YARN_VERSION/yarn-v$YARN_VERSION.tar.gz" \ && curl -fsSLO --compressed "https://yarnpkg.com/downloads/$YARN_VERSION/yarn-v$YARN_VERSION.tar.gz.asc" \ && gpg --batch --verify yarn-v$YARN_VERSION.tar.gz.asc yarn-v$YARN_VERSION.tar.gz \ && gpgconf --kill all \ && rm -rf "$GNUPGHOME" \ && mkdir -p /opt \ && tar -xzf yarn-v$YARN_VERSION.tar.gz -C /opt/ \ && ln -s /opt/yarn-v$YARN_VERSION/bin/yarn /usr/local/bin/yarn \ && ln -s /opt/yarn-v$YARN_VERSION/bin/yarnpkg /usr/local/bin/yarnpkg \ && rm yarn-v$YARN_VERSION.tar.gz.asc yarn-v$YARN_VERSION.tar.gz \ && apk del .build-deps-yarn \ # smoke test && yarn --version \ && rm -rf /tmp/* COPY docker-entrypoint.sh /usr/local/bin/ ENTRYPOINT ["docker-entrypoint.sh"] CMD [ "node" ] ================================================ FILE: Dockerfile-debian.template ================================================ FROM buildpack-deps:name RUN groupadd --gid 1000 node \ && useradd --uid 1000 --gid node --shell /bin/bash --create-home node ENV NODE_VERSION=0.0.0 RUN ARCH= && dpkgArch="$(dpkg --print-architecture)" \ && case "${dpkgArch##*-}" in \ amd64) ARCH='x64';; \ ppc64el) ARCH='ppc64le';; \ s390x) ARCH='s390x';; \ arm64) ARCH='arm64';; \ armhf) ARCH='armv7l';; \ i386) ARCH='x86';; \ *) echo "unsupported architecture"; exit 1 ;; \ esac \ # use pre-existing gpg directory, see https://github.com/nodejs/docker-node/pull/1895#issuecomment-1550389150 && export GNUPGHOME="$(mktemp -d)" \ # gpg keys listed at https://github.com/nodejs/node#release-keys && set -ex \ && for key in \ "${NODE_KEYS[@]}" ; do \ { gpg --batch --keyserver hkps://keys.openpgp.org --recv-keys "$key" && gpg --batch --fingerprint "$key"; } || \ { gpg --batch --keyserver keyserver.ubuntu.com --recv-keys "$key" && gpg --batch --fingerprint "$key"; } ; \ done \ && curl -fsSLO --compressed "https://nodejs.org/dist/v$NODE_VERSION/node-v$NODE_VERSION-linux-$ARCH.tar.xz" \ && curl -fsSLO --compressed "https://nodejs.org/dist/v$NODE_VERSION/SHASUMS256.txt.asc" \ && gpg --batch --decrypt --output SHASUMS256.txt SHASUMS256.txt.asc \ && gpgconf --kill all \ && rm -rf "$GNUPGHOME" \ && grep " node-v$NODE_VERSION-linux-$ARCH.tar.xz\$" SHASUMS256.txt | sha256sum -c - \ && tar -xJf "node-v$NODE_VERSION-linux-$ARCH.tar.xz" -C /usr/local --strip-components=1 --no-same-owner \ && rm "node-v$NODE_VERSION-linux-$ARCH.tar.xz" SHASUMS256.txt.asc SHASUMS256.txt \ && ln -s /usr/local/bin/node /usr/local/bin/nodejs \ # smoke tests && node --version \ && npm --version \ && rm -rf /tmp/* ENV YARN_VERSION=1.22.22 RUN set -ex \ # use pre-existing gpg directory, see https://github.com/nodejs/docker-node/pull/1895#issuecomment-1550389150 && export GNUPGHOME="$(mktemp -d)" \ && for key in \ 6A010C5166006599AA17F08146C2130DFD2497F5 \ ; do \ { gpg --batch --keyserver hkps://keys.openpgp.org --recv-keys "$key" && gpg --batch --fingerprint "$key"; } || \ { gpg --batch --keyserver keyserver.ubuntu.com --recv-keys "$key" && gpg --batch --fingerprint "$key"; } ; \ done \ && curl -fsSLO --compressed "https://yarnpkg.com/downloads/$YARN_VERSION/yarn-v$YARN_VERSION.tar.gz" \ && curl -fsSLO --compressed "https://yarnpkg.com/downloads/$YARN_VERSION/yarn-v$YARN_VERSION.tar.gz.asc" \ && gpg --batch --verify yarn-v$YARN_VERSION.tar.gz.asc yarn-v$YARN_VERSION.tar.gz \ && gpgconf --kill all \ && rm -rf "$GNUPGHOME" \ && mkdir -p /opt \ && tar -xzf yarn-v$YARN_VERSION.tar.gz -C /opt/ \ && ln -s /opt/yarn-v$YARN_VERSION/bin/yarn /usr/local/bin/yarn \ && ln -s /opt/yarn-v$YARN_VERSION/bin/yarnpkg /usr/local/bin/yarnpkg \ && rm yarn-v$YARN_VERSION.tar.gz.asc yarn-v$YARN_VERSION.tar.gz \ # smoke test && yarn --version \ && rm -rf /tmp/* COPY docker-entrypoint.sh /usr/local/bin/ ENTRYPOINT ["docker-entrypoint.sh"] CMD [ "node" ] ================================================ FILE: Dockerfile-slim.template ================================================ FROM debian:name-slim RUN groupadd --gid 1000 node \ && useradd --uid 1000 --gid node --shell /bin/bash --create-home node ENV NODE_VERSION=0.0.0 RUN ARCH= OPENSSL_ARCH= && dpkgArch="$(dpkg --print-architecture)" \ && case "${dpkgArch##*-}" in \ amd64) ARCH='x64' OPENSSL_ARCH='linux-x86_64';; \ ppc64el) ARCH='ppc64le' OPENSSL_ARCH='linux-ppc64le';; \ s390x) ARCH='s390x' OPENSSL_ARCH='linux*-s390x';; \ arm64) ARCH='arm64' OPENSSL_ARCH='linux-aarch64';; \ armhf) ARCH='armv7l' OPENSSL_ARCH='linux-armv4';; \ i386) ARCH='x86' OPENSSL_ARCH='linux-elf';; \ *) echo "unsupported architecture"; exit 1 ;; \ esac \ && set -ex \ # libatomic1 for arm && apt-get update && apt-get install -y ca-certificates curl wget gnupg dirmngr xz-utils libatomic1 --no-install-recommends \ && rm -rf /var/lib/apt/lists/* \ # use pre-existing gpg directory, see https://github.com/nodejs/docker-node/pull/1895#issuecomment-1550389150 && export GNUPGHOME="$(mktemp -d)" \ # gpg keys listed at https://github.com/nodejs/node#release-keys && for key in \ "${NODE_KEYS[@]}" ; do \ { gpg --batch --keyserver hkps://keys.openpgp.org --recv-keys "$key" && gpg --batch --fingerprint "$key"; } || \ { gpg --batch --keyserver keyserver.ubuntu.com --recv-keys "$key" && gpg --batch --fingerprint "$key"; } ; \ done \ && curl -fsSLO --compressed "https://nodejs.org/dist/v$NODE_VERSION/node-v$NODE_VERSION-linux-$ARCH.tar.xz" \ && curl -fsSLO --compressed "https://nodejs.org/dist/v$NODE_VERSION/SHASUMS256.txt.asc" \ && gpg --batch --decrypt --output SHASUMS256.txt SHASUMS256.txt.asc \ && gpgconf --kill all \ && rm -rf "$GNUPGHOME" \ && grep " node-v$NODE_VERSION-linux-$ARCH.tar.xz\$" SHASUMS256.txt | sha256sum -c - \ && tar -xJf "node-v$NODE_VERSION-linux-$ARCH.tar.xz" -C /usr/local --strip-components=1 --no-same-owner \ && rm "node-v$NODE_VERSION-linux-$ARCH.tar.xz" SHASUMS256.txt.asc SHASUMS256.txt \ # Remove unused OpenSSL headers to save ~34MB. See this NodeJS issue: https://github.com/nodejs/node/issues/46451 && find /usr/local/include/node/openssl/archs -mindepth 1 -maxdepth 1 ! -name "$OPENSSL_ARCH" -exec rm -rf {} \; \ && apt-mark auto '.*' > /dev/null \ && find /usr/local -type f -executable -exec ldd '{}' ';' \ | awk '/=>/ { so = $(NF-1); if (index(so, "/usr/local/") == 1) { next }; gsub("^/(usr/)?", "", so); print so }' \ | sort -u \ | xargs -r dpkg-query --search \ | cut -d: -f1 \ | sort -u \ | xargs -r apt-mark manual \ && apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false \ && ln -s /usr/local/bin/node /usr/local/bin/nodejs \ # smoke tests && node --version \ && npm --version \ && rm -rf /tmp/* ENV YARN_VERSION=1.22.22 RUN set -ex \ && savedAptMark="$(apt-mark showmanual)" \ && apt-get update && apt-get install -y ca-certificates curl wget gnupg dirmngr --no-install-recommends \ && rm -rf /var/lib/apt/lists/* \ # use pre-existing gpg directory, see https://github.com/nodejs/docker-node/pull/1895#issuecomment-1550389150 && export GNUPGHOME="$(mktemp -d)" \ && for key in \ 6A010C5166006599AA17F08146C2130DFD2497F5 \ ; do \ { gpg --batch --keyserver hkps://keys.openpgp.org --recv-keys "$key" && gpg --batch --fingerprint "$key"; } || \ { gpg --batch --keyserver keyserver.ubuntu.com --recv-keys "$key" && gpg --batch --fingerprint "$key"; } ; \ done \ && curl -fsSLO --compressed "https://yarnpkg.com/downloads/$YARN_VERSION/yarn-v$YARN_VERSION.tar.gz" \ && curl -fsSLO --compressed "https://yarnpkg.com/downloads/$YARN_VERSION/yarn-v$YARN_VERSION.tar.gz.asc" \ && gpg --batch --verify yarn-v$YARN_VERSION.tar.gz.asc yarn-v$YARN_VERSION.tar.gz \ && gpgconf --kill all \ && rm -rf "$GNUPGHOME" \ && mkdir -p /opt \ && tar -xzf yarn-v$YARN_VERSION.tar.gz -C /opt/ \ && ln -s /opt/yarn-v$YARN_VERSION/bin/yarn /usr/local/bin/yarn \ && ln -s /opt/yarn-v$YARN_VERSION/bin/yarnpkg /usr/local/bin/yarnpkg \ && rm yarn-v$YARN_VERSION.tar.gz.asc yarn-v$YARN_VERSION.tar.gz \ && apt-mark auto '.*' > /dev/null \ && { [ -z "$savedAptMark" ] || apt-mark manual $savedAptMark > /dev/null; } \ && find /usr/local -type f -executable -exec ldd '{}' ';' \ | awk '/=>/ { so = $(NF-1); if (index(so, "/usr/local/") == 1) { next }; gsub("^/(usr/)?", "", so); print so }' \ | sort -u \ | xargs -r dpkg-query --search \ | cut -d: -f1 \ | sort -u \ | xargs -r apt-mark manual \ && apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false \ # smoke test && yarn --version \ && rm -rf /tmp/* COPY docker-entrypoint.sh /usr/local/bin/ ENTRYPOINT ["docker-entrypoint.sh"] CMD [ "node" ] ================================================ FILE: GOVERNANCE.md ================================================ # Governance The Node.js Docker image project is governed using an **open maintainer model**. This repository is no longer operated as a Node.js TSC-chartered working group. Instead, project decisions are made by maintainers in public, in this repository. ## Guiding principles - Default to public discussion in issues and pull requests. - Use [Consensus Seeking](https://en.wikipedia.org/wiki/Consensus_decision-making) for decision making. - Keep decision records in-repo so contributors can follow context. - Keep a clear path from contributor → collaborator → maintainer. ## Roles ### Contributors Anyone who proposes changes, reports issues, reviews code, or helps users. ### Collaborators Collaborators have write access and help with day-to-day maintenance: - review and merge pull requests - triage issues - help drive technical direction Collaborators are nominated by maintainers via pull request and added after consensus. ### Maintainers Maintainers are responsible for long-term stewardship of the project: - facilitate consensus and escalate unresolved final decisions to the Node.js TSC - governance and membership updates - release/publishing policy and automation oversight - security and incident handling for this repository Current maintainers: - Laurent Goderre ([LaurentGoderre](https://github.com/LaurentGoderre)) - Simen Bekkhus ([SimenB](https://github.com/SimenB)) - Peter Dave Hello ([PeterDaveHello](https://github.com/PeterDaveHello)) - Rafael Gonzaga ([rafaelgss](https://github.com/rafaelgss)) - Matteo Collina ([mcollina](https://github.com/mcollina)) ## Decision making ### Standard changes (code/docs/automation) - Pull requests are discussed in public. - A PR from a non-collaborator can be merged by one collaborator. - A PR from a collaborator should be approved by another collaborator before merge. ### Maintainer-level decisions For governance, membership, major policy, or contentious technical changes: 1. Open an issue or PR describing the decision and proposed outcome. 2. Allow time for async feedback (normally at least 5 days). 3. If no unresolved objections remain, a maintainer may merge/close with a summary. If a final decision cannot be made using Consensus Seeking, the issue should be escalated to the Node.js TSC (for example by requesting `tsc-agenda`). In that case, the Node.js TSC is the final arbiter, consistent with the [TSC Charter](https://github.com/nodejs/TSC/blob/main/TSC-Charter.md). ## Meetings The project primarily operates asynchronously in GitHub issues and pull requests. If maintainers hold synchronous meetings, outcomes should be posted publicly in this repository. ## Membership changes Collaborator and maintainer changes are proposed via pull request to `README.md` and/or this file, with rationale included in the PR description. Project access should be managed via the [@nodejs/docker team](https://github.com/orgs/nodejs/teams/docker) and kept in sync with Node.js collaborator tooling. Maintainers can also move inactive members to emeritus status through the same public process. ## Developer's Certificate of Origin 1.1 By making a contribution to this project, I certify that: - (a) The contribution was created in whole or in part by me and I have the right to submit it under the open source license indicated in the file; or - (b) The contribution is based upon previous work that, to the best of my knowledge, is covered under an appropriate open source license and I have the right under that license to submit that work with modifications, whether created wholly or in part by me, under the same open source license (unless I am permitted to submit under a different license), as indicated in the file; or - (c) The contribution was provided directly to me by some other person who certified (a), (b), or (c) and I have not modified it. - (d) I understand and agree that this project and the contribution are public and that a record of the contribution (including all personal information I submit with it, including my sign-off) is maintained indefinitely and may be redistributed consistent with this project or the open source license(s) involved. ## Code of Conduct The Node.js Code of Conduct applies to this project: . ================================================ FILE: LICENSE ================================================ The MIT License (MIT) Copyright (c) 2015 Joyent, Inc. Copyright (c) 2015 Node.js contributors Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================ FILE: README.md ================================================ # Node.js [**node - Docker Official Images on Docker Hub**](https://hub.docker.com/_/node) [![GitHub issues](https://img.shields.io/github/issues/nodejs/docker-node.svg "GitHub issues")](https://github.com/nodejs/docker-node) [![GitHub stars](https://img.shields.io/github/stars/nodejs/docker-node.svg "GitHub stars")](https://github.com/nodejs/docker-node) The official Node.js docker image, made with love by the node community. ## Table of Contents - [What is Node.js?](#what-is-nodejs) - [How to use this image](#how-to-use-this-image) - [Create a `Dockerfile` in your Node.js app project](#create-a-dockerfile-in-your-nodejs-app-project) - [Best Practices](#best-practices) - [Run a single Node.js script](#run-a-single-nodejs-script) - [Verbosity](#verbosity) - [Dockerfile](#dockerfile) - [Docker Run](#docker-run) - [npm run](#npm-run) - [Image Variants](#image-variants) - [`node:`](#nodeversion) - [`node:alpine`](#nodealpine) - [`node:bullseye`](#nodebullseye) - [`node:bookworm`](#nodebookworm) - [`node:trixie`](#nodetrixie) - [`node:slim`](#nodeslim) - [License](#license) - [Supported Docker versions](#supported-docker-versions) - [Supported Node.js versions](#supported-nodejs-versions) - [Yarn v1 Classic bundling](#yarn-v1-classic-bundling) - [Governance and Current Members](#governance-and-current-members) - [Docker Maintainers](#docker-maintainers) - [Collaborators](#collaborators) - [Emeritus](#emeritus) - [Former Maintainers](#former-maintainers) ## What is Node.js? Node.js is a platform built on Chrome's JavaScript runtime for easily building fast, scalable network applications. Node.js uses an event-driven, non-blocking I/O model that makes it lightweight and efficient, perfect for data-intensive real-time applications that run across distributed devices. See: https://nodejs.org ## How to use this image ### Create a `Dockerfile` in your Node.js app project ```dockerfile # specify the node base image with your desired version node: FROM node:24 # replace this with your application's default port EXPOSE 8888 ``` You can then build and run the Docker image: ```console $ docker build -t my-nodejs-app . $ docker run -it --rm --name my-running-app my-nodejs-app ``` If you prefer Docker Compose: ```yml services: node: image: "node:24" user: "node" working_dir: /home/node/app environment: - NODE_ENV=production volumes: - ./:/home/node/app ports: # use if it is necessary to expose the container to the host machine - "8888:8888" command: ["npm", "start"] ``` You can then run using Docker Compose: ```console $ docker-compose up -d ``` Docker Compose example mounts your current directory (including node_modules) to the container. It assumes that your application has a file named [`package.json`](https://docs.npmjs.com/files/package.json) defining [start script](https://docs.npmjs.com/misc/scripts#default-values). ### Best Practices We have assembled a [Best Practices Guide](./docs/BestPractices.md) for those using these images on a daily basis. ### Run a single Node.js script For many simple, single file projects, you may find it inconvenient to write a complete `Dockerfile`. In such cases, you can run a Node.js script by using the Node.js Docker image directly: ```console $ docker run -it --rm --name my-running-script -v "$PWD":/usr/src/app -w /usr/src/app node:24 node your-daemon-or-script.js ``` ### Verbosity Prior to 8.7.0 and 6.11.4, the docker images overrode the default npm log level from `warn` to `info`. However, due to improvements to npm and new Docker patterns (e.g. multi-stage builds) the working group reached a [consensus](https://github.com/nodejs/docker-node/issues/528) to revert the log level to npm defaults. If you need more verbose output, please use one of the following methods to change the verbosity level. #### Dockerfile If you create your own `Dockerfile` which inherits from the `node` image, you can simply use `ENV` to override `NPM_CONFIG_LOGLEVEL`. ```dockerfile FROM node ENV NPM_CONFIG_LOGLEVEL=info ... ``` #### Docker Run If you run the node image using `docker run`, you can use the `-e` flag to override `NPM_CONFIG_LOGLEVEL`. ```console $ docker run -e NPM_CONFIG_LOGLEVEL=info node ... ``` #### npm run If you are running npm commands, you can use `--loglevel` to control the verbosity of the output. ```console $ docker run node npm --loglevel=warn ... ``` ## Image Variants The `node` images come in many flavors, each designed for a specific use case. All of the images contain pre-installed versions of `node`, [`npm`](https://www.npmjs.com/), and [Yarn v1 Classic](https://classic.yarnpkg.com/). For each supported architecture, the supported variants are different. In the file: [versions.json](./versions.json), it lists all supported variants for all of the architectures that we support now. See [Yarn v1 Classic bundling](#yarn-v1-classic-bundling) for future plans to remove this legacy version. ### `node:` This is the defacto image. If you are unsure about what your needs are, you probably want to use this one. It is designed to be used both as a throw away container (mount your source code and start the container to start your app), as well as the base to build other images off of. This tag is based off of [`buildpack-deps`](https://registry.hub.docker.com/_/buildpack-deps/). `buildpack-deps` is designed for the average user of docker who has many images on their system. It, by design, has a large number of extremely common Debian packages. This reduces the number of packages that images that derive from it need to install, thus reducing the overall size of all images on your system. ### `node:alpine` This image is based on the popular [Alpine Linux project](https://alpinelinux.org), available in [the `alpine` official image](https://hub.docker.com/_/alpine). Alpine Linux is much smaller than most distribution base images (~5MB), and thus leads to much slimmer images in general. This variant is highly recommended when final image size being as small as possible is desired. The main caveat to note is that it does use [musl libc](https://musl.libc.org/) instead of [glibc and friends](https://www.etalabs.net/compare_libcs.html), so certain software might run into issues depending on the depth of their libc requirements. However, most software doesn't have an issue with this, so this variant is usually a very safe choice. See [this Hacker News comment thread](https://news.ycombinator.com/item?id=10782897) for more discussion of the issues that might arise and some pro/con comparisons of using Alpine-based images. One common issue that may arise is a missing shared library required for use of `process.dlopen`. To add the missing shared libraries to your image: - For Alpine v3.18 and earlier, adding the [`libc6-compat`](https://pkgs.alpinelinux.org/package/v3.18/main/x86/libc6-compat) package in your Dockerfile is recommended: `apk add --no-cache libc6-compat` - Starting from Alpine v3.19, you can use the [`gcompat`](https://pkgs.alpinelinux.org/package/v3.19/main/x86/gcompat) package to add the missing shared libraries: `apk add --no-cache gcompat` To minimize image size, it's uncommon for additional related tools (such as `git` or `bash`) to be included in Alpine-based images. Using this image as a base, add the things you need in your own Dockerfile (see the [`alpine` image description](https://hub.docker.com/_/alpine/) for examples of how to install packages if you are unfamiliar). To make the image size even smaller, you can [bundle without npm/yarn](./docs/BestPractices.md#smaller-images-without-npmyarn). ### `node:bullseye` This image is based on version 11 of [Debian](https://debian.org), available in [the `debian` official image](https://hub.docker.com/_/debian). ### `node:bookworm` This image is based on version 12 of [Debian](https://debian.org), available in [the `debian` official image](https://hub.docker.com/_/debian). ### `node:trixie` This image is based on version 13 of [Debian](https://debian.org), available in [the `debian` official image](https://hub.docker.com/_/debian). ### `node:slim` This image does not contain the common packages contained in the default tag and only contains the minimal packages needed to run `node`. Unless you are working in an environment where *only* the Node.js image will be deployed and you have space constraints, we highly recommend using the default image of this repository. ## License [License information](https://github.com/nodejs/node/blob/main/LICENSE) for the software contained in this image. [License information](LICENSE) for the Node.js Docker project. ## Supported Docker versions If you are using [Docker Desktop](https://docs.docker.com/get-started/get-docker/), it is recommended to use a recent version, released in the last six months. Refer to [Docker Engine release notes](https://docs.docker.com/engine/release-notes/) for current Engine versions. ## Supported Node.js versions This project will support Node.js versions as still under active support as per the [Node.js release schedule](https://github.com/nodejs/Release). ## Yarn v1 Classic bundling [Yarn v1 Classic](https://classic.yarnpkg.com/) is currently bundled in `node` image variants. Because Yarn v1 is [frozen](https://github.com/yarnpkg/yarn) and no longer maintained, bundling plans have been revised. As of Node.js 26.0.0 it is planned to no longer bundle Yarn v1 into `node` images. For lower versions of Node.js (<26) `node` images will continue to bundle Yarn v1. Users with legacy requirements for Yarn v1 under Node.js 26 and above may be able to follow [Yarn v1 installation instructions](https://classic.yarnpkg.com/en/docs/install) and install using `npm install --global yarn`. ## Governance and Current Members The Node.js Docker Image is governed by an open maintainer model. See [GOVERNANCE.md](GOVERNANCE.md) for project roles and decision-making, and [CONTRIBUTING.md](CONTRIBUTING.md) for contribution guidance. If a final decision cannot be reached using consensus seeking, the Node.js TSC is the final arbiter. ### Docker Maintainers - Laurent Goderre ([LaurentGoderre](https://github.com/LaurentGoderre)) - Simen Bekkhus ([SimenB](https://github.com/SimenB)) - Peter Dave Hello ([PeterDaveHello](https://github.com/PeterDaveHello)) - Rafael Gonzaga ([rafaelgss](https://github.com/rafaelgss)) - Matteo Collina ([mcollina](https://github.com/mcollina)) ### Collaborators Additional collaborators are managed via the [@nodejs/docker team](https://github.com/orgs/nodejs/teams/docker). ### Emeritus #### Former Maintainers - Mikeal Rogers ([mikeal](https://github.com/mikeal)) - Christopher Horrell ([chorrell](https://github.com/chorrell)) - Peter Petrov ([pesho](https://github.com/pesho)) - John Mitchell ([jlmitch5](https://github.com/jlmitch5)) ================================================ FILE: SECURITY.md ================================================ # Security Policy ## Reporting a Vulnerability This repo builds releases of Node.js unchanged into Docker images. Node.js itself bundles certain packages as described in the [distribution](https://github.com/nodejs/node/blob/main/doc/contributing/distribution.md) document. This includes also the npm package manager. Common Vulnerabilities and Exposures (CVE) reports that relate to Node.js or its packaged dependencies cannot be addressed in this repo. Security issues relating to the Node.js project should follow the process documented on where it is also advised that vulnerabilities in third-party packages should be reported to their respective owners. CVEs for the base operating system image packages should be reported to those repositories. Nothing to address those CVEs is in the hands of this repo. - [Alpine](https://github.com/alpinelinux/docker-alpine) - [Debian (bullseye, bookworm, trixie)](https://github.com/debuerreotype/docker-debian-artifacts) When base images are patched, the images are rebuilt and rolled out to the Docker hub without intervention by this repo. This process is explained in . When vulnerabilities are resolved in a Node.js release, they are routinely released in a corresponding new Node.js Docker image. The schedule is determined by the Node.js releases not by the Node.js Docker repo. Please do not open issues in this repo for vulnerabilities in the above components. If they cannot be actioned here, the issue will be closed. ================================================ FILE: architectures ================================================ bashbrew-arch variants amd64 alpine3.22,alpine3.23,bookworm,bookworm-slim,bullseye,bullseye-slim,trixie,trixie-slim arm32v6 alpine3.22,alpine3.23 arm32v7 alpine3.22,alpine3.23,bookworm,bookworm-slim,bullseye,bullseye-slim,trixie,trixie-slim arm64v8 alpine3.22,alpine3.23,bookworm,bookworm-slim,bullseye,bullseye-slim,trixie,trixie-slim i386 alpine3.22,alpine3.23 ppc64le alpine3.22,alpine3.23,bookworm,bookworm-slim,trixie,trixie-slim s390x alpine3.22,alpine3.23,bookworm,bookworm-slim,trixie,trixie-slim ================================================ FILE: build-automation.mjs ================================================ import { promisify } from "util"; import child_process from "child_process"; const exec = promisify(child_process.exec); // a function that queries the Node.js release website for new versions, // compare the available ones with the ones we use in this repo // and returns whether we should update or not const checkIfThereAreNewVersions = async (github) => { try { const { stdout: versionsOutput } = await exec(". ./functions.sh && get_versions", { shell: "bash" }); const supportedVersions = versionsOutput.trim().split(" "); let latestSupportedVersions = {}; for (let supportedVersion of supportedVersions) { const { stdout } = await exec(`ls ${supportedVersion}`); const { stdout: fullVersionOutput } = await exec(`. ./functions.sh && get_full_version ./${supportedVersion}/${stdout.trim().split("\n")[0]}`, { shell: "bash" }); console.log(fullVersionOutput); latestSupportedVersions[supportedVersion] = { fullVersion: fullVersionOutput.trim() }; } const { data: availableVersionsJson } = await github.request('https://nodejs.org/download/release/index.json'); // filter only more recent versions of availableVersionsJson for each major version in latestSupportedVersions' keys // e.g. if latestSupportedVersions = { "12": "12.22.10", "14": "14.19.0", "16": "16.14.0", "17": "17.5.0" } // and availableVersions = ["Node.js 12.22.10", "Node.js 12.24.0", "Node.js 14.19.0", "Node.js 14.22.0", "Node.js 16.14.0", "Node.js 16.16.0", "Node.js 17.5.0", "Node.js 17.8.0"] // return { "12": "12.24.0", "14": "14.22.0", "16": "16.16.0", "17": "17.8.0" } let filteredNewerVersions = {}; for (let availableVersion of availableVersionsJson) { const [availableMajor, availableMinor, availablePatch] = availableVersion.version.split("v")[1].split("."); if (latestSupportedVersions[availableMajor] == null) { continue; } const [_latestMajor, latestMinor, latestPatch] = latestSupportedVersions[availableMajor].fullVersion.split("."); if (latestSupportedVersions[availableMajor] && (Number(availableMinor) > Number(latestMinor) || (availableMinor === latestMinor && Number(availablePatch) > Number(latestPatch)))) { filteredNewerVersions[availableMajor] = { fullVersion: `${availableMajor}.${availableMinor}.${availablePatch}` }; } } return { shouldUpdate: Object.keys(filteredNewerVersions).length > 0 && JSON.stringify(filteredNewerVersions) !== JSON.stringify(latestSupportedVersions), versions: filteredNewerVersions, } } catch (error) { console.error(error); process.exit(1); } }; // a function that queries the Node.js unofficial release website for new musl versions and security releases, // and returns relevant information const checkForMuslVersionsAndSecurityReleases = async (github, versions) => { try { const { data: unofficialBuildsIndexText } = await github.request('https://unofficial-builds.nodejs.org/download/release/index.json'); for (let version of Object.keys(versions)) { const buildVersion = unofficialBuildsIndexText.find(indexVersion => indexVersion.version === `v${versions[version].fullVersion}`); versions[version].muslBuildExists = buildVersion?.files.includes("linux-x64-musl") ?? false; versions[version].isSecurityRelease = buildVersion?.security ?? false; } return versions; } catch (error) { console.error(error); process.exit(1); } }; export default async function(github) { // if there are no new versions, exit gracefully // if there are new versions, // check for musl builds // then run update.sh const { shouldUpdate, versions } = await checkIfThereAreNewVersions(github); if (!shouldUpdate) { console.log("No new versions found. No update required."); process.exit(0); } else { const newVersions = await checkForMuslVersionsAndSecurityReleases(github, versions); let updatedVersions = []; for (const [version, newVersion] of Object.entries(newVersions)) { if (newVersion.muslBuildExists) { const { stdout } = await exec(`./update.sh ${newVersion.isSecurityRelease ? "-s " : ""}${version}`); console.log(stdout); updatedVersions.push(newVersion.fullVersion); } else { console.log(`There's no musl build for version ${newVersion.fullVersion} yet.`); process.exit(0); } } const { stdout } = (await exec(`git diff`)); console.log(stdout); return updatedVersions.join(', '); } } ================================================ FILE: config ================================================ baseuri https://nodejs.org/dist default_variant bookworm alpine_version 3.23 debian_versions bookworm bullseye trixie ================================================ FILE: docker-entrypoint.sh ================================================ #!/bin/sh set -e # Run command with node if the first argument contains a "-" or is not a system command. The last # part inside the "{}" is a workaround for the following bug in ash/dash: # https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=874264 if [ "${1#-}" != "${1}" ] || [ -z "$(command -v "${1}")" ] || { [ -f "${1}" ] && ! [ -x "${1}" ]; }; then set -- node "$@" fi exec "$@" ================================================ FILE: docs/BestPractices.md ================================================ # Docker and Node.js Best Practices ## Table of Contents - [Environment Variables](#environment-variables) - [Global npm dependencies](#global-npm-dependencies) - [Upgrading/downgrading Yarn](#upgradingdowngrading-yarn) - [Local](#local) - [Global](#global) - [Handling Kernel Signals](#handling-kernel-signals) - [Non-root User](#non-root-user) - [Memory](#memory) - [CMD](#cmd) - [Docker Run](#docker-run) - [Security](#security) - [node-gyp alpine](#node-gyp-alpine) - [Smaller images without npm/yarn](#smaller-images-without-npmyarn) ## Environment Variables Run with `NODE_ENV` set to `production`. This is the way you would pass in secrets and other runtime configurations to your application as well. ``` -e "NODE_ENV=production" ``` ## Global npm dependencies If you need to install global npm dependencies, it is recommended to place those dependencies in the [non-root user](#non-root-user) directory. To achieve this, add the following line to your `Dockerfile` ```Dockerfile ENV NPM_CONFIG_PREFIX=/home/node/.npm-global ENV PATH=$PATH:/home/node/.npm-global/bin # optionally if you want to run npm global bin without specifying path ``` ## Upgrading/downgrading Yarn ### Local If you need to upgrade/downgrade `yarn` for a local install, you can do so by issuing the following commands in your `Dockerfile`: > Note that if you create some other directory which is not a descendant one from where you ran the command, you will end up using the global (dated) version. If you wish to upgrade `yarn` globally, follow the instructions in the next section. > When following the local install instructions, due to duplicated yarn the image will end up being bigger. ```Dockerfile FROM node:6 ENV YARN_VERSION=1.16.0 RUN yarn policies set-version $YARN_VERSION ``` ### Global ```Dockerfile FROM node:6 ENV YARN_VERSION=1.16.0 RUN curl -fSLO --compressed "https://yarnpkg.com/downloads/$YARN_VERSION/yarn-v$YARN_VERSION.tar.gz" \ && tar -xzf yarn-v$YARN_VERSION.tar.gz -C /opt/ \ && ln -snf /opt/yarn-v$YARN_VERSION/bin/yarn /usr/local/bin/yarn \ && ln -snf /opt/yarn-v$YARN_VERSION/bin/yarnpkg /usr/local/bin/yarnpkg \ && rm yarn-v$YARN_VERSION.tar.gz ``` If you're using an Alpine-based image, `curl` won't be present, so you'll need to make sure it's installed while using it: ```Dockerfile FROM node:6-alpine ENV YARN_VERSION=1.5.1 RUN apk add --no-cache --virtual .build-deps-yarn curl \ && curl -fSLO --compressed "https://yarnpkg.com/downloads/$YARN_VERSION/yarn-v$YARN_VERSION.tar.gz" \ && tar -xzf yarn-v$YARN_VERSION.tar.gz -C /opt/ \ && ln -snf /opt/yarn-v$YARN_VERSION/bin/yarn /usr/local/bin/yarn \ && ln -snf /opt/yarn-v$YARN_VERSION/bin/yarnpkg /usr/local/bin/yarnpkg \ && rm yarn-v$YARN_VERSION.tar.gz \ && apk del .build-deps-yarn ``` ## Handling Kernel Signals Node.js was not designed to run as PID 1 which leads to unexpected behaviour when running inside of Docker. For example, a Node.js process running as PID 1 will not respond to `SIGINT` (`CTRL-C`) and similar signals. As of Docker 1.13, you can use the `--init` flag to wrap your Node.js process with a [lightweight init system](https://github.com/krallin/tini) that properly handles running as PID 1. ``` docker run -it --init node ``` You can also include Tini [directly in your Dockerfile](https://github.com/krallin/tini#using-tini), ensuring your process is always started with an init wrapper. ## Non-root User By default, Docker runs commands inside the container as root which violates the [Principle of Least Privilege (PoLP)](https://en.wikipedia.org/wiki/Principle_of_least_privilege) when superuser permissions are not strictly required. You want to run the container as an unprivileged user whenever possible. The node images provide the `node` user with uid 1000 for such purpose. The Docker Image can then be run with the `node` user in the following way: ``` -u "node" ``` Alternatively, the user can be activated in the `Dockerfile`: ```Dockerfile FROM node:6.10.3 ... # At the end, set the user to use when running this image USER 1000 # node ``` Note that the `node` user is neither a build-time nor a run-time dependency and it can be removed or altered, as long as the functionality of the application you want to add to the container does not depend on it. If you do not want nor need the user created in this image, you can remove it with the following: ```Dockerfile # For debian based images use: RUN userdel -r node # For alpine based images use: RUN deluser --remove-home node ``` If you need to change the uid/gid of the user, you can use: ```Dockerfile RUN groupmod -g 999 node && usermod -u 999 -g 999 node ``` If you need another name for the user (ex. `myapp`), execute: ```Dockerfile RUN usermod -d /home/myapp -l myapp node ``` For alpine based images, you do not have `groupmod` nor `usermod`, so to change the uid/gid you have to delete the previous user: ```Dockerfile RUN deluser --remove-home node \ && addgroup -S node -g 999 \ && adduser -S -G node -u 999 node ``` ## Memory By default, any Docker Container may consume as much of the hardware such as CPU and RAM. If you are running multiple containers on the same host, you should limit how much memory they can consume. ``` -m "300M" --memory-swap "1G" ``` ## CMD When creating an image, you can bypass the `package.json`'s `start` command and bake it directly into the image itself. First off, this reduces the number of processes running inside of your container. Secondly, it causes exit signals such as `SIGTERM` and `SIGINT` to be received by the Node.js process instead of npm swallowing them. ```Dockerfile CMD ["node","index.js"] ``` ## Docker Run Here is an example of how you would run a default Node.JS Docker Containerized application: ``` $ docker run \ --init \ -e "NODE_ENV=production" \ -u "node" \ -m "300M" --memory-swap "1G" \ -w "/home/node/app" \ --name "my-nodejs-app" \ node [script] ``` ## Security The Docker team has provided a tool to analyze your running containers for potential security issues. You can download and run this tool from here: https://github.com/docker/docker-bench-security ## node-gyp alpine Here is an example of how you would install dependencies for packages that require node-gyp support on the alpine variant: ```Dockerfile FROM node:alpine RUN apk add --no-cache --virtual .gyp python3 py-setuptools make g++ \ && npm install [ your npm dependencies here ] \ && apk del .gyp ``` And, here's a multistage build example: ```Dockerfile FROM node:alpine as builder ## Install build toolchain, install node deps and compile native add-ons RUN apk add --no-cache python3 make g++ RUN npm install [ your npm dependencies here ] FROM node:alpine as app ## Copy built node modules and binaries without including the toolchain COPY --from=builder node_modules . ``` ## Smaller images without npm/yarn If you want to achieve an even smaller image size than the `-alpine`, you can omit the npm/yarn like this: ```Dockerfile ARG ALPINE_VERSION=3.23 FROM node:24-alpine${ALPINE_VERSION} AS builder WORKDIR /build-stage COPY package*.json ./ RUN npm ci # Copy the the files you need COPY . ./ RUN npm run build FROM alpine:${ALPINE_VERSION} # Create app directory WORKDIR /usr/src/app # Add required binaries RUN apk add --no-cache libstdc++ dumb-init \ && addgroup -g 1000 node && adduser -u 1000 -G node -s /bin/sh -D node \ && chown node:node ./ COPY --from=builder /usr/local/bin/node /usr/local/bin/ COPY --from=builder /usr/local/bin/docker-entrypoint.sh /usr/local/bin/ ENTRYPOINT ["docker-entrypoint.sh"] USER node # Update the following COPY lines based on your codebase COPY --from=builder /build-stage/node_modules ./node_modules COPY --from=builder /build-stage/dist ./dist # Run with dumb-init to not start node with PID=1, since Node.js was not designed to run as PID 1 CMD ["dumb-init", "node", "dist/index.js"] ``` ================================================ FILE: functions.sh ================================================ #!/usr/bin/env bash # # Utlity functions # Don't change this file unless needed # The GitHub Action for automating new builds rely on this file info() { printf "%s\\n" "$@" } fatal() { printf "**********\\n" printf "Fatal Error: %s\\n" "$@" printf "**********\\n" exit 1 } # Get system architecture # # This is used to get the target architecture for docker image. # For crossing building, we need a way to specify the target # architecutre manually. function get_arch() { local arch case $(uname -m) in x86_64) arch="amd64" ;; ppc64le) arch="ppc64le" ;; s390x) arch="s390x" ;; aarch64 | arm64) arch="arm64" ;; armv7l) arch="arm32v7" ;; *) echo "$0 does not support architecture ${arch:-unknown} ... aborting" exit 1 ;; esac echo "${arch}" } # Get corresponding variants based on the architecture. # All supported variants of each supported architecture are listed in a # file - 'architectures'. Its format is: # ,... # ,... function get_variants() { local dir dir=${1:-.} shift local arch local availablevariants local variantsfilter local variants=() arch=$(get_arch) variantsfilter=("$@") IFS=' ' read -ra availablevariants <<< "$(grep "^${arch}" "${dir}/architectures" | sed -E 's/'"${arch}"'[[:space:]]*//' | sed -E 's/,/ /g')" if [ ${#variantsfilter[@]} -gt 0 ]; then for variant1 in "${availablevariants[@]}"; do for variant2 in "${variantsfilter[@]}"; do if [ "${variant1}" = "${variant2}" ]; then variants+=("${variant1}") fi done done if [ ${#variants[@]} -gt 0 ]; then echo "${variants[@]}" fi else echo "${availablevariants[@]}" fi } # Get supported architectures for a specific version and variant # # Get default supported architectures from 'architectures'. Then go to the version folder # to see if there is a local architectures file. The local architectures will override the # default architectures. This will give us some benefits: # - a specific version may or may not support some architectures # - if there is no specialization for a version, just don't provide local architectures function get_supported_arches() { local version local variant local arches local lines local line version="$1" shift variant="$1" shift # Get default supported arches lines=$(grep "${variant}" "$(dirname "${version}")"/architectures 2> /dev/null | cut -d' ' -f1) # Get version specific supported architectures if there is specialized information if [ -a "${version}"/architectures ]; then lines=$(grep "${variant}" "${version}"/architectures 2> /dev/null | cut -d' ' -f1) fi while IFS='' read -r line; do arches+=("${line}") done <<< "${lines}" echo "${arches[@]}" } # Get configuration values from the config file # # The configuration entries are simple key/value pairs which are whitespace separated. function get_config() { local dir dir=${1:-.} shift local name name=${1} shift local value value=$(grep "^${name}" "${dir}/config" | sed -E 's/'"${name}"'[[:space:]]*//') echo "${value}" } # Get available versions for a given path # # The result is a list of valid versions. # shellcheck disable=SC2120 function get_versions() { shift local versions=() local dirs=("$@") local default_variant default_variant=$(get_config "./" "default_variant") if [ ${#dirs[@]} -eq 0 ]; then IFS=' ' read -ra dirs <<< "$(echo "./"*/)" fi for dir in "${dirs[@]}"; do if [ -a "${dir}/Dockerfile" ] || [ -a "${dir}/${default_variant}/Dockerfile" ]; then versions+=("${dir#./}") fi done if [ ${#versions[@]} -gt 0 ]; then echo "${versions[@]%/}" fi } function is_alpine() { local variant variant=${1} shift if [ "${variant}" = "${variant#alpine}" ]; then return 1 fi } function is_debian() { local variant variant=$1 shift IFS=' ' read -ra debianVersions <<< "$(get_config "./" "debian_versions")" for d in "${debianVersions[@]}"; do if [ "${d}" = "${variant}" ]; then return 0 fi done return 1 } function is_debian_slim() { local variant variant=$1 shift IFS=' ' read -ra debianVersions <<< "$(get_config "./" "debian_versions")" for d in "${debianVersions[@]}"; do if [ "${d}-slim" = "${variant}" ]; then return 0 fi done return 1 } function get_fork_name() { local version version=$1 shift IFS='/' read -ra versionparts <<< "${version}" if [ ${#versionparts[@]} -gt 1 ]; then echo "${versionparts[0]}" fi } function get_full_tag() { local variant local tag local full_tag variant="$1" shift tag="$1" shift if [ -z "${variant}" ]; then full_tag="${tag}" elif [ "${variant}" = "default" ]; then full_tag="${tag}" else full_tag="${tag}-${variant}" fi echo "${full_tag}" } function get_full_version() { local version version=$1 shift local default_dockerfile if [ -f "${version}/${default_variant}/Dockerfile" ]; then default_dockerfile="${version}/${default_variant}/Dockerfile" else default_dockerfile="${version}/Dockerfile" fi grep -m1 'ENV NODE_VERSION=' "${default_dockerfile}" | cut -d= -f2 } function get_major_minor_version() { local version version=$1 shift local fullversion fullversion=$(get_full_version "${version}") echo "$(echo "${fullversion}" | cut -d'.' -f1).$(echo "${fullversion}" | cut -d'.' -f2)" } function get_path() { local version local variant local path version="$1" shift variant="$1" shift if [ -z "${variant}" ]; then path="${version}/${variant}" elif [ "${variant}" = "default" ]; then path="${version}" else path="${version}/${variant}" fi echo "${path}" } function get_tag() { local version version=$1 shift local versiontype versiontype=${1:-full} shift local tagversion if [ "${versiontype}" = full ]; then tagversion=$(get_full_version "${version}") elif [ "${versiontype}" = majorminor ]; then tagversion=$(get_major_minor_version "${version}") fi local tagparts IFS=' ' read -ra tagparts <<< "$(get_fork_name "${version}") ${tagversion}" IFS='-' echo "${tagparts[*]}" unset IFS } function sort_versions() { local versions=("$@") local sorted local lines local line IFS=$'\n' lines="${versions[*]}" unset IFS while IFS='' read -r line; do sorted+=("${line}") done <<< "$(echo "${lines}" | grep "^[0-9]" | sort -r)" while IFS='' read -r line; do sorted+=("${line}") done <<< "$(echo "${lines}" | grep -v "^[0-9]" | sort -r)" echo "${sorted[@]}" } function commit_range() { local commit_id_end=${1} shift local commit_id_start=${1} if [ -z "${commit_id_start}" ]; then if [ -z "${commit_id_end}" ]; then echo "HEAD~1..HEAD" elif [[ "${commit_id_end}" =~ .. ]]; then echo "${commit_id_end}" else echo "${commit_id_end}~1..${commit_id_end}" fi else echo "${commit_id_end}..${commit_id_start}" fi } function images_updated() { local commit_range local versions local images_changed commit_range="$(commit_range "$@")" IFS=' ' read -ra versions <<< "$( IFS=',' get_versions )" images_changed=$(git diff --name-only "${commit_range}" "${versions[@]}") if [ -z "${images_changed}" ]; then return 1 fi return 0 } function tests_updated() { local commit_range local test_changed commit_range="$(commit_range "$@")" test_changed=$(git diff --name-only "${commit_range}" test*) if [ -z "${test_changed}" ]; then return 1 fi return 0 } ================================================ FILE: genMatrix.js ================================================ 'use strict'; const path = require('path'); const fs = require('fs'); const testFiles = [ 'genMatrix.js', '.github/workflows/build-test.yml', ]; const nodeDirRegex = /^\d+$/; const areTestFilesChanged = (changedFiles) => changedFiles .some((file) => testFiles.includes(file)); // Returns a list of the child directories in the given path const getChildDirectories = (parent) => fs.readdirSync(parent, { withFileTypes: true }) .filter((dirent) => dirent.isDirectory()) .map(({ name }) => path.resolve(parent, name)); const getNodeVerionDirs = (base) => getChildDirectories(base) .filter((childPath) => nodeDirRegex.test(path.basename(childPath))); // Returns the paths of Dockerfiles that are at: base/*/Dockerfile const getDockerfilesInChildDirs = (base) => getChildDirectories(base) .map((childDir) => path.resolve(childDir, 'Dockerfile')); const getAllDockerfiles = (base) => getNodeVerionDirs(base).flatMap(getDockerfilesInChildDirs); const getAffectedDockerfiles = (filesAdded, filesModified, filesRenamed) => { const files = [ ...filesAdded, ...filesModified, ...filesRenamed, ]; // If the test files were changed, include everything if (areTestFilesChanged(files)) { console.log('Test files changed so scheduling all Dockerfiles'); return getAllDockerfiles(__dirname); } const modifiedDockerfiles = files.filter((file) => file.endsWith('/Dockerfile')); // Get Dockerfiles affected by modified docker-entrypoint.sh files const entrypointAffectedDockerfiles = files .filter((file) => file.endsWith('/docker-entrypoint.sh')) .map((file) => path.resolve(path.dirname(file), 'Dockerfile')); return [ ...modifiedDockerfiles, ...entrypointAffectedDockerfiles, ]; }; const getFullNodeVersionFromDockerfile = (file) => fs.readFileSync(file, 'utf8') .match(/^ENV NODE_VERSION=(\d*\.*\d*\.\d*)/m)[1]; const getDockerfileMatrixEntry = (file) => { const [variant] = path.dirname(file).split(path.sep).slice(-1); const version = getFullNodeVersionFromDockerfile(file); return { version, variant, }; }; const generateBuildMatrix = (filesAdded, filesModified, filesRenamed) => { const dockerfiles = [...new Set(getAffectedDockerfiles(filesAdded, filesModified, filesRenamed))]; const entries = dockerfiles.map(getDockerfileMatrixEntry); // Return null if there are no entries so we can skip the matrix step return entries.length ? { include: entries } : null; }; module.exports = generateBuildMatrix; ================================================ FILE: keys/node.keys ================================================ 5BE8A3F6C8A5C01D106C0AD820B1A390B168D356 DD792F5973C6DE52C432CBDAC77ABFA00DDBF2B7 CC68F5A3106FF448322E48ED27F5E38D5B0A215F 8FCCA13FEF1D0C2E91008E09770F7A9A5AE15600 890C08DB8579162FEE0DF9DB8BEAB4DFCF555EF4 C82FA3AE1CBEDC6BE46B9360C43CEC45C17AB93C 108F52B48DB57BB0CC439B2997B01419BD92F80A A363A499291CBBC940DD62E41F10027AF002F8B0 ================================================ FILE: markdown_link_check_config.json ================================================ { "ignorePatterns": [ { "pattern": "^https://nodejs\\.org/" }, { "pattern": "^https://www\\.npmjs\\.com/" }, { "pattern": "^https://news\\.ycombinator\\.com/" } ] } ================================================ FILE: stackbrew.js ================================================ #!/usr/bin/env node const fs = require('fs'); const path = require('path'); // Grab last git commit function getCommitHasForPath(path) { return require('child_process') .execSync(`git log -1 --format=%H HEAD -- ${path}`) .toString().trim() } const stackbrewPath = path.basename(__filename); // Header let stackbrew = `# this file is generated via https://github.com/nodejs/docker-node/blob/${getCommitHasForPath(stackbrewPath)}/${stackbrewPath} Maintainers: The Node.js Docker Team (@nodejs) GitRepo: https://github.com/nodejs/docker-node.git GitFetch: refs/heads/main\n`; // Loop versions const config = require('./versions.json'); const versions = Object.keys(config).reverse() let midnight = new Date() midnight.setHours(0, 0, 0, 0) const now = midnight.getTime() const aplineRE = new RegExp(/alpine*/); const slimRE = new RegExp(/\*-slim/); let foundLTS = false; let foundCurrent = false; for (version of versions) { let lts = new Date(`${config[version].lts}T00:00:00.00`).getTime(); let maintenance = new Date(`${config[version].maintenance}T00:00:00.00`).getTime(); let isCurrent = foundCurrent ? false : isNaN(lts) || lts >= now; foundCurrent = isCurrent || foundCurrent; let isLTS = foundLTS ? false : (now >= lts); foundLTS = isLTS || foundLTS; let codename = config[version].codename let defaultAlpine = config[version]['alpine-default'] let defaultDebian = config[version]['debian-default'] let variants = config[version].variants let fullversion; for (variant in variants) { let dockerfilePath = path.join(version, variant, 'Dockerfile'); let isAlpine = aplineRE.test(variant) let isSlim = slimRE.test(variant) let isDefaultSlim = new RegExp(`${defaultDebian}-slim`).test(variant) // Get full version from the Dockerfile let dockerfile = fs.readFileSync(dockerfilePath, 'utf-8') fullversion = dockerfile.match(/ENV NODE_VERSION=(?\d+)\.(?\d+)\.(?\d+)/) let tags = [ `${fullversion.groups.major}.${fullversion.groups.minor}.${fullversion.groups.patch}-${variant}`, `${fullversion.groups.major}.${fullversion.groups.minor}-${variant}`, `${fullversion.groups.major}-${variant}`, ] if (codename) { tags.push(`${codename}-${variant}`) } if (variant === defaultAlpine) { tags.push(`${fullversion.groups.major}.${fullversion.groups.minor}.${fullversion.groups.patch}-alpine`) tags.push(`${fullversion.groups.major}.${fullversion.groups.minor}-alpine`) tags.push(`${fullversion.groups.major}-alpine`) if (codename) { tags.push(`${codename}-alpine`) } } if (variant === defaultDebian) { tags.push(`${fullversion.groups.major}.${fullversion.groups.minor}.${fullversion.groups.patch}`) tags.push(`${fullversion.groups.major}.${fullversion.groups.minor}`) tags.push(`${fullversion.groups.major}`) if (isSlim) { tags.push(`${fullversion.groups.major}.${fullversion.groups.minor}.${fullversion.groups.patch}-slim`) tags.push(`${fullversion.groups.major}.${fullversion.groups.minor}-slim`) tags.push(`${fullversion.groups.major}-slim`) } if (codename) { tags.push(`${codename}`) } } if (isDefaultSlim) { tags.push(`${fullversion.groups.major}.${fullversion.groups.minor}.${fullversion.groups.patch}-slim`) tags.push(`${fullversion.groups.major}.${fullversion.groups.minor}-slim`) tags.push(`${fullversion.groups.major}-slim`) if (codename) { tags.push(`${codename}-slim`) } } if (isCurrent) { if (variant === defaultAlpine) { tags.push(variant) tags.push(`${fullversion.groups.major}.${fullversion.groups.minor}.${fullversion.groups.patch}-alpine`) tags.push(`${fullversion.groups.major}.${fullversion.groups.minor}-alpine`) tags.push(`${fullversion.groups.major}-alpine`) tags.push('alpine') tags.push('current-alpine') } if (variant === defaultDebian) { tags.push(variant) tags.push('latest') tags.push('current') } if (isAlpine) { tags.push(`${variant}`) tags.push(`current-${variant}`) } if (!isAlpine) { tags.push(`${variant}`) tags.push(`current-${variant}`) } if (isDefaultSlim) { tags.push('slim') tags.push('current-slim') } } if (isLTS) { tags.push(`lts-${variant}`) if (variant === defaultAlpine) { } if (variant === defaultDebian) { tags.push('lts') if (codename) { tags.push(`lts-${codename}`) } } if (isDefaultSlim) { tags.push(`lts-slim`) } if (variant === defaultAlpine) { tags.push(`lts-alpine`) } } // remove duplicates tags = tags.filter((x, i, a) => a.indexOf(x) == i) tags = tags.sort() let directory = `${version}/${variant}` stackbrew += `\nTags: ${tags.join(', ')}\n` stackbrew += `Architectures: ${config[version].variants[variant].join(', ')}\n` stackbrew += `GitCommit: ${getCommitHasForPath(directory)}\n` stackbrew += `Directory: ${directory}\n` } } // output console.log(stackbrew) ================================================ FILE: update-keys.sh ================================================ #!/bin/sh -ex curl -fsSLo- --compressed https://github.com/nodejs/node/raw/main/README.md | awk '/--recv-keys.*#/{ gsub(/^.*--recv-keys\s+/,"");gsub(/\s+#.*$/,""); print }' > keys/node.keys ================================================ FILE: update.sh ================================================ #!/usr/bin/env bash set -ue function usage() { cat << EOF Update the node docker images. Usage: $0 [-s] [MAJOR_VERSION(S)] [VARIANT(S)] Examples: - update.sh # Update all images - update.sh -s # Update all images, skip updating Alpine - update.sh 8,10 # Update all variants of version 8 and 10 - update.sh -s 8 # Update version 8 and variants, skip updating Alpine - update.sh 8 alpine # Update only alpine's variants for version 8 - update.sh -s 8 bullseye # Update only bullseye variant for version 8, skip updating Alpine - update.sh . alpine # Update the alpine variant for all versions OPTIONS: -s Security update; skip updating the Alpine versions. -h Show this message EOF } while getopts "sh" opt; do case "${opt}" in s) shift ;; h) usage exit ;; \?) usage exit ;; esac done . functions.sh cd "$(cd "${0%/*}" && pwd -P)" IFS=',' read -ra versions_arg <<< "${1:-}" IFS=',' read -ra variant_arg <<< "${2:-}" IFS=' ' read -ra versions <<< "$(get_versions .)" IFS=' ' read -ra update_versions <<< "$(get_versions . "${versions_arg[@]:-}")" IFS=' ' read -ra update_variants <<< "$(get_variants . "${variant_arg[@]:-}")" if [ ${#versions[@]} -eq 0 ]; then fatal "No valid versions found!" fi # Global variables # Get architecure and use this as target architecture for docker image # See details in function.sh # TODO: Should be able to specify target architecture manually arch=$(get_arch) function in_versions_to_update() { local version=$1 if [ "${#update_versions[@]}" -eq 0 ]; then echo 0 return fi for version_to_update in "${update_versions[@]}"; do if [ "${version_to_update}" = "${version}" ]; then echo 0 return fi done echo 1 } function in_variants_to_update() { local variant=$1 if [ "${#update_variants[@]}" -eq 0 ]; then echo 0 return fi for variant_to_update in "${update_variants[@]}"; do if [ "${variant_to_update}" = "${variant}" ]; then echo 0 return fi done echo 1 } function update_node_version() { local baseuri=${1} shift local version=${1} shift local template=${1} shift local dockerfile=${1} shift local variant="" if [ $# -eq 1 ]; then variant=${1} shift fi fullVersion="$(curl -sSL --compressed "${baseuri}" | grep ' /dev/null; then echo "${dockerfile} is already up to date!" else echo "${dockerfile} updated!" fi # Required for POSIX sed if [ -f "${dockerfile}-tmp-e" ]; then rm "${dockerfile}-tmp-e" fi mv -f "${dockerfile}-tmp" "${dockerfile}" ) } pids=() for version in "${versions[@]}"; do parentpath=$(dirname "${version}") versionnum=$(basename "${version}") baseuri=$(get_config "${parentpath}" "baseuri") update_version=$(in_versions_to_update "${version}") [ "${update_version}" -eq 0 ] && info "Updating version ${version}..." # Get supported variants according the target architecture # See details in function.sh IFS=' ' read -ra variants <<< "$(get_variants "${parentpath}")" if [ -f "${version}/Dockerfile" ]; then if [ "${update_version}" -eq 0 ]; then update_node_version "${baseuri}" "${versionnum}" "${parentpath}/Dockerfile.template" "${version}/Dockerfile" & pids+=($!) fi fi for variant in "${variants[@]}"; do # Skip non-docker directories [ -f "${version}/${variant}/Dockerfile" ] || continue update_variant=$(in_variants_to_update "${variant}") template_file="${parentpath}/Dockerfile-${variant}.template" if is_debian "${variant}"; then template_file="${parentpath}/Dockerfile-debian.template" elif is_debian_slim "${variant}"; then template_file="${parentpath}/Dockerfile-slim.template" elif is_alpine "${variant}"; then template_file="${parentpath}/Dockerfile-alpine.template" fi cp "${parentpath}/docker-entrypoint.sh" "${version}/${variant}/docker-entrypoint.sh" if [ "${update_version}" -eq 0 ] && [ "${update_variant}" -eq 0 ]; then update_node_version "${baseuri}" "${versionnum}" "${template_file}" "${version}/${variant}/Dockerfile" "${variant}" & pids+=($!) fi done done # The reason we explicitly wait on each pid is so the return status of this script is set properly # if one of the jobs fails. If we just called "wait", the exit status would always be 0 for pid in "${pids[@]}"; do wait "$pid" done info "Done!" ================================================ FILE: versions.json ================================================ { "25": { "start": "2025-10-15", "lts": "", "maintenance": "2026-04-01", "end": "2026-06-01", "codename": "", "alpine-default": "alpine3.23", "debian-default": "bookworm", "variants": { "alpine3.22": [ "amd64", "arm64v8", "s390x" ], "alpine3.23": [ "amd64", "arm64v8", "s390x" ], "bookworm": [ "amd64", "arm64v8", "ppc64le", "s390x" ], "bookworm-slim": [ "amd64", "arm64v8", "ppc64le", "s390x" ], "bullseye": [ "amd64", "arm64v8" ], "bullseye-slim": [ "amd64", "arm64v8" ], "trixie": [ "amd64", "arm64v8", "ppc64le", "s390x" ], "trixie-slim": [ "amd64", "arm64v8", "ppc64le", "s390x" ] } }, "24": { "start": "2025-05-06", "lts": "2025-10-28", "maintenance": "2026-10-20", "end": "2028-04-30", "codename": "krypton", "alpine-default": "alpine3.23", "debian-default": "bookworm", "variants": { "alpine3.22": [ "amd64", "arm64v8", "s390x" ], "alpine3.23": [ "amd64", "arm64v8", "s390x" ], "bookworm": [ "amd64", "arm64v8", "ppc64le", "s390x" ], "bookworm-slim": [ "amd64", "arm64v8", "ppc64le", "s390x" ], "bullseye": [ "amd64", "arm64v8" ], "bullseye-slim": [ "amd64", "arm64v8" ], "trixie": [ "amd64", "arm64v8", "ppc64le", "s390x" ], "trixie-slim": [ "amd64", "arm64v8", "ppc64le", "s390x" ] } }, "22": { "start": "2024-04-23", "lts": "2024-10-29", "maintenance": "2025-10-21", "end": "2027-04-30", "codename": "jod", "alpine-default": "alpine3.23", "debian-default": "bookworm", "variants": { "alpine3.22": [ "amd64", "arm32v6", "arm32v7", "arm64v8", "s390x" ], "alpine3.23": [ "amd64", "arm32v6", "arm32v7", "arm64v8", "s390x" ], "bookworm": [ "amd64", "arm32v7", "arm64v8", "ppc64le", "s390x" ], "bookworm-slim": [ "amd64", "arm32v7", "arm64v8", "ppc64le", "s390x" ], "bullseye": [ "amd64", "arm32v7", "arm64v8" ], "bullseye-slim": [ "amd64", "arm32v7", "arm64v8" ], "trixie": [ "amd64", "arm64v8", "ppc64le", "s390x" ], "trixie-slim": [ "amd64", "arm64v8", "ppc64le", "s390x" ] } }, "20": { "start": "2023-04-18", "lts": "2023-10-24", "maintenance": "2024-10-22", "end": "2026-04-30", "codename": "iron", "alpine-default": "alpine3.23", "debian-default": "bookworm", "variants": { "alpine3.22": [ "amd64", "arm32v6", "arm32v7", "arm64v8", "ppc64le", "s390x" ], "alpine3.23": [ "amd64", "arm32v6", "arm32v7", "arm64v8", "ppc64le", "s390x" ], "bookworm": [ "amd64", "arm32v7", "arm64v8", "ppc64le", "s390x" ], "bookworm-slim": [ "amd64", "arm32v7", "arm64v8", "ppc64le", "s390x" ], "bullseye": [ "amd64", "arm32v7", "arm64v8" ], "bullseye-slim": [ "amd64", "arm32v7", "arm64v8" ], "trixie": [ "amd64", "arm64v8", "ppc64le", "s390x" ], "trixie-slim": [ "amd64", "arm64v8", "ppc64le", "s390x" ] } } }