diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..18e82b1 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,53 @@ +# Base stage (common for both development and production) +FROM node:lts-alpine AS base + +WORKDIR /usr/src/app + +# Copy package.json and package-lock.json first (better layer caching) +COPY package*.json ./ + +# Install dependencies using npm ci +RUN npm ci + +# Copy the rest of the application code +COPY . . + +# Development stage +FROM base AS dev + +# Expose the port for development +EXPOSE 3000 + +# Start the Next.js app in development mode +CMD ["npm", "run", "dev"] + +# Build stage (for production) +FROM base AS builder + +# Build the Next.js app +RUN npm run build + +# Production stage +FROM node:lts-alpine AS runner + +WORKDIR /usr/src/app + +# Install only production dependencies +COPY --from=builder /usr/src/app/package*.json ./ +RUN npm ci --omit=dev + +# Copy the built app from the build stage +COPY --from=builder /usr/src/app/.next ./.next +# COPY --from=builder /usr/src/app/public ./public +COPY --from=builder /usr/src/app/next.config.mjs ./ +COPY --from=builder /usr/src/app/vercel.json ./ +COPY --from=builder /usr/src/app/.env ./.env + +# Set the environment variable to production +ENV NODE_ENV=production + +# Expose the port for production +EXPOSE 3000 + +# Run the Next.js app in standalone production mode +CMD ["npm", "run", "start"] diff --git a/README.md b/README.md index 1e0b685..db0d80c 100644 --- a/README.md +++ b/README.md @@ -75,6 +75,27 @@ LoanManagement implements a comprehensive RBAC system: 6. Open [http://localhost:3000](http://localhost:3000) in your browser to see the application. +## Getting Started with Docker + +Ensure you have the [Docker](https://docs.docker.com/get-docker/) installed + +- Build the image for development: + + ```bash + docker build --target dev -t loan_dev . + ``` +- Start the container for development: + ```bash + docker run -p 3000:3000 --env-file .env loan_dev + ``` +- Build the image for production: + ```bash + docker build --target runner -t loan_prod . + ``` +- Start the container for production: + ```bash + ddocker run -p 3000:3000 --env-file .env loan_prod + ``` ## Deployment This application can be easily deployed on Vercel, the platform created by the creators of Next.js. For other deployment options, refer to the [Next.js deployment documentation](https://nextjs.org/docs/deployment). diff --git a/package-lock.json b/package-lock.json index b811795..37427fd 100644 --- a/package-lock.json +++ b/package-lock.json @@ -60,10 +60,12 @@ } }, "node_modules/@auth/core": { - "version": "0.35.0", - "resolved": "https://registry.npmjs.org/@auth/core/-/core-0.35.0.tgz", - "integrity": "sha512-XvMALiYn5ZQd1hVeG1t+jCU89jRrc7ortl/05wkBrPHnRWZScxAK5jKuzBz+AOBQXewDjYcMpzeF5tTqg6rDhQ==", + "version": "0.34.2", + "resolved": "https://registry.npmjs.org/@auth/core/-/core-0.34.2.tgz", + "integrity": "sha512-KywHKRgLiF3l7PLyL73fjLSIBe1YNcA6sMeew4yMP6cfCWGXZrkkXd32AjRi1hlJ9nvovUBGZHvbn+LijO6ZeQ==", "license": "ISC", + "optional": true, + "peer": true, "dependencies": { "@panva/hkdf": "^1.1.1", "@types/cookie": "0.6.0", @@ -90,18 +92,69 @@ } } }, + "node_modules/@auth/core/node_modules/cookie": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz", + "integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==", + "license": "MIT", + "optional": true, + "peer": true, + "engines": { + "node": ">= 0.6" + } + }, "node_modules/@auth/prisma-adapter": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/@auth/prisma-adapter/-/prisma-adapter-2.5.0.tgz", - "integrity": "sha512-A+sd+mqV+7i9a5FcP9oZSIJTBHsidd5xA0abGSaAeek8OaA1LebbX20kjggFRIeP/UlKiQERXar/e1Q4mJjp/w==", + "version": "2.7.2", + "resolved": "https://registry.npmjs.org/@auth/prisma-adapter/-/prisma-adapter-2.7.2.tgz", + "integrity": "sha512-orznIVt6aQMoJ4/rfWFSpRPU8LoZn6jVtDuEkZgLud2xSnCalq6x+hX+rqlk4E5LM13NW1GIJojOPQnM4aM4Gw==", "license": "ISC", "dependencies": { - "@auth/core": "0.35.0" + "@auth/core": "0.37.2" }, "peerDependencies": { "@prisma/client": ">=2.26.0 || >=3 || >=4 || >=5" } }, + "node_modules/@auth/prisma-adapter/node_modules/@auth/core": { + "version": "0.37.2", + "resolved": "https://registry.npmjs.org/@auth/core/-/core-0.37.2.tgz", + "integrity": "sha512-kUvzyvkcd6h1vpeMAojK2y7+PAV5H+0Cc9+ZlKYDFhDY31AlvsB+GW5vNO4qE3Y07KeQgvNO9U0QUx/fN62kBw==", + "license": "ISC", + "dependencies": { + "@panva/hkdf": "^1.2.1", + "@types/cookie": "0.6.0", + "cookie": "0.7.1", + "jose": "^5.9.3", + "oauth4webapi": "^3.0.0", + "preact": "10.11.3", + "preact-render-to-string": "5.2.3" + }, + "peerDependencies": { + "@simplewebauthn/browser": "^9.0.1", + "@simplewebauthn/server": "^9.0.2", + "nodemailer": "^6.8.0" + }, + "peerDependenciesMeta": { + "@simplewebauthn/browser": { + "optional": true + }, + "@simplewebauthn/server": { + "optional": true + }, + "nodemailer": { + "optional": true + } + } + }, + "node_modules/@auth/prisma-adapter/node_modules/oauth4webapi": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/oauth4webapi/-/oauth4webapi-3.1.1.tgz", + "integrity": "sha512-0h4FZjsntbKQ5IHGM9mFT7uOwQCRdcTG7YhC0xXlWIcCch24wUa6Vggaipa3Sw6Ab7nEnmO4rctROmyuHBfP7Q==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/panva" + } + }, "node_modules/@babel/runtime": { "version": "7.25.6", "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.25.6.tgz", @@ -2385,9 +2438,9 @@ } }, "node_modules/cookie": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz", - "integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==", + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.1.tgz", + "integrity": "sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==", "license": "MIT", "engines": { "node": ">= 0.6" @@ -3379,9 +3432,9 @@ } }, "node_modules/express": { - "version": "4.21.0", - "resolved": "https://registry.npmjs.org/express/-/express-4.21.0.tgz", - "integrity": "sha512-VqcNGcj/Id5ZT1LZ/cfihi3ttTn+NJmkli2eZADigjq29qTlWi/hAQ43t/VLPq8+UX06FCEx3ByOYet6ZFblng==", + "version": "4.21.1", + "resolved": "https://registry.npmjs.org/express/-/express-4.21.1.tgz", + "integrity": "sha512-YSFlK1Ee0/GC8QaO91tHcDxJiE/X4FbpAyQWkxAvG6AXCuR65YzK8ua6D9hvi/TzUfZMpc+BwuM1IPw8fmQBiQ==", "license": "MIT", "dependencies": { "accepts": "~1.3.8", @@ -3389,7 +3442,7 @@ "body-parser": "1.20.3", "content-disposition": "0.5.4", "content-type": "~1.0.4", - "cookie": "0.6.0", + "cookie": "0.7.1", "cookie-signature": "1.0.6", "debug": "2.6.9", "depd": "2.0.0", @@ -4682,9 +4735,9 @@ } }, "node_modules/jose": { - "version": "5.9.2", - "resolved": "https://registry.npmjs.org/jose/-/jose-5.9.2.tgz", - "integrity": "sha512-ILI2xx/I57b20sd7rHZvgiiQrmp2mcotwsAH+5ajbpFQbrYVQdNHYlQhoA5cFb78CgtBOxtC05TeA+mcgkuCqQ==", + "version": "5.9.4", + "resolved": "https://registry.npmjs.org/jose/-/jose-5.9.4.tgz", + "integrity": "sha512-WBBl6au1qg6OHj67yCffCgFR3BADJBXN8MdRvCgJDuMv3driV2nHr7jdGvaKX9IolosAsn+M0XRArqLXUhyJHQ==", "license": "MIT", "funding": { "url": "https://github.com/sponsors/panva" @@ -5338,9 +5391,9 @@ } }, "node_modules/next-auth": { - "version": "4.24.7", - "resolved": "https://registry.npmjs.org/next-auth/-/next-auth-4.24.7.tgz", - "integrity": "sha512-iChjE8ov/1K/z98gdKbn2Jw+2vLgJtVV39X+rCP5SGnVQuco7QOr19FRNGMIrD8d3LYhHWV9j9sKLzq1aDWWQQ==", + "version": "4.24.8", + "resolved": "https://registry.npmjs.org/next-auth/-/next-auth-4.24.8.tgz", + "integrity": "sha512-SLt3+8UCtklsotnz2p+nB4aN3IHNmpsQFAZ24VLxGotWGzSxkBh192zxNhm/J5wgkcrDWVp0bwqvW0HksK/Lcw==", "license": "ISC", "dependencies": { "@babel/runtime": "^7.20.13", @@ -5354,12 +5407,16 @@ "uuid": "^8.3.2" }, "peerDependencies": { + "@auth/core": "0.34.2", "next": "^12.2.5 || ^13 || ^14", "nodemailer": "^6.6.5", "react": "^17.0.2 || ^18", "react-dom": "^17.0.2 || ^18" }, "peerDependenciesMeta": { + "@auth/core": { + "optional": true + }, "nodemailer": { "optional": true } @@ -5530,10 +5587,12 @@ "license": "MIT" }, "node_modules/oauth4webapi": { - "version": "2.15.0", - "resolved": "https://registry.npmjs.org/oauth4webapi/-/oauth4webapi-2.15.0.tgz", - "integrity": "sha512-6nZnlxj6M3LeVrxB7bgxwY8hq0B5Quemxhbw85evRlK70qCCUm9O1s47AepSmgYUbkwLTFedP1DZ1eBUIKyRSw==", + "version": "2.17.0", + "resolved": "https://registry.npmjs.org/oauth4webapi/-/oauth4webapi-2.17.0.tgz", + "integrity": "sha512-lbC0Z7uzAFNFyzEYRIC+pkSVvDHJTbEW+dYlSBAlCYDe6RxUkJ26bClhk8ocBZip1wfI9uKTe0fm4Ib4RHn6uQ==", "license": "MIT", + "optional": true, + "peer": true, "funding": { "url": "https://github.com/sponsors/panva" }