Avoiding Common Pitfalls: Deploying Node.js Backends to AWS Lambda with Docker & Serverless on macOS
Deploying a Node.js (NestJS) backend to AWS Lambda using Docker and the Serverless Framework can be a smooth experience—if you know what to watch out for. On macOS, especially with Apple Silicon, there are unique challenges that can trip up even experienced developers. Here's a practical guide to the most common pitfalls and how to avoid them, based on real-world troubleshooting.
1. Global Package Permissions: Never Use sudo
with Serverless
Pitfall: Installing Serverless Framework globally with sudo
(sudo npm i -g serverless
) can cause permission errors, making it impossible to update or remove packages later.
Solution:
- Always install Serverless globally without
sudo
:
npm install -g serverless
- Or use a Node version manager (like
nvm
) for even more control.
2. Base Image Confusion: Use the AWS Lambda Base Image
Pitfall: Using a standard Node.js image (e.g., node:20-alpine
) instead of the AWS Lambda base image leads to entrypoint errors like:
Error: fork/exec /usr/local/bin/docker-entrypoint.sh: exec format error
Solution:
- Always use the AWS Lambda base image:
FROM public.ecr.aws/lambda/nodejs:20
...
CMD [ "dist/lambda.handler" ]
- This ensures Lambda can find and invoke your handler correctly.
3. Handler Syntax: CMD Must Match Lambda's Expectations
Pitfall: Using the wrong CMD in your Dockerfile, such as CMD ["node", "dist/lambda.js"]
, will break Lambda's invocation process.
Solution:
- Use the format
CMD [ "<file>.<exported function>" ]
(e.g.,CMD [ "dist/lambda.handler" ]
). - Make sure your built JS file exports the handler as
exports.handler
.
4. Architecture Mismatches: Build for linux/amd64
Pitfall: On Apple Silicon (M1/M2), Docker may build images for arm64
by default, but AWS Lambda requires amd64
(x86_64). This leads to manifest errors or runtime failures.
Solution:
- Always build with:
docker buildx build --platform linux/amd64 -t lambda-img:latest --load .
- Check your image manifest to ensure only
amd64
is present.
5. CORS Configuration: Place It in the Right Spot
Pitfall: Defining CORS under each function event in serverless.yml
(as you might with REST API) will cause configuration errors with HTTP API.
Solution:
- Place CORS configuration under
provider.httpApi
:
provider:
httpApi:
cors:
allowedOrigins:
- "*"
allowedHeaders:
- "*"
allowedMethods:
- "*"
6. Manifest Bloat: Clean Up Before Rebuilding
Pitfall: Docker image manifests may accumulate unwanted architectures (unknown
, arm64
) if you don't clean up before rebuilding, leading to Lambda deployment failures.
Solution:
- Regularly prune Docker images and cache:
docker system prune -af
docker rmi $(docker images -q) || true
7. Debugging: Always Check CloudWatch Logs
Pitfall: Many Lambda errors (handler not found, runtime errors) are only visible in CloudWatch logs.
Solution:
- After each deployment, check CloudWatch logs for your Lambda function to quickly identify and resolve issues.
Final Thoughts
Deploying with Docker and Serverless on macOS is powerful, but requires attention to detail. By following these best practices and learning from common mistakes, you'll save hours of frustration and ensure your backend runs smoothly on AWS Lambda.
Happy deploying!
Top comments (0)