Here's a comprehensive guide to deploying a Node.js application in a Docker container with AWS Lambda and exposing it via API Gateway. This approach leverages Docker for packaging the Node.js application, Lambda for serverless execution, and API Gateway for handling requests and serverless framework to deploy above services into AWS account through Github Actions.
File structure
├── Dockerfile
├── controller
├── docker-compose.yml
├── environment.py
├── lambda.js
├── layer.sh
├── middleware
├── models
├── node_modules
├── output
├── package.json
├── routes
├── server.js
├── serverless.yml
├── uploads
└── utils
Dockerfile
FROM public.ecr.aws/lambda/nodejs:20
COPY package.json ${LAMBDA_TASK_ROOT}
RUN npm install --production
COPY . ${LAMBDA_TASK_ROOT}
COPY lambda.js ${LAMBDA_TASK_ROOT}
CMD ["lambda.handler"]
lambda.js
import serverlessExpress from 'aws-serverless-express';
import app from './server.js';
const server = serverlessExpress.createServer(app);
export const handler = (event, context) => {
return serverlessExpress.proxy(server, event, context);
};
server.js
import express from 'express';
import userRouter from './routes/userRoutes.js'
import cors from 'cors';
const app = express()
const PORT = 3000;
app.use(cors());
app.use(express.json({ limit: '100mb' }));
app.use(express.urlencoded({ limit: '100mb', extended: true }));
app.use('/user', userRouter);
export default app;
serverless.yml
service: backend
frameworkVersion: '3'
provider:
name: aws
runtime: nodejs18.x
region: us-east-1
timeout: 900
memorySize: 128
vpc:
securityGroupIds:
- sg-group-id
subnetIds:
- subnet-id-1
- subnet-id-2
iam:
role:
statements:
- Effect: 'Allow'
Action:
- 'lambda:InvokeFunction'
- 'lambda:GetFunction'
- 'lambda:ListFunction'
- 'lambda:CreateEventSourceMapping'
- 'lambda:GetEventSourceMapping'
- 'lambda:ListEventSourceMappings'
- 'lambda:UpdateEventSourceMapping'
- 'iam:DetachRolePolicy'
- 'iam:getRolePolicy'
Resource: '*'
- Effect: 'Allow'
Action:
- 'logs:*'
- 'ec2:DescribeInstances'
- 'ec2:CreateNetworkInterface'
- 'ec2:AttachNetworkInterface'
- 'ec2:DescribeNetworkInterfaces'
- 'ec2:DeleteNetworkInterface'
- 'ec2:DetachNetworkInterface'
- 'ec2:AssignPrivateIpAddresses'
- 'ec2:UnassignPrivateIpAddresses'
Resource:
- '*'
- Effect: 'Allow'
Action:
- 'secretsmanager:GetSecretValue'
- 'secretsmanager:ListSecrets'
- 'secretsmanager:GetResourcePolicy'
Resource:
- '*'
- Effect: 'Allow'
Action:
- 'geo:SearchPlaceIndexForText'
- 'geo:SearchPlaceIndexForPosition'
Resource:
- '*'
# Allow x-ray-tracing
- Effect: 'Allow' # xray permissions (required)
Action:
- 'xray:PutTraceSegments'
- 'xray:PutTelemetryRecords'
Resource:
- '*'
- Effect: 'Allow'
Action:
- 'sns:Publish'
Resource:
- '*'
- Effect: 'Allow'
Action:
- 's3:ListBucket'
- 's3:GetObject'
Resource:
- '*'
- Effect: 'Allow'
Action:
- 'sqs:*'
Resource:
- "*"
apiGateway:
apiKeys:
- firstapikey
plugins:
- serverless-plugin-log-retention
custom:
logRetentionInDays: 7
package:
exclude:
- node_modules/**
- layers/**
functions:
api:
name: backend
image: ${aws:accountId}.dkr.ecr.${self:provider.region}.amazonaws.com/backend:latest
events:
- http:
path: /{proxy+}
method: any
github actions file
name: Deploy backend
on:
push:
branches:
- development
jobs:
deploy:
runs-on: ubuntu-latest
permissions:
id-token: write
contents: read
steps:
- name: Check out the repository
uses: actions/checkout@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
- name: Configure AWS credentials using OIDC
uses: aws-actions/configure-aws-credentials@v2
with:
role-to-assume: ${{ secrets.AWS_ROLE_ARN }}
aws-region: us-east-1
- name: Login to Amazon ECR
id: login-ecr
uses: aws-actions/amazon-ecr-login@v1
- name: Build, tag, and push image to ECR
env:
AWS_ACCOUNT_ID: ${{ secrets.AWS_ACCOUNT_ID }}
ECR_REGISTRY: ${{ secrets.AWS_ACCOUNT_ID }}.dkr.ecr.us-east-1.amazonaws.com
ECR_REPOSITORY: backend
IMAGE_TAG: latest
run: |
docker build -t $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG .
docker push $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG
- name: Install Dependencies
run: |
npm install -g serverless@3
npm install serverless-plugin-log-retention --save-dev
- name: serverless deploy
uses: serverless/github-action@v3.2
with:
args: deploy --stage prod --config serverless.yml
Top comments (0)