diff --git a/deploy/Dockerfile.api b/deploy/Dockerfile.api index 20ec1b1..a669abc 100644 --- a/deploy/Dockerfile.api +++ b/deploy/Dockerfile.api @@ -5,7 +5,10 @@ # builder на том же node:22-slim (glibc), что и рантайм: нативный better-sqlite3, # скачанный/собранный здесь под целевую платформу, гарантированно совместим -FROM node:22-slim AS build +# Сборка нативно на машине сборки (под QEMU тяжёлые сборки падают); better-sqlite3 везёт +# prebuilt-бинарники всех платформ, ниже оставляем только бинарник целевой. +FROM --platform=$BUILDPLATFORM node:22-slim AS build +ARG TARGETARCH # toolchain нужен только если prebuilt better-sqlite3 не скачается; в рантайм не попадает RUN apt-get update \ && apt-get install -y --no-install-recommends python3 make g++ ca-certificates \ @@ -31,13 +34,13 @@ RUN --mount=type=cache,id=kvarta-pnpm-slim,target=/pnpm-store \ # оставляем только glibc-бинарник своей архитектуры (linux-x64 для linux/amd64) RUN set -eu; \ bs=$(readlink -f /out/node_modules/better-sqlite3); \ - keep="linux-$(node -p process.arch).node"; \ + case "$TARGETARCH" in amd64) arch=x64 ;; arm64) arch=arm64 ;; *) echo "TARGETARCH=$TARGETARCH?"; exit 1 ;; esac; \ + keep="linux-$arch.node"; \ test -f "$bs/prebuilds/$keep"; \ find "$bs/prebuilds" -type f ! -name "$keep" -delete; \ rm -rf "$bs/deps" "$bs/src" "$bs/build" "$bs/binding.gyp" \ /out/node_modules/.pnpm/node-addon-api@*; \ - find /out/node_modules -name '*.md' -type f -delete; \ - cd /out && node -e "const D=require('better-sqlite3'); const db=new D(':memory:'); console.log('better-sqlite3 ok, sqlite', db.prepare('select sqlite_version() v').get().v); db.close()" + find /out/node_modules -name '*.md' -type f -delete # рантайму не нужны npm/corepack/yarn и документация (~25 МБ); удалить их слоем поверх базы # нельзя — размер не уменьшится, поэтому чистим и сплющиваем базу в один слой через scratch @@ -61,6 +64,8 @@ ENV PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin \ APP_VERSION=${APP_VERSION} WORKDIR /app COPY --from=build --chown=kvarta:kvarta /out ./ +# бинарник целевой платформы реально грузится — проверяем в самом образе +RUN cd /app && node -e "const D=require('better-sqlite3'); new D(':memory:').close()" USER kvarta VOLUME ["/data"] EXPOSE 3000 diff --git a/deploy/Dockerfile.landing b/deploy/Dockerfile.landing index 461ebf9..699dc03 100644 --- a/deploy/Dockerfile.landing +++ b/deploy/Dockerfile.landing @@ -2,7 +2,9 @@ # Сборка из корня репо: # docker buildx build --platform linux/amd64 -f deploy/Dockerfile.landing -t kvarta-landing . -FROM node:22-alpine AS build +# JS собирается нативно на машине сборки: под эмуляцией QEMU next build падает с segfault (SWC). +# Результат сборки платформонезависим, кроме sharp — его ставим отдельно под целевую платформу. +FROM --platform=$BUILDPLATFORM node:22-alpine AS build # corepack из node 22 может не знать ключи свежего pnpm — обновляем его RUN npm install -g corepack@latest >/dev/null && corepack enable ENV NEXT_TELEMETRY_DISABLED=1 @@ -18,7 +20,13 @@ RUN --mount=type=cache,id=kvarta-pnpm-alpine,target=/pnpm-store \ COPY apps/landing apps/landing COPY packages/shared packages/shared RUN pnpm --filter @kvarta/landing build \ - && mkdir -p apps/landing/public + && mkdir -p apps/landing/public \ + && rm -rf apps/landing/.next/standalone/node_modules/.pnpm/@img+sharp-* + +# sharp для next/image под целевую платформу; npm — чистый JS, под эмуляцией работает +FROM node:22-alpine AS sharp +WORKDIR /sharp +RUN npm install --omit=dev --no-audit --no-fund sharp@0.35.5 >/dev/null # рантайму не нужны npm/corepack/yarn (~23 МБ); удалить их слоем поверх базы нельзя — # размер не уменьшится, поэтому чистим и сплющиваем базу в один слой через scratch @@ -34,12 +42,14 @@ ENV PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin \ NODE_ENV=production \ NEXT_TELEMETRY_DISABLED=1 \ PORT=3000 \ - HOSTNAME=0.0.0.0 + HOSTNAME=0.0.0.0 \ + NEXT_SHARP_PATH=/sharp/node_modules/sharp WORKDIR /app # outputFileTracingRoot = корень репо, поэтому server.js лежит в apps/landing/ внутри standalone COPY --from=build --chown=kvarta:kvarta /repo/apps/landing/.next/standalone ./ COPY --from=build --chown=kvarta:kvarta /repo/apps/landing/.next/static ./apps/landing/.next/static COPY --from=build --chown=kvarta:kvarta /repo/apps/landing/public ./apps/landing/public +COPY --from=sharp /sharp/node_modules /sharp/node_modules USER kvarta EXPOSE 3000 CMD ["node", "apps/landing/server.js"]