diff --git a/.github/workflows/registry-build-push.yml b/.github/workflows/registry-build-push.yml new file mode 100644 index 0000000..9804eb9 --- /dev/null +++ b/.github/workflows/registry-build-push.yml @@ -0,0 +1,51 @@ +name: Build and publish to Github Container Registry + +on: + push: + branches: [main] + tags: ["v*.*.*"] + pull_request: + branches: + - main + +env: + REGISTRY: ghcr.io + IMAGE_NAME: ${{ github.repository }} + +jobs: + build-and-push-images: + runs-on: ubuntu-latest + permissions: + contents: read + packages: write + + steps: + - name: Checkout repository + uses: actions/checkout@v3 + + - name: Log in to the Container registry + uses: docker/login-action@v2 + with: + registry: ${{ env.REGISTRY }} + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Extract metadata (tags, labels) for Docker + id: meta + uses: docker/metadata-action@v4 + with: + images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} + flavor: | + latest=auto + prefix= + suffix= + + - name: Build and push Docker image + uses: docker/build-push-action@v3 + with: + context: . + push: true + build-args: | + DOCKER_TAG=${{ steps.meta.outputs.version }} + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} diff --git a/.github/workflows/registry-pr-purge.yml b/.github/workflows/registry-pr-purge.yml new file mode 100644 index 0000000..2fe72aa --- /dev/null +++ b/.github/workflows/registry-pr-purge.yml @@ -0,0 +1,19 @@ +name: Purge Pull Request Image + +# https://docs.github.com/en/actions/reference/events-that-trigger-workflows#registry_package +# Purge Pull Request Image +on: + pull_request: + types: [closed] + +jobs: + purge_pr_image: + runs-on: ubuntu-latest + steps: + - name: Purge Pull Request Image + uses: vlaurin/action-ghcr-prune@v0.4.0 + with: + token: ${{ secrets.GITHUB_TOKEN}} + organization: ${{ github.repository_owner}} + container: ${{ github.event.repository.name }} + tag-regex: pr-${{github.event.pull_request.number}}$ diff --git a/.github/workflows/registry-purge.yml b/.github/workflows/registry-purge.yml new file mode 100644 index 0000000..eb9588e --- /dev/null +++ b/.github/workflows/registry-purge.yml @@ -0,0 +1,18 @@ +name: Purge untagged images + +# https://docs.github.com/en/actions/reference/events-that-trigger-workflows#registry_package +# Run cleanup job if a new package was published or updated +on: + registry_package: + +jobs: + purge_untagged_images: + runs-on: ubuntu-latest + steps: + - name: clean packages + uses: vlaurin/action-ghcr-prune@v0.4.0 + with: + token: ${{ secrets.GITHUB_TOKEN}} + organization: ${{ github.repository_owner}} + container: ${{ github.event.repository.name }} + untagged: true diff --git a/Dockerfile b/Dockerfile index 18c87fd..a6d1eb7 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,49 +1,69 @@ -#-----------------------------> Base Image -FROM node:18-alpine AS base - -# ---------------------------> Dependency Installation -FROM base AS deps - +# Install dependencies only when needed +FROM node:22-alpine AS deps +# Check https://github.com/nodejs/docker-node/tree/b4117f9333da4138b03a546ec926ef50a31506c3#nodealpine to understand why libc6-compat might be needed. RUN apk add --no-cache libc6-compat WORKDIR /app -COPY package.json yarn.lock* package-lock.json* pnpm-lock.json* ./ +# Install dependencies based on the preferred package manager +COPY package.json yarn.lock* package-lock.json* pnpm-lock.yaml* ./ RUN \ - if [ -f yarn.lock ]; then yarn --frozen-lockfile; \ - elif [ -f package-lock.json ]; then npm ci; \ - elif [ -f pnpm-lock.yaml ]; then yarn global add pnpm && pnpm i --frozen-lockfile; \ - else echo "Lockfile not found." && exit 1; \ - fi - -#-------------------------> Next.JS Build -FROM base as builder + if [ -f yarn.lock ]; then yarn --frozen-lockfile; \ + elif [ -f package-lock.json ]; then npm ci; \ + elif [ -f pnpm-lock.yaml ]; then yarn global add pnpm && pnpm i --frozen-lockfile; \ + else echo "Lockfile not found." && exit 1; \ + fi + + +# Rebuild the source code only when needed +FROM node:18-alpine AS builder WORKDIR /app COPY --from=deps /app/node_modules ./node_modules -COPY . . +COPY . . + +ARG DOCKER_TAG=unset +ENV NEXT_PUBLIC_APP_VERSION=$DOCKER_TAG RUN npx prisma generate +# Next.js collects completely anonymous telemetry data about general usage. +# Learn more here: https://nextjs.org/telemetry +# Uncomment the following line in case you want to disable telemetry during the build. +ENV NEXT_TELEMETRY_DISABLED 1 + +# If using npm comment out above and use below instead +# RUN npm run build RUN yarn build -#-------------------------> Start Next.JS Server -FROM base AS runner +# Production image, copy all the files and run next +FROM node:22-alpine AS runner WORKDIR /app ENV NODE_ENV production +# Uncomment the following line in case you want to disable telemetry during runtime. +ENV NEXT_TELEMETRY_DISABLED 1 -RUN addgroup --system --gid 1001 nextjs +RUN addgroup --system --gid 1001 nodejs RUN adduser --system --uid 1001 nextjs -USER nextjs - COPY --from=builder /app/public ./public +COPY --from=builder /app/entrypoint.sh ./entrypoint.sh +COPY --from=builder /app/prisma ./prisma +COPY --from=builder /app/next.config.mjs ./next.config.mjs +COPY --from=builder /app/package.json ./package.json +RUN chmod +x ./entrypoint.sh +RUN npm install ts-node typescript +# Automatically leverage output traces to reduce image size +# https://nextjs.org/docs/advanced-features/output-file-tracing +COPY --from=builder --chown=nextjs:nodejs /app/.next/ ./.next +# COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static +# COPY --from=builder --chown=nextjs:nodejs /app/.next/server ./.next/server -COPY --from=builder /app/.next/standalone ./ -COPY --from=builder /app/.next/static ./.next/static +USER nextjs -EXPOSE 1000 +EXPOSE 3000 ENV PORT 3000 -ENV HOSTNAME localhost -CMD [ "node", "server.js" ] +ENTRYPOINT [ "/app/entrypoint.sh" ] + +CMD ["npm", "run", "start"] diff --git a/entrypoint.sh b/entrypoint.sh new file mode 100644 index 0000000..7f10608 --- /dev/null +++ b/entrypoint.sh @@ -0,0 +1,16 @@ +#!/bin/sh + +find /app/.next \( -type d -name .git -prune \) -o -type f -print0 | xargs -0 + +if [ "$MIGRATE_DATABASE" = true ] +then + echo "Running database migrations" + npx --yes prisma migrate deploy + npx --yes prisma db seed +else + echo 'No Database migrations will be applied.' + echo 'If there are missing Database migrations set environment variable MIGRATE_DATABASE to true' +fi + +echo "Starting AusReis App" +exec "$@" \ No newline at end of file