-
Notifications
You must be signed in to change notification settings - Fork 0
Next.JS
read
Perfect β using a reverse proxy is an excellent choice for a modular, iframe-free, loosely coupled Next.js monorepo, especially for banking portals where:
- Teams own independent applications (
accounts
,loans
,estimator
) - Apps can scale and deploy independently
- Unified UX can still be achieved via shared design system
User β [ Nginx / Traefik / API Gateway ]
β β
/portal β apps/portal /estimator β apps/estimator
/analysis β apps/analysis
Each app lives in its own folder/repo and gets its own subdomain or route path.
server {
listen 80;
server_name yourbank.com;
location / {
proxy_pass http://localhost:3000; # portal app
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
location /estimator/ {
rewrite ^/estimator(/.*)$ $1 break;
proxy_pass http://localhost:3001; # estimator app
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
location /analysis/ {
rewrite ^/analysis(/.*)$ $1 break;
proxy_pass http://localhost:3002; # analysis app
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}
- Runs:
-
portal
on port 3000 -
estimator
on port 3001 -
analysis
on port 3002
-
- All apps use
basePath
config (see next step)
For apps other than the shell (estimator
, analysis
):
// apps/estimator/next.config.js
/** @type {import('next').NextConfig} */
const nextConfig = {
basePath: '/estimator',
output: 'standalone',
};
module.exports = nextConfig;
apps/
βββ portal/ β basePath: "/"
βββ estimator/ β basePath: "/estimator"
βββ analysis/ β basePath: "/analysis"
Benefit | Why it matters in banking |
---|---|
Independent deployments | You can roll out changes to /loans without affecting /accounts
|
Subdomain or path-based routing | Matches common banking UX patterns |
No iframe required | Full native navigation |
Supports shared auth | Auth cookies/JWT via domain or SSO provider |
Better fault isolation | One app going down doesnβt break others |
- Use shared
auth
package in all apps (e.g.next-auth
or JWT utils) - Add design system as
packages/ui/
to maintain UX consistency - Use basePath-aware links (
<Link href="/estimator/foo">
) and dynamic imports
Certainly! Here's a complete setup for building and deploying individual Next.js applications from a monorepo using Docker. This configuration allows each app to be developed, built, and deployed independently, facilitating a modular and scalable architecture.ξ
ξYour project directory should be organized as followsξξ ξ
monorepo/
βββ apps/
β βββ portal/ # Main shell application
β βββ estimator/ # Estimator application
β βββ analysis/ # Analysis application
βββ packages/
β βββ ui/ # Shared UI components
β βββ auth/ # Shared authentication logic
βββ nginx/
β βββ default.conf # NGINX reverse proxy configuration
βββ docker-compose.yml
βββ turbo.json
βββ package.json
```ξξ
---
## π³ Dockerfile for Each App
ξEach application (`portal`, `estimator`, `analysis`) should have its own `Dockerfile` located in its respective directory. Here's a sample `Dockerfile` using multi-stage builds for optimized production image:ξξ
ξ
```dockerfile
# Stage 1: Build
FROM node:18-alpine AS builder
WORKDIR /app
COPY . .
RUN npm ci
RUN npm run build
# Stage 2: Production
FROM node:18-alpine
WORKDIR /app
COPY --from=builder /app/.next ./.next
COPY --from=builder /app/public ./public
COPY --from=builder /app/package.json ./package.json
RUN npm install --production
EXPOSE 3000
CMD ["npm", "start"]
``
ξξ
ξEnsure that each application's `package.json` includes the necessary script:ξξ
ξ
```json
{
"scripts": {
"dev": "next dev",
"build": "next build",
"start": "next start"
}
}
``
ξξ
---
## βοΈ NGINX Reverse Proxy Configuration
ξThe `nginx/default.conf` file routes incoming requests to the appropriate application based on the URL pat:ξξ
ξ
```nginx
server {
listen 80;
server_name localhost;
location / {
proxy_pass http://portal:3000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
location /estimator/ {
rewrite ^/estimator(/.*)$ $1 break;
proxy_pass http://estimator:3001;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
location /analysis/ {
rewrite ^/analysis(/.*)$ $1 break;
proxy_pass http://analysis:3002;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}
``
ξξ
---
## π³ Docker Compose Configuratio
ξThe `docker-compose.yml` file orchestrates the building and running of all servics:ξ
ξ
```yaml
version: '3.8'
services:
nginx:
image: nginx:latest
volumes:
- ./nginx/default.conf:/etc/nginx/conf.d/default.conf
ports:
- "80:80"
depends_on:
- portal
- estimator
- analysis
portal:
build: ./apps/portal
ports:
- "3000:3000"
estimator:
build: ./apps/estimator
ports:
- "3001:3000"
analysis:
build: ./apps/analysis
ports:
- "3002:3000"
``
ξξ
---
## π Deployment Steps
1. **Build and Start Services*: ξFrom the root of your monorepo, un:ξξ
```bash
docker-compose up --build
``
ξξ
2. **Access Applications**:
- ξMain Portal: [http://localhost/](http://localhot/)ξ
- ξEstimator App: [http://localhost/estimator](http://localhost/estimaor)ξ
- ξAnalysis App: [http://localhost/analysis](http://localhost/analyis)ξξ
---
## π¦ Shared Packaes
ξThe `packages/` directory contains shared modules like `ui` and `auth`. To use these in your applicatons:ξξ
1. **Install Dependencie**: ξEnsure that each app's `package.json` includes the shared packages as dependenies.ξξ
2. **Configure Module Resolutio**: ξUse tools like [Yarn Workspaces](https://classic.yarnpkg.com/en/docs/workspaces/) or [npm Workspaces](https://docs.npmjs.com/cli/v7/using-npm/workspaces) to manage shared packages within the monoepo.ξξ
3. **Import Module**: ξIn your application code, import shared modules as neded:ξξ
```javascript
import { Button } from '@myorg/ui';
import { useAuth } from '@myorg/auth';
read
For building a CI/CD pipeline using AWS to deploy your Next.js multi-app monorepo with Docker, you can leverage AWS CodePipeline and AWS CodeBuild for building, testing, and deploying your applications to services like Amazon ECS, Elastic Beanstalk, or Amazon S3 for static hosting.
Hereβs a step-by-step guide for creating a CI/CD pipeline for your Next.js monorepo:
- AWS Account: Set up AWS services like CodePipeline, CodeBuild, and IAM.
- AWS CLI & AWS CodePipeline Setup: Install and configure the AWS CLI.
- Docker: Your application should be Dockerized (as shown in the previous setup).
- Amazon S3 (for static sites) or Amazon ECS (for containerized apps): You can deploy your apps to either of these services.
- GitHub or AWS CodeCommit: For code repository integration.
-
Create a CodeBuild Project for each app (
portal
,estimator
,analysis
).
For each app, define a buildspec.yml
file in the root directory (for Docker build and deploy). For instance, hereβs a buildspec.yml
for the Portal app:
version: 0.2
phases:
install:
commands:
- echo Installing dependencies...
- npm install
build:
commands:
- echo Building the app...
- npm run build
post_build:
commands:
- echo Build completed on `date`
- docker build -t portal-image .
- $(aws ecr get-login --no-include-email --region us-east-1)
- docker tag portal-image:latest <aws_account_id>.dkr.ecr.us-east-1.amazonaws.com/portal-repo:latest
- docker push <aws_account_id>.dkr.ecr.us-east-1.amazonaws.com/portal-repo:latest
artifacts:
files:
- apps/portal/Dockerfile
- apps/portal/package.json
- apps/portal/next.config.js
For each other app (estimator
, analysis
), create similar buildspec.yml
files that build Docker images and push them to Amazon Elastic Container Registry (ECR).
- Elastic Container Registry (ECR) will store your Docker images.
- Go to the ECR console.
- Create repositories for each app (
portal-repo
,estimator-repo
,analysis-repo
). - Use the provided authentication command from AWS CLI to authenticate Docker to ECR.
- Go to the AWS CodePipeline console.
- Create a new pipeline for each app (or a single pipeline for all apps).
- Source: GitHub or AWS CodeCommit (where your monorepo is hosted).
- Build: Link to the CodeBuild Project you set up earlier for each app.
For ECS (Elastic Container Service) or Elastic Beanstalk, you can define the deploy stage.
- Create an ECS Cluster.
- Define a Task Definition for your containerized apps.
- Set up an ECS Service to run your Docker containers.
- In CodePipeline, set the Deploy stage to deploy to ECS. This will pull the Docker image from ECR and run it on ECS.
Hereβs a simple example of an ECS task definition:
{
"family": "my-app-task",
"containerDefinitions": [
{
"name": "portal-container",
"image": "<aws_account_id>.dkr.ecr.us-east-1.amazonaws.com/portal-repo:latest",
"memory": 512,
"cpu": 256,
"essential": true,
"portMappings": [
{
"containerPort": 3000,
"hostPort": 3000
}
]
}
]
}
- Create an Elastic Beanstalk Application for each app (
portal
,estimator
,analysis
). - Choose Docker as the platform.
- In CodePipeline, set the Deploy stage to deploy to Elastic Beanstalk.
-
Source Stage:
- GitHub / CodeCommit (Repository where your monorepo is hosted).
-
Build Stage (with AWS CodeBuild):
- Builds each appβs Docker image and pushes it to ECR.
-
Deploy Stage (with ECS / Elastic Beanstalk):
- Deploys the app to ECS or Elastic Beanstalk.
You may need environment variables for sensitive data like API keys. Use AWS Secrets Manager or AWS Systems Manager Parameter Store to manage secrets securely.
You can include unit or integration tests in the pipeline before the deployment stage.
For production-grade setups, consider adding an Application Load Balancer (ALB) for routing traffic to ECS containers and enabling auto-scaling.
Once everything is set up, push your code to the repository, and AWS CodePipeline will automatically trigger the pipeline for each app.
- CI/CD for multiple environments (e.g., dev, staging, prod).
- Blue-Green deployment strategy for ECS.
- Monitoring: Use CloudWatch logs and metrics for monitoring the health of your deployments.