In this guide, you’ll learn how to deploy a Dockerized Node.js application to an AWS EC2 instance using a Jenkins Pipeline. We’ll cover every step—from adding a deploy stage and managing Docker containers on EC2, to conditional execution and verifying your deployment.
Table of Contents
Prerequisites
Adding the Deploy Stage
Stopping & Removing the Existing Container
Running the New Container
Wrapping in a script Block
Conditional Execution with when
Verifying the Deployment
Links and References
Prerequisites
A Jenkins instance with the SSH Agent plugin installed
An AWS EC2 Ubuntu server accessible via SSH
A Dockerized application pushed to a Docker registry
Jenkins credentials configured for:
SSH key (e.g., aws-dev-deploy-ec2-instance)
MongoDB username & password (mongo-db-username, mongo-db-password)
1. Adding the Deploy Stage
After your Push Docker Image stage, insert a new stage called Deploy - AWS EC2 . Here’s the skeleton of your declarative pipeline:
pipeline {
agent any
stages {
stage( 'Build Docker Image' ) { /* ... */ }
stage( 'Trivy Vulnerability Scanner' ) { /* ... */ }
stage( 'Push Docker Image' ) { /* ... */ }
stage( 'Deploy - AWS EC2' ) {
steps { /* To be implemented */ }
}
}
post {
always { /* ... */ }
}
}
Stage Name Description Build Docker Image Build and tag your Docker image Trivy Vulnerability Scanner Scan the image for vulnerabilities Push Docker Image Push the image to your Docker registry Deploy - AWS EC2 SSH into EC2 and restart the container
We’ll use the SSH Agent plugin to authenticate to EC2 using the private key credential aws-dev-deploy-ec2-instance.
2. Stopping & Removing the Existing Container
Use an SSH one-liner to detect if the solar-system container is running, then stop and remove it:
ssh -o StrictHostKeyChecking=no [email protected] "
if sudo docker ps -a | grep -q 'solar-system'; then
echo 'Container found. Stopping...'
sudo docker stop solar-system && sudo docker rm solar-system
echo 'Container stopped and removed.'
fi
"
Suppressing StrictHostKeyChecking avoids interactive host key prompts, which is essential for unattended CI/CD pipelines.
3. Running the New Container
Next, start a fresh container with your environment variables. These variables come from the global environment block in your Jenkinsfile:
ssh -o StrictHostKeyChecking=no [email protected] "
sudo docker run --name solar-system \
-e MONGO_URI= $MONGO_URI \
-e MONGO_USERNAME= $MONGO_USERNAME \
-e MONGO_PASSWORD= $MONGO_PASSWORD \
-p 3000:3000 \
-d siddharth67/solar-system: $GIT_COMMIT
"
Define your environment variables at the top of the Jenkinsfile:
pipeline {
agent any
environment {
MONGO_URI = 'mongodb+srv://supercluster.d83jj.mongodb.net/superData'
MONGO_USERNAME = credentials( 'mongo-db-username' )
MONGO_PASSWORD = credentials( 'mongo-db-password' )
SONAR_SCANNER_HOME = tool 'sonarqube-scanner-610'
}
stages { /* ... */ }
}
Variable Source MONGO_URI Hard-coded connection string MONGO_USERNAME Jenkins credential mongo-db-username MONGO_PASSWORD Jenkins credential mongo-db-password GIT_COMMIT Jenkins built-in variable
4. Wrapping in a script Block
Because we’re using conditional logic (if), wrap the SSH commands in a script step inside the declarative stage:
stage( 'Deploy - AWS EC2' ) {
steps {
script {
sshagent([ 'aws-dev-deploy-ec2-instance' ]) {
sh '''
ssh -o StrictHostKeyChecking=no [email protected] "
if sudo docker ps -a | grep -q 'solar-system'; then
echo 'Container found. Stopping...'
sudo docker stop solar-system && sudo docker rm solar-system
echo 'Container stopped and removed.'
fi
sudo docker run --name solar-system \
-e MONGO_URI=$MONGO_URI \
-e MONGO_USERNAME=$MONGO_USERNAME \
-e MONGO_PASSWORD=$MONGO_PASSWORD \
-p 3000:3000 -d siddharth67/solar-system:$GIT_COMMIT
"
'''
}
}
}
post {
always { /* cleanup or notifications */ }
}
}
5. Conditional Execution with when
Run the deploy stage only on feature branches by adding a when condition. You can also configure this filter in the Jenkins UI:
stage( 'Deploy - AWS EC2' ) {
when {
branch 'feature/*'
}
steps {
script {
sshagent([ 'aws-dev-deploy-ec2-instance' ]) {
sh '''<same SSH block as above>'''
}
}
}
}
Using when { branch 'feature/*' } ensures that deployment only triggers for feature branches, preventing accidental prod deployments.
6. Verifying the Deployment
Check Jenkins Console
ssh -o StrictHostKeyChecking=no [email protected] "
if sudo docker ps -a | grep -q 'solar-system'; then
echo 'Container found. Stopping...'
sudo docker stop solar-system && sudo docker rm solar-system
fi
"
Sample logs:
Warning: Permanently added '3.140.244.188' (ECDSA) to the list of known hosts.
Container found. Stopping...
Container stopped and removed.
Unable to find image 'siddharth67/solar-system:5376ef9094c...' locally
Status: Downloaded newer image for siddharth67/solar-system:5376ef9094c...
cab883d639d9
On the EC2 Instance
Expected output:
CONTAINER ID IMAGE NAMES
cab88363d990 siddharth67/solar-system:5376ef09... solar-system
COMMAND CREATED STATUS PORTS
"docker-entrypoint.s..." About a minute ago Up About a minute 0.0.0.0:3000->3000/tcp
Access the Application
Open a browser and navigate to:
http://<EC2_PUBLIC_IP>:3000
Integration testing should follow to validate your application endpoints and data flow.
Links and References
Happy Deploying!