This project implements an event-driven workflow on AWS that tracks container images pushed to Amazon Elastic Container Registry (ECR) . It stores metadata in Amazon DynamoDB and send notifications through Amazon SNS.
The solution ensure visibility & auditing for container images in a centralized, automated way.
Whenever a new image is pushed to Amazon ECR:
- Amazon EventBridge captures the push event.
- AWS Lambda is triggered.
- Lambda extracts image metadata (e.g., repository name, tag, etc).
- Metadata is stored in Amazon DynamoDB for tracking.
- A notification is sent via Amazon SNS to alert subscribers.
Flow:
- Jenkins pushes a Docker Image -> Amazon ECR
- EventBridge captures image push event
- Lambda executes logic
- Stores metadata -> DynamoDB
- Send notification -> SNS
.
├── Jenkinsfile # CI/CD pipeline
├── LICENSE # License file for the project
├── README.md # Main documentation file
├── lambda_function.py # Lambda function
└── doc/
└── Architecture Diagram Overview.png -
Go to DynamoDB → Create Table.
-
Table name:
ECRImageLogs -
Partition key:
Repository (String) -
Sort key:
ImageTag (String) -
Leave all other options as default.
-
Click Create Table.
-
Go to AWS SNS → Create topic.
-
Choose Standard as the topic type.
-
Name the topic:
ECRPushNotifications -
Create a subscription:
- Protocol: Email
- Endpoint: Your email address
-
Confirm the subscription from your email inbox.
-
Go to AWS Lambda → Create function.
-
Choose the following settings:
-
Author from scratch
-
Function name:
ECRImageLogger -
Runtime:
Python 3.12
-
-
Execution role:
-
Create a new IAM role named:
ECRImageLoggerIAMRole -
Attach the following policies:
AmazonDynamoDBFullAccessAmazonSNSFullAccess
-
-
Navigate to the Code tab and paste the following code:
import json import boto3 import os from datetime import datetime # Initialize AWS clients dynamodb = boto3.resource('dynamodb') sns = boto3.client('sns') # Environment variables (set in Lambda console) DYNAMODB_TABLE = os.environ['DYNAMODB_TABLE'] # DynamoDB table name SNS_TOPIC_ARN = os.environ['SNS_TOPIC_ARN'] # SNS topic ARN def lambda_handler(event, context): """ Lambda function that logs Docker image details into DynamoDB and sends an SNS notification after a successful ECR push. """ # Extract details from the event (supports both EventBridge and Jenkins formats) if "detail" in event: # EventBridge ECR event image_tag = event['detail'].get('image-tag', 'unknown-tag') repository = event['detail'].get('repository-name', 'unknown-repo') pushed_by = event.get('account', 'unknown-user') else: # Jenkins webhook (custom JSON) image_tag = event.get('image_tag', 'unknown-tag') repository = event.get('repository', 'unknown-repo') pushed_by = event.get('pushed_by', 'unknown-user') # Current timestamp timestamp = datetime.utcnow().isoformat() # Store details in DynamoDB table = dynamodb.Table(DYNAMODB_TABLE) table.put_item( Item={ 'Repository': repository, 'ImageTag': image_tag, 'PushedBy': pushed_by, 'Timestamp': timestamp } ) # Create a notification message message = ( f"Docker image pushed successfully!\n" f"Repository: {repository}\n" f"Tag: {image_tag}\n" f"Pushed By: {pushed_by}\n" f"Timestamp: {timestamp}" ) # Publish the message to SNS sns.publish( TopicArn=SNS_TOPIC_ARN, Message=message, Subject="ECR Image Push Notification" ) return { 'statusCode': 200, 'body': json.dumps('Lambda executed successfully!') }
-
Add environment variables:
Key Value DYNAMODB_TABLEECRImageLogsSNS_TOPIC_ARNYour SNS ARN -
Increase Timeout to:
1 minute
-
Go to Amazon EventBridge → Rules → Create Rule.
-
Set the following:
-
Name:
ECRPushTrigger -
Event bus:
default
-
-
Define the Event pattern:
{ "source": ["aws.ecr"], "detail-type": ["ECR Image Action"], "detail": { "action-type": ["PUSH"], "result": ["SUCCESS"] } } -
Alternatively, upload the pattern as a JSON file.
-
Add a Target:
-
Type: Lambda function
-
Function name:
ECRImageLogger
-
-
Save the rule.
-
Prerequisite: Jenkins Server Setup
-
Access the Jenkins server UI.
-
Create a new item:
-
Name:
Docker-Push-CI/CD -
Type: Pipeline
-
-
Configure the environment based on your requirements.
-
Paste the following Pipeline Script:
pipeline { agent any stages { stage('Install Docker') { steps { echo 'Installing Docker (if not already installed)...' sh ''' if ! command -v docker &> /dev/null; then sudo apt update -y sudo apt install -y docker.io sudo systemctl start docker fi ''' } } stage('Install AWS CLI') { steps { echo 'Installing AWS CLI (if not already installed)...' sh ''' if ! command -v aws &> /dev/null; then sudo apt update -y sudo apt install -y unzip curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip" unzip -o awscliv2.zip sudo ./aws/install fi ''' } } stage('Git Checkout') { steps { sh ''' sudo mkdir -p /docker cd /docker ''' checkout([$class: 'GitSCM', branches: [[name: '*/main']], userRemoteConfigs: [[url: 'https://github.com/harshkhalkar/student-registration-flask-application.git']] ]) sh 'rm -rf LICENSE README.md kubernetes docker-compose.yml init.sql Jenkinsfile' sh 'ls -l' } } stage('Build and Run Docker Container') { steps { sh ''' sudo docker build -t demo/purpose:v2 . sudo docker run -d -p 5000:5000 --name pyapp demo/purpose:v2 ''' } } stage('Run Tests') { steps { echo 'Running tests inside container...' sh ''' sudo docker ps curl -s localhost:5000 || echo "Flask app not reachable" sudo docker exec pyapp ls -l sudo docker exec pyapp ls -l tests sudo docker exec pyapp python3 -m unittest discover -s tests -t . ''' } } stage('Push to ECR') { steps { sh ''' aws ecr get-login-password --region us-east-1 | sudo docker login --username AWS --password-stdin 873579225118.dkr.ecr.us-east-1.amazonaws.com sudo docker tag demo/purpose:v2 873579225118.dkr.ecr.us-east-1.amazonaws.com/demo/purpose:v2 sudo docker push 873579225118.dkr.ecr.us-east-1.amazonaws.com/demo/purpose:v2 ''' } } } post { always { echo 'Cleaning up Docker resources...' sh ''' sudo docker stop pyapp || true sudo docker rm pyapp || true sudo docker rmi demo/purpose:v2 || true sudo docker rmi $(sudo docker images -q) || true ''' } } } -
Click Save and Run the pipeline.
-
Run the Jenkins Pipeline
- Jenkins should:
- Build the Docker image
- Push it to Amazon ECR
- Jenkins should:
-
Verify EventBridge Trigger
- Go to Amazon EventBridge → Rules.
- Confirm that your rule was triggered.
-
Check DynamoDB
- Go to the
ECRImageLogstable → Items - You should see a new record containing:
- Repository name
- Image tag
- Pushed by
- Timestamp
- Go to the
-
Check SNS Notification
- You should receive an email notification with ECR image push details.
-
Check Lambda Logs
- Go to CloudWatch Logs → Log groups
- Find the log group for
ECRImageLogger - Confirm the Lambda executed successfully and logged image metadata.
- Supports both EventBridge (AWS) and custom webhook events (e.g., from Jenkins)
- Logs repository name, image tag, pushed-by info, and timestamp
- Stores details in a DynamoDB table
- Sends notifications via SNS topic
Set the following in the Lambda environment:
DYNAMODB_TABLE: Name of the DynamoDB table to log image dataSNS_TOPIC_ARN: ARN of the SNS topic for notifications
-
Event Source
Receives an event from either:- EventBridge (ECR image push)
- Jenkins (custom JSON payload)
-
Extract Details
Parses image tag, repository name, user who pushed the image. -
Log to DynamoDB
Saves the image details with a timestamp. -
Send SNS Notification
Publishes a message with the image info to an SNS topic.
Returns a JSON response with HTTP status 200 on success.
Docker image pushed successfully!
Repository: my-repo
Tag: v1
Pushed By:
Timestamp: 2025-08-16T10:25:30.123Z
