diff --git a/Dockerfile b/Dockerfile index 7a1006c..cc9e6b5 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,31 +1,35 @@ -FROM node:20-alpine AS base - -FROM node:20-alpine AS deps -RUN apk add --no-cache libc6-compat -WORKDIR /app -COPY package.json package-lock.json* ./ -RUN npm ci - -FROM node:20-alpine AS builder -WORKDIR /app -COPY --from=deps /app/node_modules ./node_modules -COPY . . -RUN npm run build - -FROM node:20-alpine AS runner -WORKDIR /app +FROM node:20-alpine AS base + +FROM node:20-alpine AS deps +RUN apk add --no-cache libc6-compat +WORKDIR /app +COPY package.json package-lock.json* ./ +RUN npm ci + +FROM node:20-alpine AS builder +WORKDIR /app +COPY --from=deps /app/node_modules ./node_modules +COPY . . +# The commit being built, supplied by Ship. Declared late so the layers above +# stay cached; it is empty for builds that do not pass it. +ARG NEXT_PUBLIC_APP_COMMIT +ENV NEXT_PUBLIC_APP_COMMIT=${NEXT_PUBLIC_APP_COMMIT} +RUN npm run build + +FROM node:20-alpine AS runner +WORKDIR /app ENV NODE_ENV=production - -RUN addgroup --system --gid 1001 nodejs -RUN adduser --system --uid 1001 nextjs - -COPY --from=builder /app/public ./public -COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./ -COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static - -USER nextjs -EXPOSE 3000 + +RUN addgroup --system --gid 1001 nodejs +RUN adduser --system --uid 1001 nextjs + +COPY --from=builder /app/public ./public +COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./ +COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static + +USER nextjs +EXPOSE 3000 ENV PORT=3000 ENV HOSTNAME="0.0.0.0" - + CMD ["node", "server.js"] diff --git a/src/app/layout.tsx b/src/app/layout.tsx index 919075b..222de13 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -8,6 +8,7 @@ import { Toaster } from "@/components/ui/sonner"; import { TooltipProvider } from "@/components/ui/tooltip"; import { ServiceWorkerRegistration } from "@/components/service-worker-registration"; import { ThemeBootstrapScript } from "@/components/theme-bootstrap"; +import { BuildStamp } from "@/components/build-stamp"; // Fonts are self-hosted from ./fonts (Latin subsets of the Google Fonts // files, downloaded 2026-10-20). With next/font/google every build fetched @@ -197,6 +198,7 @@ export default function RootLayout({ children }: { children: React.ReactNode }) {children} + diff --git a/src/components/build-stamp.tsx b/src/components/build-stamp.tsx new file mode 100644 index 0000000..be90fc3 --- /dev/null +++ b/src/components/build-stamp.tsx @@ -0,0 +1,32 @@ +/** + * The commit this build came from, as a faint mark in the corner. + * + * `NEXT_PUBLIC_APP_COMMIT` is set by Ship (the Forgejo Desktop app) when it + * builds the image. A build made any other way has no value, so nothing is + * rendered. It never takes a click and is nearly transparent. + */ +export function BuildStamp() { + const commit = process.env.NEXT_PUBLIC_APP_COMMIT; + if (!commit) return null; + + return ( + + ); +}