Files
my-protfolio/Dockerfile
Amirhossein Khalili 15ae6b77c6
Some checks failed
Test and deploy / Verify production build (push) Has been cancelled
fix: retain Sharp shared libraries in the runtime image
Copy the complete source-built Sharp package and the shared-library closure resolved in the working verification stage into the final image. Keep the change after application verification so existing compilation layers remain cacheable.

No manual checks or verification run, as requested.
2026-09-15 23:43:02 +03:30

98 lines
4.1 KiB
Docker

# syntax=docker/dockerfile:1.7
FROM node:22-alpine AS image-runtime
# Distribution libraries support baseline CPUs and dispatch optional SIMD at runtime.
RUN apk add --no-cache glib expat libjpeg-turbo libpng libwebp tiff lcms2 librsvg libstdc++
FROM image-runtime AS image-build
RUN apk add --no-cache python3 make g++ meson ninja pkgconf xz \
glib-dev expat-dev libjpeg-turbo-dev libpng-dev libwebp-dev tiff-dev lcms2-dev librsvg-dev
ADD --checksum=sha256:3c41e1d5458081bfa4a5bc54e116c46259c75c6760a18027764555632b9dda3e https://github.com/libvips/libvips/releases/download/v8.18.6/vips-8.18.6.tar.xz /tmp/vips.tar.xz
RUN if [ "$(uname -m)" = x86_64 ]; then export CFLAGS='-O2 -march=x86-64 -mtune=generic' CXXFLAGS='-O2 -march=x86-64 -mtune=generic'; fi \
&& mkdir /tmp/vips && tar -xJf /tmp/vips.tar.xz -C /tmp/vips --strip-components=1 \
&& meson setup /tmp/vips/build /tmp/vips --prefix=/opt/vips --libdir=lib \
--buildtype=release --auto-features=disabled \
-Dhighway=disabled -Dorc=disabled -Dcplusplus=true -Dexamples=false \
-Djpeg=enabled -Dpng=enabled -Dwebp=enabled -Dtiff=enabled -Dlcms=enabled -Drsvg=enabled -Dzlib=enabled \
&& meson compile -C /tmp/vips/build -j 2 \
&& meson install -C /tmp/vips/build
FROM image-build AS dependencies
WORKDIR /app
ARG NPM_REGISTRY=https://package-mirror.liara.ir/repository/npm/
ENV NEXT_TELEMETRY_DISABLED=1 \
PKG_CONFIG_PATH=/opt/vips/lib/pkgconfig \
LD_LIBRARY_PATH=/opt/vips/lib \
npm_config_nodedir=/usr/local
COPY package.json package-lock.json ./
RUN --mount=type=cache,id=portfolio-npm-node22,target=/root/.npm,sharing=locked \
npm ci \
--registry="${NPM_REGISTRY}" \
--replace-registry-host=registry.npmjs.org \
--include=optional
# Compile Sharp against our baseline libvips, not its x86-64-v2 prebuilt binary.
RUN if [ "$(uname -m)" = x86_64 ]; then export CFLAGS='-O2 -march=x86-64 -mtune=generic' CXXFLAGS='-O2 -march=x86-64 -mtune=generic'; fi \
&& npm explore sharp -- npm run build
COPY scripts/check-image-runtime.mjs ./scripts/check-image-runtime.mjs
RUN node scripts/check-image-runtime.mjs --require-source
FROM dependencies AS verification
COPY . .
RUN npm run lint
RUN npm run typecheck
RUN --mount=type=cache,id=portfolio-next-node22,target=/app/.next/cache,sharing=locked \
npm run build
RUN npm test
# Carry the exact shared-library dependency closure from the working build stage.
# Development packages can provide libraries that are absent from image-runtime.
FROM verification AS native-runtime-libraries
RUN mkdir -p /runtime-libs \
&& (ldd /app/node_modules/sharp/src/build/Release/*.node /opt/vips/lib/libvips*.so* 2>/dev/null || true) \
| awk '/=> \// { print $3 } /^[[:space:]]*\// { print $1 }' \
| sort -u \
| while IFS= read -r library; do \
mkdir -p "/runtime-libs$(dirname "$library")"; \
cp -L "$library" "/runtime-libs$library"; \
done
FROM image-runtime AS runtime
WORKDIR /app
ENV NODE_ENV=production \
NEXT_TELEMETRY_DISABLED=1 \
HOSTNAME=0.0.0.0 \
PORT=3000 \
DATA_DIR=/data \
LD_LIBRARY_PATH=/opt/vips/lib
RUN addgroup --system --gid 1001 nodejs \
&& adduser --system --uid 1001 nextjs
COPY --from=verification --chown=nextjs:nodejs /app/.next/standalone ./
COPY --from=verification --chown=nextjs:nodejs /app/.next/static ./.next/static
COPY --from=verification --chown=nextjs:nodejs /app/public ./public
COPY --from=image-build /opt/vips/lib /opt/vips/lib
# Preserve the package and its native dependency closure beyond Next's tracing.
COPY --from=dependencies --chown=nextjs:nodejs /app/node_modules/sharp/ ./node_modules/sharp/
COPY --from=native-runtime-libraries /runtime-libs/ /
COPY scripts/check-image-runtime.mjs ./scripts/check-image-runtime.mjs
RUN node scripts/check-image-runtime.mjs --require-source
RUN mkdir -p .next/cache /data && chown -R nextjs:nodejs .next/cache /data
USER nextjs
EXPOSE 3000
HEALTHCHECK --interval=2s --timeout=2s --start-period=3s --retries=30 \
CMD ["node", "-e", "fetch('http://127.0.0.1:3000/api/health').then(r=>{if(!r.ok)process.exit(1)}).catch(()=>process.exit(1))"]
CMD ["node", "server.js"]