Production NextJS deployment with ECS and CDK
Learn how to deploy NextJS app for production and additional environments using containers.
Using CDK
CDK has so-called ECS patterns that allow you to configure everything from DNS and HTTPS records to multiple containers in one go.
It is even one of the top recommended setups on the CDK developer guide.
It is also a good fit for NextJS deployments, since it is a Docker-deployment scenario as shown in NextJS docs.
CDK script
CDK is a relatively new way of creating infrastructure by writing it as a code. This gives you great flexibility and you can create one single script to deploy all types of environments — development, staging and production.
Learn more about CDK here:
With a recent CDK 2.0 release, it is even easier to deploy with minimum dependencies. Here is the example which deploys fully fledged NextJS app in a one go.
To make things more practical, some parts of the cloud environment are created manually (our using other tools, such as Terraform).
This way, network and base infrastructure stays the same even if you remove environment afterwards.
To use it, you should create beforehand in AWS:
- VPC — this configured per environment (production, development or staging)
- Route53 Zone and zone certificate (to automatically register <environment>.example.com hostname and setup SSL loadbalancer)
- ECR — Docker container image registry, to keep latest and previous images
- Docker image — For NextJS you need to bake the environment variables into the image (see Dockerfile)
- LogGroup — to keep logs even when you remove the environment.
Check out the build script in https://gist.github.com/huksley/746665004649c3ed3536fc0bd12650ec which helps you create necessary resourcess.
Good things about CDK
- “Stacks” (for example single environment for the app) — are configurable as you can see fit. You can also override some of the configuration by plugging into the instances it creates.
- You can use existing resources easily. For example, creating a new VPC for every environment does not make sense.
- All logs end up in a single AWS CloudWatch log group for a single deployment.
- Simple IAM setup to give access to deployment from GitHub actions. You just need to give a right to assume the role for CDK-generated roles. CDK also guards against so-called permissions broadening, so initial environment deployment is done locally, and after that, it deploys automatically.
- Support for multiple environments (so you can have an isolated environment for a branch preview)
Important notes about CDK
- Surprisingly, setting up a container healthcheck is a hack — you can have a healthcheck for a load balancer, but not for a container. Issue tracked here.
- CDK uses CloudFormation under the hood. It might be slow. I get around 12 minutes for fully new environment deployment.
- To scale, you need to change configuration and run deployment again.
- Every environment incurs fixed costs because of the application load balancer working 24x7 plus Fargate containers cost.
- Additionally layer caching for a faster multi-stage build is a bit of a mess.
Combining CDK and Docker together
Before you can execute CDK, you need to create docker image in a local environment, and push it to ECR.
See https://gist.github.com/huksley/746665004649c3ed3536fc0bd12650ec for example deployment script and you can use Dockerfile from official NextJS example.
Conclusion
With this configuration, you can have app.example.com, dev.example.com and any other environments automatically deployed.