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