Key Takeaways
Enhanced Development Efficiency: Most developers don’t realize how much time gets wasted chasing bugs that only show up in production. Dockerizing your Lambda functions lets you run the same environment on your laptop that runs on AWS — which means what you test locally is genuinely what ships. Faster cycles, less guesswork, more control.
Versatile Integration: This isn’t a niche solution built for one type of project. Healthcare platforms, fintech products, mobile backends, QA pipelines — Dockerized Lambda slots into all of it without friction. The foundation it creates is consistent enough to hold up across very different development contexts.
Improved Flexibility and Security: When your Lambda code lives inside a Docker container, you’re not just getting portability — you’re getting a locked, reproducible environment. That consistency directly translates into better security posture and way less “it worked yesterday” energy from your team.
Overview
Dockerized Lambda function is a technique that involves packaging serverless applications into Docker containers, granting developers more control over the execution environment.
Lambda functions, typically executed on managed infrastructure like AWS Lambda, find enhanced flexibility through Dockerization. This technique is particularly beneficial for healthcare custom software development and cross-platform mobile app development services — environments where a gap between dev and prod isn’t just inconvenient, it erodes trust in the entire system.
Furthermore, Dockerizing Lambda functions facilitates QA software testing services and supports Android app development companies and iOS development services. It empowers banking software development companies and custom enterprise software development by offering a consistent environment for development and deployment — one that doesn’t shift depending on who’s running the code or where.
Planning to Create Dockerized Lambda
- Creating application files and a Dockerfile within them
- Creating ECR, and Building docker image, and pushing it to ECR
- Creating a Lambda function through an ECR Image
- Creating triggers for Lambda in the form of APIs through AWS API Gateway
- Deploy the APIs and test the APIs
Step 1 : Creating Application Files and Dockerfile Within It
Create the index.js file with the struct of a lambda and leverage the event object to get path, protocol, and type of API (POST, GET, PATCH, DELETE).
Create Dockerfile - the files to be copied will be kept in the directory /var/task/ as the AWS Lambda expects them to be there. Here is a sample of the Docker file:
FROM public.ecr.aws/lambda/nodejs:14
COPY index.js package.json package-lock.json /var/task/
RUN npm install --production
CMD ["index.handler"]
Here is the index.js file. Here we are using DynamoDB for CRUD in order to avoid DB connection logic for SQL DB and focus on architectural steps.
const AWS = require('aws-sdk');
AWS.config.update( {
region: 'ap-south-1'
});
const dynamodb = new AWS.DynamoDB.DocumentClient();
const dynamodbTableName = 'product-inventory';
const healthPath = '/health';
const productPath = '/product';
const productsPath = '/products';
exports.handler = async function(event) {
console.log('Request event: ', event);
let response;
switch(true) {
case event.httpMethod === 'GET' && event.path === healthPath:
response = buildResponse(200);
break;
case event.httpMethod === 'GET' && event.path === productPath:
response = await getProduct(event.queryStringParameters.productId);
break;
case event.httpMethod === 'GET' && event.path === productsPath:
response = await getProducts();
break;
case event.httpMethod === 'POST' && event.path === productPath:
response = await saveProduct(JSON.parse(event.body));
break;
case event.httpMethod === 'PATCH' && event.path === productPath:
const requestBody = JSON.parse(event.body);
response = await modifyProduct(requestBody.productId, requestBody.updateKey, requestBody.updateValue);
break;
case event.httpMethod === 'DELETE' && event.path === productPath:
response = await deleteProduct(JSON.parse(event.body).productId);
break;
default:
response = buildResponse(404, '404 Not Found');
}
return response;
}
async function getProduct(productId) {
const params = {
TableName: dynamodbTableName,
Key: {
'productId': productId
}
}
return await dynamodb.get(params).promise().then((response) => {
return buildResponse(200, response.Item);
}, (error) => {
console.error('Do your custom error handling here. I am just gonna log it: ', error);
});
async function getProducts() {
const params = {
TableName: dynamodbTableName
}
const allProducts = await scanDynamoRecords(params, []);
const body = {
products: allProducts
}
return buildResponse(200, body);
}
async function scanDynamoRecords(scanParams, itemArray) {
try {
const dynamoData = await dynamodb.scan(scanParams).promise();
itemArray = itemArray.concat(dynamoData.Items);
if (dynamoData.LastEvaluatedKey) {
scanParams.ExclusiveStartkey = dynamoData.LastEvaluatedKey;
return await scanDynamoRecords(scanParams, itemArray);
}
return itemArray;
} catch(error) {
console.error('Do your custom error handling here. I am just gonna log it: ', error);
}
}
async function saveProduct(requestBody) {
const params = {
TableName: dynamodbTableName,
Item: requestBody
}
return await dynamodb.put(params).promise().then(() => {
const body = {
Operation: 'SAVE',
Message: 'SUCCESS',
Item: requestBody
}
return buildResponse(200, body);
}, (error) => {
console.error('Do your custom error handling here. I am just gonna log it: ', error);
})
}
async function modifyProduct(productId, updateKey, updateValue) {
const params = {
TableName: dynamodbTableName,
Key: {
'productId': productId
},
UpdateExpression: `set ${updateKey} = :value`,
ExpressionAttributeValues: {
':value': updateValue
},
ReturnValues: 'UPDATED_NEW'
}
return await dynamodb.update(params).promise().then((response) => {
const body = { Operation: 'UPDATE',
Message: 'SUCCESS',
UpdatedAttributes: response
}
return buildResponse(200, body);
}, (error) => {
console.error('Do your custom error handling here. I am just gonna log it: ', error);
})
}
async function deleteProduct(productId) {
const params = {
TableName: dynamodbTableName,
Key: {
'productId': productId
},
ReturnValues: 'ALL_OLD'
}
return await dynamodb.delete(params).promise().then((response) => {
const body = {
Operation: 'DELETE',
Message: 'SUCCESS',
Item: response
}
return buildResponse(200, body);
}, (error) => {
console.error('Do your custom error handling here. I am just gonna log it: ', error);
})
}
const errorObj = {apiError : "Might be issue with DB connection JUST TESTING"}
function buildResponse(statusCode, body) {
if(!body){
return {
statusCode: statusCode,
headers: {
'Content-Type': 'application/json',
"Access-Control-Allow-Origin" : "*",
"Access-Control-Allow-Credentials" : true
},
body: JSON.stringify(errorObj)
}
}
else{
return {
statusCode: statusCode,
headers: {
'Content-Type': 'application/json',
"Access-Control-Allow-Origin" : "*",
"Access-Control-Allow-Credentials" : true
},
body: JSON.stringify(body)
}
}
Generate package.json and package-lock.json and locally create a docker image and run it over a container to make sure everything works fine.
Worth saying this plainly — don’t skip the local container test. Run it, hit the endpoints, and confirm the DynamoDB calls return what you expect. A bug caught here costs you ten minutes. The same bug caught after you’ve pushed to ECR and wired up Lambda costs you an afternoon.
Now we have our files ready.
Step 2: Creating an ECR Instance
ECR or Elastic Container Registry is a service provided by AWS to keep Docker images in the repo and use them as per demand. We will be using these images to create our lambda.
Think of ECR as a private Docker Hub that lives inside your AWS account. It stores your image, versions it, and hands it to Lambda whenever the function spins up. Clean, integrated, no third-party registry needed.
Search ECR in AWS and click on “Create Repository.”
- Give a name to the repository and click “Create Repository.”
- The created Repo on ECR will be shown in the list
Now go to the repo, and you will find the “push commands”. Go through the highlighted/marked buttons as below.
These commands we need to execute when pushing the Docker image to our created repo at ECR.
You can follow the image below to check how files are uploaded to the EC2 and then how the Docker image is created.
- RED LINE: Creating a file in the directory
- BLUE LINE: Writing content in the files
- YELLOW LINE: Executing the first push command we got from ECR. For logging into Docker.
Now we will be executing the rest of the push commands as given by ECR.
Now our image is pushed to our ECR repo, as shown below.
Step 3: Creating a Lambda Function through an ECR Image
Go to AWS → Lambda → click on "Create Function" button
- RED LINE: Select container image
- GREEN LINE: Give a name to the function (Remember that the name of the lambda should match the name of the REPO)
- BLUE LINE: Paste the Image URI from the ECR Repo pushed image
And then click on create function.
Go to the Lambda Function created and click on test to check if it's working fine.
If it comes back clean, that's your confirmation that the whole chain worked - Dockerfile, application logic, ECR push, Lambda config, all of it. First successful test on a container you built yourself hits differently than a regular deploy.
If everything works fine, lets go and create trigger for this lambda from API gateway.
Step 4: Creating a Trigger For Lambda by AWS API Gateway
Go to API Gateway → Create API → REST API. Give a name to the API collection and click "Create API."
Now, just create a resource with a path as handled in the application (see index.js file).
Like in the image below, you can see I have created 2 resources, "products" and "/product". After creating a resource create method for the resources, like for "/products", I have created a GET method and for the "/product", 4 methods are created: GET, POST, PATCH, and DELETE.
NOTE: Turn on the "Lambda Proxy Integration" to avoid mapping of the event object in your code.
Seriously - don't overlook this toggle. Leave it off, and the full event object never reaches your handler correctly. Your routing logic breaks, nothing goes where it should, and the error messages won't point you back to this setting. One checkbox saves a genuinely confusing debugging session.
Step 5: Deploy the APIs and test them
After creating the APIs, deploy the APIs and take note of the invoking URLs. As shown in the image below.
Note the invoking URL.
Below are the APIs tested via POSTMAN.
Work through every route methodically. Health check first, then fetch a product, create one, update a field, and delete a record. Watch each one return the right response from DynamoDB - routed through API Gateway, processed by your containerized Lambda, handed back clean.
SUMMARY: The above steps can be imagined as follows:
Client → API Gateway → Lambda (Docker Container) → DynamoDB + API Gateway integration
Conclusion
In conclusion, Dockerized Lambda functions present significant advantages for custom financial software development, iOS mobile app development companies, and software development for healthcare. By encapsulating Lambda function code and its dependencies within Docker containers, developers in healthcare custom software development and cross-platform mobile app development services gain greater control, flexibility, and efficiency throughout the development lifecycle.
For businesses seeking offshore software development, Dockerizing Lambda functions provides a reliable approach. It facilitates the hiring of offshore development teams and the engagement of dedicated offshore developers for software development services. Moreover, it streamlines the process of hiring a software development team and ensures efficient software outsourcing — everyone runs the same container, so environment mismatches stop eating into delivery time.
In essence, Dockerizing Lambda functions empowers software development companies, software development agencies, and application development companies to deliver robust solutions across diverse industries. Whether it’s web development services or software application development, Dockerization enhances the capabilities of software development firms and contributes to their success in the competitive marketplace.
About Innostax
Innostax specializes in managed engineering teams and was founded in 2014. It is headquartered in Framingham, Massachusetts. We establish engineering teams with accountability as a priority for both startups and enterprises, helping them achieve consistent software velocity with no customer churn.
Read more : Dockerized Lambda : Transform Your Development with Efficiency
Top comments (0)