An invoice generator app built using Next.js, Typescript, and Shadcn
docker pull al1abb/invoify:latest
docker run -d --name invoify -p 3000:3000 --restart always al1abb/invoify:latest
podman run -d --name invoify -p 3000:3000 --restart always al1abb/invoify:latest
skopeo inspect docker://docker.io/al1abb/invoify:latest
oras pull al1abb/invoify:latest
FROM node:22-alpine AS build
WORKDIR /app
# `npm ci` installs exactly what package-lock.json pins, so image builds are
# reproducible โ `npm install` was free to resolve newer versions.
COPY package.json package-lock.json ./
RUN npm ci
COPY . .
RUN npm run build
# Drop dev-only packages before they are copied into the runtime image. The
# `puppeteer` devDependency bundles its own Chromium (hundreds of MB) that
# production never uses โ production runs puppeteer-core with
# @sparticuz/chromium.
RUN npm prune --omit=dev
FROM node:22-alpine AS production
WORKDIR /app
ENV NODE_ENV=production
# Chromium needs these at runtime; the Alpine base does not ship them.
RUN apk add --no-cache \
chromium \
nss \
freetype \
harfbuzz \
ca-certificates \
ttf-freefont
RUN addgroup --system --gid 1001 nodejs
RUN adduser --system --uid 1001 nextjs
COPY --from=build --chown=nextjs:nodejs /app/.next ./.next
COPY --from=build --chown=nextjs:nodejs /app/node_modules ./node_modules
COPY --from=build --chown=nextjs:nodejs /app/package.json ./package.json
COPY --from=build --chown=nextjs:nodejs /app/public ./public
USER nextjs
EXPOSE 3000
CMD ["npm", "start"]