From 13728f9252011e6c73e383e7800add92e40931e2 Mon Sep 17 00:00:00 2001 From: hsiegeln <37154749+hsiegeln@users.noreply.github.com> Date: Tue, 21 Apr 2026 11:52:55 +0200 Subject: [PATCH] fix(docker): expliziter Plattform-Install fuer sharp-Prebuilts Finaler Anlauf gegen den arm64-Build-Fehler. Bisher scheiterte npm daran, @img/sharp-linuxmusl-arm64 unter Docker-Buildx-QEMU zu installieren, trotz --include=optional. Mehrschichtiger Fix: 1. --cpu=arm64 --os=linux --libc=musl auf npm install: umgeht QEMU- bezogene Detection-Bugs (sharp's offiziell empfohlener Fix). 2. Expliziter Zusatz-Install von @img/sharp-linuxmusl-arm64 und @img/sharp-libvips-linuxmusl-arm64: zwingt die Prebuilts auf Disk, unabhaengig von der Lockfile-Resolution. 3. --ignore-scripts beim Install + npm rebuild danach: loest den Race, wo sharp's postinstall laeuft bevor der Prebuilt-Tarball fertig ist. 4. node-addon-api + node-gyp als Runtime-Deps: from-source-Build- Fallback falls alle Prebuilt-Pfade scheitern. Co-Authored-By: Claude Opus 4.7 (1M context) --- Dockerfile | 38 +++++++--- package-lock.json | 182 +++++++++++++++++++++++++++++++++++++++++++++- package.json | 1 + 3 files changed, 207 insertions(+), 14 deletions(-) diff --git a/Dockerfile b/Dockerfile index 2552c87..78ec5e9 100644 --- a/Dockerfile +++ b/Dockerfile @@ -8,24 +8,38 @@ WORKDIR /app RUN apk add --no-cache python3 make g++ libc6-compat vips-dev COPY package*.json ./ -# Zwei Fallstricke werden hier adressiert: -# (a) Der auf Windows erzeugte package-lock.json markiert die linux-musl- -# arm64-Prebuilts von sharp als "dev": true, weshalb npm ci sie selbst -# mit --include=optional nicht installiert. --> npm install statt ci. -# (b) Parallel-Install laesst sharp's postinstall laufen, bevor das -# @img/sharp-linuxmusl-arm64-Paket entpackt ist. --> --ignore-scripts -# hier, dann npm rebuild mit allen Deps auf Disk. node-addon-api ist -# als devDep da, damit der from-source Fallback ebenfalls funktioniert -# (python3 + make + g++ + vips-dev sind oben installiert). -RUN npm install --ignore-scripts --include=optional --no-audit --no-fund +# Sharp-Prebuilt-Install unter Docker-Buildx-QEMU war trotz aller Flag- +# Varianten unzuverlaessig. Finale Strategie: +# - --cpu/--os/--libc explizit setzen: sharp's offizielle Doc-Empfehlung +# fuer Cross-Platform-Docker-Builds (siehe sharp-Install-Doku), +# umgeht QEMU-Detection-Bugs. +# - --ignore-scripts + npm rebuild: loest das Parallel-Install-Race, +# bei dem sharp's install-Skript vor dem Entpacken der Prebuilt-Binary +# laeuft. +# - Explizites Nachinstallieren der Prebuilts als Sicherheit: falls (A) +# noch nicht reicht, zwingt (B) die Plattform-Pakete auf Disk. +# - node-addon-api + node-gyp als Runtime-Deps: falls am Ende doch alles +# nicht klappt und sharp from-source baut (mit dem oben installierten +# python3 + make + g++ + vips-dev). +RUN npm install --cpu=arm64 --os=linux --libc=musl \ + --ignore-scripts --include=optional --no-audit --no-fund +RUN npm install --cpu=arm64 --os=linux --libc=musl \ + --ignore-scripts --no-save --no-audit --no-fund \ + @img/sharp-linuxmusl-arm64@0.34.5 \ + @img/sharp-libvips-linuxmusl-arm64@1.2.4 RUN npm rebuild COPY . . RUN npm run build -# Fresh-Install fuer den Runtime-Stage: nur Produktions-Deps, gleicher Ansatz. +# Fresh-Install fuer den Runtime-Stage: nur Produktions-Deps, gleiche Strategie. RUN rm -rf node_modules \ - && npm install --ignore-scripts --omit=dev --include=optional --no-audit --no-fund \ + && npm install --cpu=arm64 --os=linux --libc=musl \ + --ignore-scripts --omit=dev --include=optional --no-audit --no-fund \ + && npm install --cpu=arm64 --os=linux --libc=musl \ + --ignore-scripts --no-save --no-audit --no-fund \ + @img/sharp-linuxmusl-arm64@0.34.5 \ + @img/sharp-libvips-linuxmusl-arm64@1.2.4 \ && npm rebuild FROM node:22-alpine AS runner diff --git a/package-lock.json b/package-lock.json index aa2231b..e725ad5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -16,6 +16,7 @@ "linkedom": "^0.18.5", "lucide-svelte": "^1.0.1", "node-addon-api": "^8.7.0", + "node-gyp": "^12.3.0", "yauzl": "^3.3.0", "zod": "^3.23.8" }, @@ -1177,6 +1178,18 @@ "node": ">=12" } }, + "node_modules/@isaacs/fs-minipass": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@isaacs/fs-minipass/-/fs-minipass-4.0.1.tgz", + "integrity": "sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w==", + "license": "ISC", + "dependencies": { + "minipass": "^7.0.4" + }, + "engines": { + "node": ">=18.0.0" + } + }, "node_modules/@jridgewell/gen-mapping": { "version": "0.3.13", "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", @@ -2010,6 +2023,15 @@ "url": "https://opencollective.com/vitest" } }, + "node_modules/abbrev": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-4.0.0.tgz", + "integrity": "sha512-a1wflyaL0tHtJSmLSOVybYhy22vRih4eduhhrkcjgrWGnRfrZtovJ2FRjxuTtkkj47O/baf0R86QU5OuYpz8fA==", + "license": "ISC", + "engines": { + "node": "^20.17.0 || >=22.9.0" + } + }, "node_modules/abort-controller": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", @@ -2784,6 +2806,15 @@ "url": "https://github.com/fb55/entities?sponsor=1" } }, + "node_modules/env-paths": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", + "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/es-errors": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", @@ -2916,6 +2947,12 @@ "node": ">=12.0.0" } }, + "node_modules/exponential-backoff": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/exponential-backoff/-/exponential-backoff-3.1.3.tgz", + "integrity": "sha512-ZgEeZXj30q+I0EN+CbSSpIyPaJ5HVQD18Z1m+u1FXbAeT94mr1zw50q4q6jiiC447Nl/YTcIYSAftiGqetwXCA==", + "license": "Apache-2.0" + }, "node_modules/fast-fifo": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/fast-fifo/-/fast-fifo-1.3.2.tgz", @@ -2926,7 +2963,6 @@ "version": "6.5.0", "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", - "dev": true, "license": "MIT", "engines": { "node": ">=12.0.0" @@ -3425,6 +3461,18 @@ "node": ">=16 || 14 >=14.17" } }, + "node_modules/minizlib": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-3.1.0.tgz", + "integrity": "sha512-KZxYo1BUkWD2TVFLr0MQoM8vUUigWD3LlD83a/75BqC+4qE0Hb1Vo5v1FgcfaNXvfXzr+5EhQ6ing/CaBijTlw==", + "license": "MIT", + "dependencies": { + "minipass": "^7.1.2" + }, + "engines": { + "node": ">= 18" + } + }, "node_modules/mkdirp-classic": { "version": "0.5.3", "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", @@ -3504,6 +3552,78 @@ "node": "^18 || ^20 || >= 21" } }, + "node_modules/node-gyp": { + "version": "12.3.0", + "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-12.3.0.tgz", + "integrity": "sha512-QNcUWM+HgJplcPzBvFBZ9VXacyGZ4+VTOb80PwWR+TlVzoHbRKULNEzpRsnaoxG3Wzr7Qh7BYxGDU3CbKib2Yg==", + "license": "MIT", + "dependencies": { + "env-paths": "^2.2.0", + "exponential-backoff": "^3.1.1", + "graceful-fs": "^4.2.6", + "nopt": "^9.0.0", + "proc-log": "^6.0.0", + "semver": "^7.3.5", + "tar": "^7.5.4", + "tinyglobby": "^0.2.12", + "undici": "^6.25.0", + "which": "^6.0.0" + }, + "bin": { + "node-gyp": "bin/node-gyp.js" + }, + "engines": { + "node": "^20.17.0 || >=22.9.0" + } + }, + "node_modules/node-gyp/node_modules/isexe": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-4.0.0.tgz", + "integrity": "sha512-FFUtZMpoZ8RqHS3XeXEmHWLA4thH+ZxCv2lOiPIn1Xc7CxrqhWzNSDzD+/chS/zbYezmiwWLdQC09JdQKmthOw==", + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=20" + } + }, + "node_modules/node-gyp/node_modules/undici": { + "version": "6.25.0", + "resolved": "https://registry.npmjs.org/undici/-/undici-6.25.0.tgz", + "integrity": "sha512-ZgpWDC5gmNiuY9CnLVXEH8rl50xhRCuLNA97fAUnKi8RRuV4E6KG31pDTsLVUKnohJE0I3XDrTeEydAXRw47xg==", + "license": "MIT", + "engines": { + "node": ">=18.17" + } + }, + "node_modules/node-gyp/node_modules/which": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/which/-/which-6.0.1.tgz", + "integrity": "sha512-oGLe46MIrCRqX7ytPUf66EAYvdeMIZYn3WaocqqKZAxrBpkqHfL/qvTyJ/bTk5+AqHCjXmrv3CEWgy368zhRUg==", + "license": "ISC", + "dependencies": { + "isexe": "^4.0.0" + }, + "bin": { + "node-which": "bin/which.js" + }, + "engines": { + "node": "^20.17.0 || >=22.9.0" + } + }, + "node_modules/nopt": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-9.0.0.tgz", + "integrity": "sha512-Zhq3a+yFKrYwSBluL4H9XP3m3y5uvQkB/09CwDruCiRmR/UJYnn9W4R48ry0uGC70aeTPKLynBtscP9efFFcPw==", + "license": "ISC", + "dependencies": { + "abbrev": "^4.0.0" + }, + "bin": { + "nopt": "bin/nopt.js" + }, + "engines": { + "node": "^20.17.0 || >=22.9.0" + } + }, "node_modules/normalize-path": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", @@ -3638,7 +3758,6 @@ "version": "4.0.4", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz", "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", - "dev": true, "license": "MIT", "engines": { "node": ">=12" @@ -3762,6 +3881,15 @@ "svelte": "^3.2.0 || ^4.0.0-next.0 || ^5.0.0-next.0" } }, + "node_modules/proc-log": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/proc-log/-/proc-log-6.1.0.tgz", + "integrity": "sha512-iG+GYldRf2BQ0UDUAd6JQ/RwzaQy6mXmsk/IzlYyal4A4SNFw54MeH4/tLkF4I5WoWG9SQwuqWzS99jaFQHBuQ==", + "license": "ISC", + "engines": { + "node": "^20.17.0 || >=22.9.0" + } + }, "node_modules/process": { "version": "0.11.10", "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", @@ -4379,6 +4507,22 @@ "dev": true, "license": "MIT" }, + "node_modules/tar": { + "version": "7.5.13", + "resolved": "https://registry.npmjs.org/tar/-/tar-7.5.13.tgz", + "integrity": "sha512-tOG/7GyXpFevhXVh8jOPJrmtRpOTsYqUIkVdVooZYJS/z8WhfQUX8RJILmeuJNinGAMSu1veBr4asSHFt5/hng==", + "license": "BlueOak-1.0.0", + "dependencies": { + "@isaacs/fs-minipass": "^4.0.0", + "chownr": "^3.0.0", + "minipass": "^7.1.2", + "minizlib": "^3.1.0", + "yallist": "^5.0.0" + }, + "engines": { + "node": ">=18" + } + }, "node_modules/tar-fs": { "version": "2.1.4", "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.4.tgz", @@ -4433,6 +4577,15 @@ "streamx": "^2.15.0" } }, + "node_modules/tar/node_modules/chownr": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-3.0.0.tgz", + "integrity": "sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==", + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=18" + } + }, "node_modules/teex": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/teex/-/teex-1.0.1.tgz", @@ -4465,6 +4618,22 @@ "dev": true, "license": "MIT" }, + "node_modules/tinyglobby": { + "version": "0.2.16", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.16.tgz", + "integrity": "sha512-pn99VhoACYR8nFHhxqix+uvsbXineAasWm5ojXoN8xEwK5Kd3/TrhNn1wByuD52UxWRLy8pu+kRMniEi6Eq9Zg==", + "license": "MIT", + "dependencies": { + "fdir": "^6.5.0", + "picomatch": "^4.0.4" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" + } + }, "node_modules/tinypool": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-1.1.1.tgz", @@ -4991,6 +5160,15 @@ "dev": true, "license": "MIT" }, + "node_modules/yallist": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-5.0.0.tgz", + "integrity": "sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw==", + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=18" + } + }, "node_modules/yauzl": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-3.3.0.tgz", diff --git a/package.json b/package.json index 3241954..660cbc0 100644 --- a/package.json +++ b/package.json @@ -43,6 +43,7 @@ "linkedom": "^0.18.5", "lucide-svelte": "^1.0.1", "node-addon-api": "^8.7.0", + "node-gyp": "^12.3.0", "yauzl": "^3.3.0", "zod": "^3.23.8" }