From Localhost to AWS EC2: Building a Jenkins CI/CD Pipeline for ElderSafe
While working on ElderSafe, a smart elderly safety and monitoring application, I got the opportunity to work on the DevOps side of the project and learn how an application can move from a developer's machine to a cloud environment using Docker, Jenkins, and AWS EC2. This experience helped me understand that DevOps is not just about knowing individual tools. It is about connecting those tools into a reliable software delivery process.
1. What is ElderSafe?
ElderSafe is a smart elderly monitoring and safety system designed to help connect elderly users with their families and healthcare-related support.
The project contains multiple components, including:
- React-based frontend
- FastAPI backend
- MongoDB database
- Machine learning functionality
- Docker-based deployment
- Cloud infrastructure
The application was developed as a team project, so different parts of the system were being developed simultaneously.
This created an important DevOps question:
How can we deploy the complete application consistently without manually configuring everything every time?
That became the problem I wanted to solve.
2. The Initial Problem
During development, the application worked on our local machines.
But a local environment and a cloud server are not necessarily the same.
For example, the application required:
- Frontend dependencies
- Python dependencies
- Backend configuration
- Database connectivity
- Correct ports
- Docker
- Environment variables
If these things were configured manually on a server, deployment could become inconsistent.
A simplified manual process would look something like:
1
2
3
4
5
6
7
8
9
10
11
12
13
Developer
↓
Push Code
↓
SSH into Server
↓
Pull Latest Code
↓
Build Application
↓
Start Services
↓
Check ApplicationThis works for a small experiment.
But if the same process needs to happen repeatedly, automation becomes much more useful.
So I decided to build a CI/CD workflow using Jenkins.
3. The Technology Stack
The DevOps side of the project used:
| Technology | Purpose |
|---|---|
| GitHub | Source code management |
| Jenkins | CI/CD automation |
| Docker | Application containerization |
| Docker Compose | Running multiple services |
| AWS EC2 | Cloud deployment |
| MongoDB Atlas | Database |
Each technology had a different responsibility.
The goal wasn't to use tools just because they were popular.
The goal was to understand how they fit together.
4. Why Docker?
ElderSafe contains multiple application components.
The frontend and backend have different dependencies and environments.
Docker allowed me to package the application components into containers.
A simplified architecture looked like this:
1
2
3
4
5
6
7
8
9
10
11
12
ElderSafe
|
---------------------
| |
Frontend Backend
React FastAPI
| |
-------- Docker -----
|
Docker Compose
|
AWS EC2Instead of installing every dependency directly on the EC2 machine, the application environment could be defined through Docker configuration.
This made deployment more consistent.
5. Running ElderSafe with Docker Compose
Since the project contained multiple services, Docker Compose was useful for defining how the services should run together.
A simplified example looks like:
1
2
3
4
5
6
7
8
9
10
11
services:
frontend:
build: ./frontend
ports:
- "3000:3000"
backend:
build: ./backend
ports:
- "8000:8000"The actual configuration depends on the project, but the important concept is that the services can be started together.
Instead of manually starting every component, Docker Compose provides a single workflow.
For example:
1
docker compose up -dAnd to stop the services:
1
docker compose downThis was one of the first points where I saw how containerization can simplify deployment.
6. Why Jenkins?
Docker solved the problem of packaging the application.
But I still needed a way to automate the deployment process.
That's where Jenkins came in.
Jenkins acts as the automation layer between the source code and deployment environment.
The workflow became:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Developer
↓
GitHub
↓
Jenkins
↓
Build
↓
Test
↓
Docker
↓
Deploy
↓
AWS EC2Instead of manually performing deployment commands after every change, Jenkins could execute the required steps automatically.
7. Setting Up Jenkins
I configured Jenkins as the CI/CD server for the project.
The pipeline was responsible for retrieving the latest source code and performing the required deployment steps.
A simplified pipeline could be represented as:
1
2
3
4
5
Stage 1 → Checkout
Stage 2 → Build
Stage 3 → Test
Stage 4 → Docker Build
Stage 5 → DeployThe exact pipeline stages depend on the application and deployment strategy.
The important part was separating the deployment process into clear stages.
This made it easier to identify where something went wrong.
8. Connecting Jenkins with the EC2 Server
The next challenge was connecting the CI/CD system with the cloud environment.
The application was deployed on an AWS EC2 instance.
The general workflow was:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
GitHub
|
↓
Jenkins
|
↓
Build / Validate
|
↓
Docker
|
↓
AWS EC2
|
↓
ElderSafe AppThe EC2 instance acted as the deployment environment.
This gave me practical exposure to concepts such as:
- SSH
- Linux server administration
- Security groups
- Ports
- Docker on Linux
- Application deployment
- Cloud infrastructure
9. Understanding AWS Security Groups
One of the things that became much clearer during deployment was that making an application run on EC2 doesn't automatically make it accessible.
AWS security groups control inbound and outbound traffic associated with the instance.
For example, if my application listens on a particular port, that port needs to be appropriately configured for the intended access.
The request path can be thought of as:
1
2
3
4
5
6
7
8
9
10
11
User
↓
Internet
↓
AWS Security Group
↓
EC2 Instance
↓
Docker Container
↓
ApplicationIf any layer is incorrectly configured, the application may not be reachable.
This taught me an important debugging lesson:
When a cloud application isn't accessible, don't immediately assume that the application code is the problem.
Check the infrastructure layer by layer.
10. The CI/CD Pipeline
The final workflow can be simplified as:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
Developer
|
↓
GitHub Push
|
↓
Jenkins
|
----------------
| | |
Build Test Docker
| | |
--------|-------
↓
Deployment
↓
AWS EC2
↓
Docker Compose
↓
ElderSafeThis changed deployment from a manual process into a repeatable process.
Whenever new changes were ready, Jenkins could perform the required pipeline steps rather than requiring every deployment step to be performed manually.
11. One Problem I Encountered
One of the biggest lessons from the project was that deployment rarely works perfectly on the first attempt.
There were several layers that had to work together:
1
2
3
4
5
6
7
8
9
10
11
Application
↓
Docker
↓
Docker Compose
↓
Jenkins
↓
EC2
↓
AWS NetworkingWhen something failed, simply looking at the final application wasn't enough.
I had to work backwards through the deployment chain.
For example:
1
2
3
4
5
6
7
8
9
10
11
Is the application running?
↓
Is the container running?
↓
Did Docker build successfully?
↓
Did Jenkins complete successfully?
↓
Is EC2 running?
↓
Are the required ports accessible?This approach helped me understand troubleshooting as a structured process rather than randomly changing configurations.
12. A Lesson About Cloud Costs
Another important lesson I learned was that cloud resources are not something to create and forget.
During development, resources such as EC2 instances can continue generating charges depending on the configuration and attached resources.
For a student project, this is especially important.
I learned to:
- Check running resources
- Stop resources when they aren't needed
- Monitor attached resources
- Understand which resources can generate charges
- Avoid leaving unused infrastructure running
Cloud learning isn't only about deployment.
It is also about responsible resource management.
13. What I Learned from the Project
This project taught me several practical concepts.
1. Docker makes environments more consistent
Instead of depending entirely on the host machine, application dependencies can be packaged into containers.
2. Jenkins turns repeated steps into automation
CI/CD reduces repetitive manual deployment work and creates a repeatable process.
3. EC2 provides hands-on cloud experience
Deploying directly to a Linux-based EC2 environment helped me understand servers, networking, SSH, and cloud infrastructure.
4. Debugging is a major DevOps skill
Knowing commands is useful, but understanding where a failure occurs is even more important.
5. Security should be part of the pipeline
Container scanning showed me how security checks can be integrated into CI/CD.
6. Cloud resources need to be managed carefully
A successful deployment is not the end of the project. Resource usage and cost also matter.
14. What I Would Improve Next
The current deployment workflow is a learning-focused implementation, but there are several areas I would improve as the project becomes more production-oriented.
Monitoring
I would add better monitoring for application health, logs, CPU, memory, and failures.
Infrastructure as Code
Instead of manually configuring infrastructure, I would explore Terraform or AWS CloudFormation.
Better Secret Management
Sensitive configuration should be managed using dedicated secret-management mechanisms rather than being placed directly in source code.
Automated Testing
More comprehensive unit and integration tests could be added before deployment.
Container Registry
A production-oriented workflow could use a container registry so that versioned images are stored separately from the deployment server.
Improved Deployment Strategy
As the application grows, deployment strategies such as rolling or blue/green deployments could be explored.
15. The Architecture I Have Now
The complete learning architecture can be summarized as:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
┌──────────────┐
│ GitHub │
└──────┬───────┘
│
↓
┌──────────────┐
│ Jenkins │
└──────┬───────┘
│
┌───────────┴───────────┐
↓ ↓
Build/Test Security Scan
│ │
└───────────┬───────────┘
↓
┌──────────────┐
│ Docker │
└──────┬───────┘
↓
┌──────────────┐
│ AWS EC2 │
└──────┬───────┘
↓
┌──────────────────┐
│ Docker Compose │
└────────┬─────────┘
↓
┌──────────────────┐
│ ElderSafe │
│ │
│ React + FastAPI │
└──────────────────┘This architecture is simple, but it helped me understand the complete path from source code to cloud deployment.
16. My Biggest Takeaway
The most valuable thing I gained from this project wasn't learning one particular command.
It was learning how different technologies work together.
Before working on this project, I could study Docker, Jenkins, and AWS separately.
After implementing the deployment workflow, I started seeing them as connected pieces:
GitHub manages the code.
Jenkins automates the process.
Docker packages the application.
AWS EC2 provides the cloud infrastructure.
Security scanning helps identify container vulnerabilities.
Together, they form a software delivery pipeline.
Conclusion
ElderSafe started as a software project, but working on its deployment turned it into a practical DevOps learning experience.
Taking an application from localhost to an AWS EC2 instance forced me to understand much more than just deployment commands.
I learned about:
- Containerization
- CI/CD
- Jenkins
- AWS EC2
- Linux
- Networking
- Security groups
- Docker Compose
- Container security
- Troubleshooting
- Cloud cost awareness
The biggest lesson for me was simple:
Don't learn DevOps only by memorizing tools. Build something, deploy it, break it, troubleshoot it, and understand why each component is there.
That is where the real learning happens.
And this project has also given me a clear direction for what I want to learn next: Kubernetes, infrastructure as code, cloud-native deployment, monitoring, and more advanced DevSecOps practices.
If you're learning AWS or DevOps as a student, start with a small project and try to deploy it yourself. The problems you encounter during deployment can teach you more than a perfectly working tutorial ever will.
Enjoyed reading this content? Let the author know!
Your likes, comments, shares, and saves help creators reach more builders.
Loading recommendations
Loading article