From 3f8c94c5a30f76afbde5ebcb5b0423fb858c4507 Mon Sep 17 00:00:00 2001 From: Alexander Biraben-Renard Date: Tue, 3 Sep 2024 18:14:08 +0100 Subject: [PATCH] devops: modify GH actions and Dockerfile (#100) - Modify Dockerfile to be faster by not installing Prisma twice and assuming npm - Modify the Dockerfile/GitHub actions workflow to use caching for faster build times - Modify GitHub actions workflow to: - Set the `DATABASE_URL` environment variable properly - Create the upload directories in the volume - Set the EntraID environment variables properly --- .github/workflows/build.yml | 29 ++++++++++++--- Dockerfile | 74 ++++++++++++++----------------------- 2 files changed, 52 insertions(+), 51 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 8b910982..9cf8728f 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -76,8 +76,7 @@ jobs: attestations: write id-token: write steps: - - name: Checkout repository - uses: actions/checkout@v4 + - uses: actions/checkout@v4 - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 # Uses the `docker/login-action` action to log in to the Container registry using the account and password that will publish the packages. Once published, the packages are scoped to the account defined here. @@ -111,7 +110,8 @@ jobs: push: true tags: ${{ steps.meta.outputs.tags }} labels: ${{ steps.meta.outputs.labels }} - no-cache: true + cache-from: type=gha + cache-to: type=gha, mode=max # Deploy! deploy-impaas: @@ -133,9 +133,28 @@ jobs: - name: Deploy to ImPaaS run: | tsuru app deploy -i ghcr.io/imperial/cpp-connect:latest -a cpp-connect + - name: Create upload directories + run: | + tsuru app run "mkdir -p \$UPLOAD_DIR && cd \$UPLOAD_DIR && mkdir -p banners cvs avatars logos attachments" -a cpp-connect + - name: Set database URL + run: | + tsuru app run "DATABASE_URL=postgres://\$PGUSER:\$PGPASSWORD@\$PGHOST:\$PGPORT/\$PGDATABASE && echo \$DATABASE_URL" -a cpp-connect \ + | grep "^postgres://" \ + | xargs -I {} tsuru env set -a cpp-connect DATABASE_URL={} - name: Run migrations run: | - tsuru app run "DATABASE_URL=postgres://\$PGUSER:\$PGPASSWORD@\$PGHOST:\$PGPORT/\$PGDATABASE npm exec prisma migrate deploy" -a cpp-connect + tsuru app run "npm exec prisma migrate deploy" -a cpp-connect - name: Set environment variables run: | - tsuru env set -a cpp-connect NEXTAUTH_URL=${{ vars.NEXTAUTH_URL }} EMAIL_SERVER_USER=${{ secrets.EMAIL_SERVER_USER }} EMAIL_SERVER_PASSWORD=${{ secrets.EMAIL_SERVER_PASSWORD }} EMAIL_SERVER_HOST=${{ secrets.EMAIL_SERVER_HOST }} EMAIL_SERVER_PORT=${{ secrets.EMAIL_SERVER_PORT }} EMAIL_FROM=${{ secrets.EMAIL_FROM }} AUTH_SECRET=${{ secrets.AUTH_SECRET }} AUTH_TRUST_HOST=true + tsuru env set -a cpp-connect \ + NEXTAUTH_URL=${{ vars.NEXTAUTH_URL }} \ + EMAIL_SERVER_USER=${{ secrets.EMAIL_SERVER_USER }} \ + EMAIL_SERVER_PASSWORD=${{ secrets.EMAIL_SERVER_PASSWORD }} \ + EMAIL_SERVER_HOST=${{ secrets.EMAIL_SERVER_HOST }} \ + EMAIL_SERVER_PORT=${{ secrets.EMAIL_SERVER_PORT }} \ + EMAIL_FROM=${{ secrets.EMAIL_FROM }} \ + AUTH_SECRET=${{ secrets.AUTH_SECRET }} \ + AUTH_TRUST_HOST=true \ + MS_ENTRA_CLIENT_ID=${{ secrets.MS_ENTRA_CLIENT_ID }} \ + MS_ENTRA_CLIENT_SECRET=${{ secrets.MS_ENTRA_CLIENT_SECRET }} \ + MS_ENTRA_TENANT_ID=${{ secrets.MS_ENTRA_TENANT_ID }} diff --git a/Dockerfile b/Dockerfile index 8da35529..4178802a 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,60 +1,45 @@ FROM node:18-alpine AS base -# Install dependencies only when needed -FROM base AS deps +FROM base AS app_base + +# Make UPLOAD_DIRs +ENV UPLOAD_DIR=/uploads +RUN mkdir $UPLOAD_DIR +RUN mkdir $UPLOAD_DIR/banners $UPLOAD_DIR/cvs $UPLOAD_DIR/avatars $UPLOAD_DIR/logos $UPLOAD_DIR/attachments + +# Prisma base image only for installing prisma +FROM base AS prisma_base # 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 package-lock.json* ./ +RUN npm install prisma --omit=dev + +FROM prisma_base AS deps +WORKDIR /app -# 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 corepack enable pnpm && pnpm i --frozen-lockfile; \ - else echo "Lockfile not found." && exit 1; \ - fi +# Won't need to re-install prisma, since it's already installed in the prisma_base image +RUN npm ci -# Rebuild the source code only when needed FROM base AS builder WORKDIR /app - -# Add a dummy argument to force rebuild -ARG CACHEBUST=1 COPY --from=deps /app/node_modules ./node_modules COPY . . -# 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 +# Disable telemetry during the build. +ENV NEXT_TELEMETRY_DISABLED 1 -RUN \ - if [ -f yarn.lock ]; then yarn run build; \ - elif [ -f package-lock.json ]; then npm run build; \ - elif [ -f pnpm-lock.yaml ]; then corepack enable pnpm && pnpm run build; \ - else echo "Lockfile not found." && exit 1; \ - fi +RUN npm run build # Production image, copy all the files and run next -FROM base AS runner +FROM app_base AS runner WORKDIR /app -# Make UPLOAD_DIRs -ENV UPLOAD_DIR=/uploads -RUN mkdir $UPLOAD_DIR -RUN mkdir $UPLOAD_DIR/banners $UPLOAD_DIR/cvs $UPLOAD_DIR/avatars $UPLOAD_DIR/logos $UPLOAD_DIR/attachments - -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 nodejs -# RUN adduser --system --uid 1001 nextjs +# Disable telemetry during runtime. +ENV NEXT_TELEMETRY_DISABLED 1 COPY --from=builder /app/public ./public - # Set the correct permission for prerender cache RUN mkdir .next RUN chown node:node .next @@ -62,25 +47,22 @@ RUN chown node:node .next # Copy prisma schema COPY --from=builder --chown=node:node /app/prisma ./prisma +# Copy over the prisma client +COPY --from=prisma_base /app/node_modules ./node_modules + # Automatically leverage output traces to reduce image size # https://nextjs.org/docs/advanced-features/output-file-tracing COPY --from=builder --chown=node:node /app/.next/standalone ./ COPY --from=builder --chown=node:node /app/.next/static ./.next/static - -# Take ownershuip of the app folder & upload +# Take ownership of the app folder and uploads RUN chown node:node /app -RUN chown -R node:node /uploads +RUN chown -R node:node $UPLOAD_DIR USER node -# Install prisma so this user can use it -RUN npm install prisma - EXPOSE 3000 ENV PORT=3000 -# server.js is created by next build from the standalone output -# https://nextjs.org/docs/pages/api-reference/next-config-js/output -CMD HOSTNAME="0.0.0.0" node server.js \ No newline at end of file +CMD HOSTNAME="0.0.0.0" node server.js