What is Fargate ?
Why Next.js on AWS ?
The Next.js documentation says :
The easiest way to deploy Next.js to production is to use the Vercel platform from the creators of Next.js
Well, if you are just getting started with your project, i will say go for Vercel.
But in my case, i had all my projects on AWS using CDK, and i don't wanted to have to manage my Next.js app on another platform.
Let's get started
Let's create the main folder of the project
mkdir nextJsOnAws
cd nextJsOnAws
NextJS part
npx create-next-app
and name it the way you want (i named it front)
We are going to create a Dockerfile ( i am using the official one from the Vercel documentation)
# Install dependencies only when needed
FROM node:alpine AS deps
RUN apk add --no-cache libc6-compat
WORKDIR /app
COPY package.json yarn.lock ./
RUN yarn install --frozen-lockfile
# Rebuild the source code only when needed
FROM node:alpine AS builder
WORKDIR /app
COPY . .
COPY --from=deps /app/node_modules ./node_modules
RUN yarn build && yarn install --production --ignore-scripts --prefer-offline
# Production image, copy all the files and run next
FROM node:alpine AS runner
WORKDIR /app
ENV NODE_ENV production
RUN addgroup -g 1001 -S nodejs
RUN adduser -S nextjs -u 1001
COPY --from=builder /app/public ./public
COPY --from=builder --chown=nextjs:nodejs /app/.next ./.next
COPY --from=builder /app/node_modules ./node_modules
COPY --from=builder /app/package.json ./package.json
USER nextjs
EXPOSE 3000
CMD ["yarn", "start"]
CDK part
Let's create a new CDK project on a dedicated folder
mkdir cdkPart
cd cdkPart
cdk init --language typescript
Then let's install the package we need
npm install @aws-cdk/aws-ec2 @aws-cdk/aws-ecs @aws-cdk/aws-ecs-patterns
In the lib folder, a file was created called cdk_part-stack, open it and complete it like this
import * as cdk from '@aws-cdk/core';
import * as ec2 from "@aws-cdk/aws-ec2";
import * as ecs from "@aws-cdk/aws-ecs";
import * as ecs_patterns from "@aws-cdk/aws-ecs-patterns";
import { DockerImageAsset } from "@aws-cdk/aws-ecr-assets";
export class CdkPartStack extends cdk.Stack {
constructor(scope: cdk.Construct, id: string, props?: cdk.StackProps) {
super(scope, id, props);
const APP_PORT = 3000
const pathToDockerFile = "../front"
const vpc = new ec2.Vpc(this, "MyVpc", {
maxAzs: 2,
});
const taskDefinition = new ecs.FargateTaskDefinition(this, "MyTaskDefinition", {
memoryLimitMiB: 512,
cpu: 256,
});
const dockerFile = new DockerImageAsset(this, 'DockerFileAsset', {
directory: pathToDockerFile,
file: 'Dockerfile',
});
// cdk will build it and push it to en ecr repository
const image = ecs.ContainerImage.fromDockerImageAsset(dockerFile);
const container = taskDefinition.addContainer("MyContainer", {
image,
// store the logs in cloudwatch
logging: ecs.LogDriver.awsLogs({ streamPrefix: "myexample-logs" })
});
container.addPortMappings({
containerPort: APP_PORT,
});
const cluster = new ecs.Cluster(this, "MyECSCluster", {
clusterName: "MyECSCluster",
containerInsights: true,
vpc,
});
const securityGroup = new ec2.SecurityGroup(this, `My-security-group`, {
vpc: vpc,
allowAllOutbound: true,
description: 'My Security Group'
});
securityGroup.addIngressRule(ec2.Peer.anyIpv4(), ec2.Port.tcp(APP_PORT));
const fargateService = new ecs_patterns.ApplicationLoadBalancedFargateService(this, 'MyFargateService', {
cluster,
publicLoadBalancer: true,
cpu: 256,
desiredCount: 1,
memoryLimitMiB: 512,
taskDefinition,
securityGroups: [securityGroup]
})
const scalableTarget = fargateService.service.autoScaleTaskCount({
minCapacity: 1,
maxCapacity: 2
})
scalableTarget.scaleOnCpuUtilization('cpuScaling', {
targetUtilizationPercent: 70
})
}
}
Now time for deploy
cdk synth
Then after that :
cdk deploy
The deploy can be a little long , so be patient :)
Let's go to the console
After the deploy is completed, go to your AWS Console > ECS (for Elastic Container Service)
Click on MyECSCluster
Click on the service
Select the Task Tab
Click on the Task
You can see that your container is ... RUNNING :)
Let's see the app !!!
Go to the console > EC2 > LoadBalancer and copy the DNS name of your load balancer
Paste it in your browser and ...
Congrats ! You deployed your Next.js app with Fargate and it's running :)
Cleaning
Don't forget to clean after this tutorial, i don't want you to have a huge bill on AWS!
cdk destroy
I hope you liked this tutorial, i will try my best to post some articles about AWS.
If you want, you can follow me on Twitter :)
Top comments (2)
Will this work with NextJS SSR ? and how to manage env variables ?
You can add env variables like this :
Honestly, i haven't tried it with SSR, so i cannot give you an answer for that.