π AWS CI/CD Pipeline | End-to-End Deployment Using CodePipeline & CodeDeploy
Build an automated deployment pipeline for a Dockerized Python Flask application using GitHub, AWS CodePipeline, AWS CodeDeploy, and EC2.

Search for a command to run...
Build an automated deployment pipeline for a Dockerized Python Flask application using GitHub, AWS CodePipeline, AWS CodeDeploy, and EC2.

No comments yet. Be the first to comment.
π Build a Production-Ready CI Pipeline on AWS with GitHub, Docker & CodeBuild Learn how to automate Docker image building, testing, and deployment whenever code is pushed to GitHub.

Understand AWS CodePipeline from scratch, how CI/CD orchestration works, how Jenkins compares with AWS CodePipeline, and the key differences between open-source/self-managed tools and AWS managed services.

Learn AWS CI/CD from scratch with AWS CodeCommit. Understand CI/CD concepts, AWS Developer Tools, CodeCommit architecture, IAM permissions, repository creation, Git commands, authentication, security, real-world use cases, CodeCommit vs GitHub, best practices, troubleshooting, and interview questions.

Learn AWS CloudFormation (CFT) from scratch with simple explanations, real-world examples, YAML templates, best practices, Drift Detection, CloudFormation vs Terraform, interview questions, and hands-on demonstrations.

In this project, we will build an end-to-end CI/CD pipeline on AWS that automatically deploys a Python Flask application to an EC2 instance.
The project focuses mainly on the Continuous Delivery (CD) part of the pipeline using AWS CodeDeploy and then integrates CodeDeploy with AWS CodePipeline.
By the end of this project, the workflow will look like:
Developer
β
β git push
βΌ
GitHub Repository
β
βΌ
AWS CodePipeline
β
βΌ
Source Stage
β
βΌ
Build / CI Stage
β
βΌ
AWS CodeDeploy
β
βΌ
EC2 Instance
β
βββ CodeDeploy Agent
βββ Docker
βββ Flask Application
Our goal is to deploy a Python Flask application running inside a Docker container onto an AWS EC2 instance.
Instead of manually connecting to the EC2 server every time we release a new version, we want AWS to automatically deploy the latest version.
The final workflow will be:
Developer pushes code
β
GitHub
β
CodePipeline
β
CodeDeploy
β
EC2
β
Docker Container
β
Flask Application
This means whenever new code is pushed into the configured repository, the pipeline can automatically take that code through the required stages and deploy it to the EC2 server.
CI/CD stands for:
CI β Continuous Integration
CD β Continuous Delivery / Continuous Deployment
CI/CD is a software development approach that automates the process of:
Code β Build β Test β Package β Deploy
Without CI/CD, developers may have to manually build applications, copy files to servers, restart applications, and verify deployments.
With CI/CD, these activities can be automated.
Continuous Integration focuses on automatically validating new code changes.
For example:
Developer
β
Git Push
β
Build
β
Unit Tests
β
Package
The objective is to identify problems early.
Continuous Delivery focuses on taking successfully built application code and deploying it to an environment.
For example:
Build Artifact
β
CodeDeploy
β
EC2
β
Application
In this project, AWS CodeDeploy is responsible for the deployment process.
We will use the following components:
| Service | Purpose |
|---|---|
| GitHub | Source code repository |
| AWS CodePipeline | Orchestrates the pipeline |
| AWS CodeDeploy | Automates deployment |
| Amazon EC2 | Deployment server |
| IAM | Permissions and access control |
| Docker | Runs the application container |
| Python Flask | Sample application |
The high-level architecture looks like this:
ββββββββββββββββββββ
β Developer β
ββββββββββ¬ββββββββββ
β
git push
β
βΌ
ββββββββββββββββββββ
β GitHub β
β Source Code β
ββββββββββ¬ββββββββββ
β
βΌ
ββββββββββββββββββββ
β CodePipeline β
ββββββββββ¬ββββββββββ
β
βΌ
ββββββββββββββββββββ
β CodeDeploy β
ββββββββββ¬ββββββββββ
β
βΌ
ββββββββββββββββββββββββββββββββ
β EC2 Instance β
β β
β CodeDeploy Agent β
β Docker β
β β
β Docker Container β
β β β
β βΌ β
β Python Flask App β
ββββββββββββββββββββββββββββββββ
Before starting this project, you should have basic knowledge of:
AWS
EC2
IAM
Git/GitHub
Linux
Docker
Basic Python
Basic CI/CD concepts
You should also have:
An AWS account
A GitHub repository
A sample Flask application
An EC2 instance
Permission to create IAM roles and AWS services
First, we need an application that will be deployed.
For this project, we are using a Python Flask application.
A simple project structure can look like:
project/
β
βββ app.py
βββ Dockerfile
βββ appspec.yml
βββ start_container.sh
βββ stopcontainer.sh
βββ requirements.txt
Let's understand these files.
app.pyThis contains our Flask application.
Example:
from flask import Flask
app = Flask(__name__)
@app.route("/")
def home():
return "Hello from AWS CI/CD Pipeline!"
if __name__ == "__main__":
app.run(host="0.0.0.0", port=5000)
The application listens on port 5000 inside the container.
We use Docker to package our application and its dependencies.
Example:
FROM python:3.10
WORKDIR /app
COPY requirements.txt .
RUN pip install -r requirements.txt
COPY . .
EXPOSE 5000
CMD ["python", "app.py"]
The Dockerfile tells Docker how to create the application image.
This file contains the Python dependencies.
For example:
Flask
appspec.ymlOne of the most important files in AWS CodeDeploy is:
appspec.yml
The appspec.yml file tells CodeDeploy how the application should be deployed.
It defines deployment instructions and lifecycle hooks.
A simplified example can look like:
version: 0.0
os: linux
files:
- source: /
destination: /home/ubuntu/app
hooks:
ApplicationStop:
- location: stopcontainer.sh
timeout: 300
runas: root
ApplicationStart:
- location: start_container.sh
timeout: 300
runas: root
The exact configuration can vary depending on the application and deployment design.
CodeDeploy provides lifecycle events that allow us to execute scripts during deployment.
For example:
ApplicationStop
β
Download / Install Files
β
ApplicationStart
β
Application Running
This is useful because we can automatically:
Stop the old container
Copy the new application files
Build/start the new container
Start the updated application
stopcontainer.shThe purpose of this script is to stop the currently running application container before deploying the new version.
Example:
#!/bin/bash
docker stop flask-app || true
docker rm flask-app || true
The || true prevents the deployment from failing if the container does not already exist.
start_container.shThis script starts the new application.
For example:
#!/bin/bash
cd /home/ubuntu/app
docker build -t flask-app .
docker run -d \
--name flask-app \
-p 80:5000 \
flask-app
Now the application running on container port 5000 is exposed through EC2 port 80.
Now we need an EC2 instance that will act as our deployment target.
From the AWS Console:
AWS Console
β
EC2
β
Launch Instance
Select an Ubuntu AMI.
For learning purposes, choose an appropriate small instance type that fits your AWS account and budget.
We need to allow the traffic required to access our server.
Typical rules could include:
| Protocol | Port | Purpose |
|---|---|---|
| SSH | 22 | Remote administration |
| HTTP | 80 | Application access |
For SSH, restrict the source to your own IP whenever possible.
Avoid opening administrative ports such as SSH to the entire internet unless there is a specific reason.
After launching the instance, connect using SSH.
Example:
ssh -i my-key.pem ubuntu@<EC2_PUBLIC_IP>
Make sure the private key has appropriate permissions:
chmod 600 my-key.pem
Our application will run inside a Docker container, so Docker must be available on the EC2 instance.
First update the system:
sudo apt update
Then install Docker:
sudo apt install docker.io -y
Check the installation:
docker --version
Also verify that Docker is running:
sudo systemctl status docker
The CodeDeploy Agent is a software component installed on the deployment target.
It allows AWS CodeDeploy to communicate with the EC2 instance and execute deployment instructions.
The basic flow is:
AWS CodeDeploy
β
CodeDeploy Agent
β
EC2 Instance
β
Application Deployment
The agent must be installed and running on the target EC2 instance.
After installation, verify its status using the appropriate service command for your system.
For example:
sudo systemctl status codedeploy-agent
If the service is running, the EC2 instance can communicate with CodeDeploy.
IAM is extremely important in AWS CI/CD.
AWS services need permission to interact with other AWS resources.
For example:
CodeDeploy
β
Needs permission
β
EC2
An IAM role can provide the required permissions.
The EC2 instance should have an IAM role that provides the permissions required by the CodeDeploy agent and application.
When configuring the role, follow the principle of least privilege.
That means:
Give only the permissions that are actually required.
Avoid giving broad administrator permissions unnecessarily.
Now let's create an AWS CodeDeploy application.
Go to:
AWS Console
β
CodeDeploy
β
Applications
β
Create application
Choose:
Compute Platform: EC2/On-premises
Give the application a meaningful name.
For example:
flask-cicd-app
After creating the CodeDeploy application, create a Deployment Group.
The deployment group tells CodeDeploy:
"Which EC2 instances should receive this deployment?"
We can identify instances using tags.
For example:
Key: Environment
Value: Production
Then CodeDeploy can deploy to EC2 instances matching that tag.
Tags help AWS identify and organize resources.
For example:
Environment = Production
Application = Flask
Team = DevOps
CodeDeploy can use these tags to select deployment targets.
Now our application repository should contain the required deployment files:
app.py
Dockerfile
requirements.txt
appspec.yml
start_container.sh
stopcontainer.sh
The source package is provided to CodeDeploy.
CodeDeploy reads:
appspec.yml
and follows the deployment instructions.
The deployment process looks like:
Source Package
β
CodeDeploy
β
ApplicationStop
β
Files Copied
β
ApplicationStart
β
Docker Image Built
β
Docker Container Started
β
Application Available
Now we connect CodeDeploy with AWS CodePipeline.
This is where our project becomes an end-to-end automated pipeline.
The pipeline can be represented as:
GitHub
β
CodePipeline
β
Source
β
Build / CI
β
CodeDeploy
β
EC2
β
Docker
β
Flask Application
CodePipeline acts as the orchestrator.
It coordinates the different stages of the software delivery process.
Go to:
AWS Console
β
CodePipeline
β
Create Pipeline
Give the pipeline a meaningful name.
Example:
flask-cicd-pipeline
Configure GitHub as the source provider.
The pipeline will retrieve the latest application code from the configured repository.
Whenever the source changes according to the configured trigger, the pipeline can start a new execution.
If your project already has a CI/build stage, CodePipeline can pass the resulting application package to the deployment stage.
The important idea is:
Source
β
Build
β
Deployment
Only after the required previous stage succeeds should the deployment stage proceed.
For the deployment stage, select:
Provider:
AWS CodeDeploy
Then select:
Application
Deployment Group
that you created earlier.
Now CodePipeline knows where to send the application.
Our final pipeline looks like:
ββββββββββββββββ
β GitHub β
ββββββββ¬ββββββββ
β
βΌ
ββββββββββββββββ
β CodePipeline β
ββββββββ¬ββββββββ
β
βΌ
ββββββββββββββββ
β Source β
ββββββββ¬ββββββββ
β
βΌ
ββββββββββββββββ
β Build β
ββββββββ¬ββββββββ
β
βΌ
ββββββββββββββββ
β CodeDeploy β
ββββββββ¬ββββββββ
β
βΌ
βββββββββββββββββββββββ
β EC2 Instance β
β β
β CodeDeploy Agent β
β β β
β Docker β
β β β
β Flask Container β
βββββββββββββββββββββββ
Now let's test the pipeline.
Make a small change to your application.
For example:
return "Hello from AWS CI/CD Pipeline - Version 2!"
Commit the change:
git add .
git commit -m "Update application"
git push
The pipeline should detect the new source version according to its configured trigger.
Then:
GitHub
β
CodePipeline
β
CodeDeploy
β
EC2
β
Docker
β
New Application Version
Once deployment succeeds, access the EC2 instance using the configured application endpoint.
If the application is exposed on port 80, you can access:
http://<EC2_PUBLIC_IP>
If everything is configured correctly, the updated Flask application should be displayed.
This is one of the most important beginner questions.
CodeDeploy uses:
appspec.yml
The file defines:
Which files should be deployed
Where they should be copied
Which lifecycle scripts should run
When those scripts should run
For example:
ApplicationStop
β
Stop old application
β
Deploy files
β
ApplicationStart
β
Start new application
During real deployments, things don't always work on the first attempt.
Here are some common problems highlighted by this project.
Check:
sudo systemctl status codedeploy-agent
If it is stopped, start it using the appropriate system service command.
The CodeDeploy agent must be healthy for deployments to work.
If your deployment script executes:
docker build
but Docker is not installed, the deployment will fail.
Check:
docker --version
Install Docker if necessary.
The deployment user may not have permission to communicate with Docker.
Check Docker permissions and ensure the deployment scripts execute with the appropriate user privileges.
Suppose your container uses:
-p 80:5000
but another process is already using port 80.
The new container may fail to start.
Check listening ports:
sudo ss -tulpn
You can then identify which process is using the required port.
If the previous container is still running, the new container may fail because of:
Container name conflict
or:
Port already allocated
That's why the stop script is important.
Example:
docker stop flask-app || true
docker rm flask-app || true
appspec.ymlA small mistake in:
appspec.yml
can cause deployment failure.
Check:
File name
YAML indentation
Script paths
Destination directories
Lifecycle hook names
File permissions
AWS services need appropriate permissions.
If the required IAM role does not have sufficient permissions, deployment operations can fail.
Always check:
IAM Role
β
Required Permissions
β
AWS Service Access
A useful project structure is:
flask-cicd-project/
β
βββ app.py
β
βββ requirements.txt
β
βββ Dockerfile
β
βββ appspec.yml
β
βββ start_container.sh
β
βββ stopcontainer.sh
Each file has a specific responsibility.
| File | Purpose |
|---|---|
app.py |
Flask application |
requirements.txt |
Python dependencies |
Dockerfile |
Creates Docker image |
appspec.yml |
CodeDeploy deployment instructions |
start_container.sh |
Starts new container |
stopcontainer.sh |
Stops old container |
CodeDeploy automates application deployments to supported compute environments such as EC2.
It removes much of the manual work involved in copying application files and executing deployment scripts.
The CodeDeploy Agent runs on the deployment target.
It communicates with AWS CodeDeploy and executes the deployment instructions.
appspec.ymlThis is the deployment configuration file.
It defines:
Files
Hooks
Lifecycle Events
Deployment Instructions
Lifecycle hooks allow scripts to execute at specific stages of deployment.
Examples include:
ApplicationStop
ApplicationStart
CodePipeline orchestrates the different stages of the CI/CD workflow.
For example:
Source
β
Build
β
Deploy
IAM roles provide AWS resources and services with the permissions they need.
They are preferable to embedding long-term AWS credentials inside application code or deployment scripts.
Amazon EC2 provides the virtual server where our application is ultimately deployed.
Docker packages the Flask application and its dependencies into a container.
This makes the application environment more consistent.
Without Docker, we might need to manually configure:
Python
Flask
Dependencies
System Libraries
Application Configuration
With Docker, we package the environment into an image.
Dockerfile
β
Docker Image
β
Docker Container
β
Flask Application
This provides a more consistent deployment process.
Developer
β
SSH into EC2
β
Pull latest code
β
Install dependencies
β
Stop application
β
Start application
β
Verify
This process is repetitive and error-prone.
Developer
β
Git Push
β
CodePipeline
β
CodeDeploy
β
EC2
β
Docker
β
Application
This is faster, repeatable, and easier to standardize.
This project helped me understand how different AWS services work together to create a practical CI/CD pipeline.
The major concepts covered were:
AWS CodePipeline
AWS CodeDeploy
EC2
IAM Roles
CodeDeploy Agent
Docker
Flask
appspec.yml
Deployment lifecycle hooks
Shell scripts
Automated deployments
CI/CD workflow
Deployment troubleshooting
Answer:
AWS CodeDeploy is an AWS deployment service that automates application deployments to supported compute environments such as EC2.
It helps automate tasks such as transferring application files, executing deployment scripts, and managing application lifecycle events.
Answer:
The CodeDeploy Agent is software installed on the deployment target, such as an EC2 instance.
It communicates with CodeDeploy and executes the deployment instructions provided by the deployment package.
appspec.yml?Answer:
appspec.yml is a configuration file used by AWS CodeDeploy to define deployment instructions.
It can specify files to copy and lifecycle hooks that execute scripts during deployment.
Answer:
An IAM role provides the required permissions to AWS services and resources without embedding long-term credentials directly into the application.
For example, an EC2 instance can use an IAM role to access AWS services securely.
Answer:
CodePipeline is used to orchestrate the complete CI/CD workflow.
CodeDeploy is focused specifically on application deployment.
For example:
CodePipeline
β
Orchestrates pipeline
β
CodeDeploy
β
Deploys application to EC2
Answer:
Deployment scripts automate repetitive deployment tasks.
In this project:
stopcontainer.sh
stops the previous container, while:
start_container.sh
starts the new application container.
Answer:
Docker packages the application and its dependencies into a portable container.
This helps create a consistent application environment between development and deployment.
Answer:
In our configured pipeline, a new source change can trigger CodePipeline.
The pipeline retrieves the updated code, processes the configured stages, and then invokes CodeDeploy to deploy the new version to the EC2 instance.
Answer:
We should check the deployment status and logs, then verify:
CodeDeploy Agent
IAM permissions
appspec.yml
Deployment scripts
Docker installation
Docker container status
Port availability
EC2 configuration
ApplicationStop?Answer:
ApplicationStop is a CodeDeploy lifecycle event that can be used to execute commands before the new application version is deployed.
In this project, it can be used to stop the existing Docker container.
After completing this project, our application delivery architecture looks like:
DEVELOPER
β
β git push
βΌ
βββββββββββββββββββ
β GitHub β
ββββββββββ¬βββββββββ
β
βΌ
βββββββββββββββββββ
β CodePipeline β
ββββββββββ¬βββββββββ
β
Source / Build
β
βΌ
βββββββββββββββββββ
β CodeDeploy β
ββββββββββ¬βββββββββ
β
βΌ
βββββββββββββββββββββββββββββββ
β EC2 Server β
β β
β CodeDeploy Agent β
β β β
β βΌ β
β Docker β
β β β
β βΌ β
β Flask Container β
β β β
β βΌ β
β Flask Application β
βββββββββββββββββββββββββββββββ
The most important thing to understand from this project is not just how to click through the AWS Console.
The important concept is understanding how the services communicate with each other.
GitHub
β
CodePipeline
β
CodeDeploy
β
CodeDeploy Agent
β
EC2
β
Docker
β
Flask Application
Each component has a specific responsibility.
GitHub β Stores source code
CodePipeline β Orchestrates the delivery workflow
CodeDeploy β Handles application deployment
CodeDeploy Agent β Communicates with the EC2 target
EC2 β Provides the server
Docker β Runs the application container
Flask β Provides the application
In this project, we implemented a practical AWS CI/CD deployment workflow using CodePipeline, CodeDeploy, EC2, IAM, Docker, and GitHub.
We started with a Python Flask application and prepared it for automated deployment using:
Dockerfile
appspec.yml
start_container.sh
stopcontainer.sh
We then configured an EC2 deployment target, installed the CodeDeploy Agent, configured IAM permissions, created a CodeDeploy application and deployment group, and finally integrated CodeDeploy with CodePipeline.
The final result is an automated deployment workflow:
Code Change
β
GitHub
β
CodePipeline
β
CodeDeploy
β
EC2
β
Docker
β
Updated Flask Application
This project provides a strong foundation for understanding how AWS-managed services can be combined to build a practical CI/CD workflow.
π The real DevOps mindset is not just knowing individual tools β it is understanding how to connect those tools to build an automated, reliable, and repeatable software delivery process.
πΊ AWS Ultimate CI/CD Pipeline | End-to-End Demo | AWS CodePipeline
https://youtu.be/8ftrKNbSv28?si=d0sHbYjlPyFtsQBT
Thank you for taking the time to read this article.
Technology is evolving rapidly, and continuous learning is one of the most valuable investments you can make in your career. Whether you're exploring DevOps, Cloud Computing, Artificial Intelligence, Cybersecurity, Software Development, Data Science, or Career Growth, the resources below can help you deepen your knowledge and stay ahead in the industry.
Learn from world-renowned universities and industry leaders including Google, IBM, Stanford, Microsoft, Meta, and many more.
β Professional Certificates β Career-focused Learning Paths β AI & Machine Learning Programs β Cloud & DevOps Certifications β Business & Leadership Courses
π https://imp.i384100.net/k0KvbV
One of the largest online learning platforms with practical, hands-on courses covering:
β DevOps & Kubernetes β Docker & Cloud Computing β AWS, Azure & GCP β Programming & Development β Cybersecurity & Ethical Hacking
π https://trk.udemy.com/MAL2MY
A great platform for anyone interested in:
β Python Programming β SQL & Databases β Data Analytics β Machine Learning β Artificial Intelligence
Interactive learning paths and hands-on projects make it ideal for beginners and professionals alike.
π https://datacamp.pxf.io/nX4kER
Access high-quality courses and certifications from leading institutions such as:
β Harvard University β MIT β Berkeley β Microsoft
Perfect for learners seeking university-level education online.
π https://edx.sjv.io/POvVeN
Enhance your creative skills with courses on:
β Graphic Design β Video Editing β Animation β Digital Marketing β Content Creation
π https://domestika.sjv.io/dynKAW
Discover exclusive lifetime deals on:
β AI Tools β Productivity Software β Developer Utilities β Marketing Platforms β Business Applications
A must-have resource for developers, creators, freelancers, and entrepreneurs looking to save money while accessing premium tools.
π https://appsumo.8odi.net/L04a33
Looking to start an online business or launch an eCommerce store?
Shopify provides everything you need to build, manage, and scale an online business.
β Online Store Builder β Payment Integration β Inventory Management β Marketing Tools
π https://shopify.pxf.io/Vxv09k
Create professional websites, blogs, and online stores with one of the most trusted web ecosystems in the world.
Ideal for:
β Personal Blogs β Portfolio Websites β Business Websites β eCommerce Stores
π https://automattic.pxf.io/Z6vR5W
Learn English and other languages through personalized one-on-one tutoring sessions with experts from around the world.
π https://preply.sjv.io/o4gBDY
Improve your professional communication skills and English fluency through structured learning programs.
π https://englishonline.sjv.io/9VOGa4
One of the most recognized language-learning platforms for immersive language acquisition.
π https://aff.rosettastone.com/X4OyqG
Interactive science kits and educational experiences designed to make STEM learning engaging and practical.
π https://imp.i328067.net/bk2beg
Educational materials and learning resources for students, teachers, and lifelong learners.
π https://carsondellosaeducation.sjv.io/E0JbjW
Creating detailed technical content, tutorials, guides, and learning resources takes significant time and effort.
If you find my articles helpful and would like to support my work, you can do so through the following platforms:
Support my open-source contributions, technical content, and community projects.
π https://github.com/sponsors/hritikranjan1
Enjoying my content? Consider buying me a chai and supporting future tutorials, guides, and educational resources.
π https://www.chai4.me/hritikranjan
Hritik Ranjan
π‘ AI Enthusiast βοΈ DevOps Learner π Cybersecurity Advocate π» Software Developer
π GitHub: https://github.com/hritikranjan1
π LinkedIn: https://linkedin.com/in/hritikranjan1
If this article added value to your learning journey:
β
Share it with your network
β
Bookmark it for future reference
β
Follow for more DevOps, AI, Cloud, Cybersecurity, and Software Engineering content
Thank you for reading and being part of this learning journey.
Keep Learning. Keep Building. Keep Growing. π
AWS
DevOps
CI/CD
AWS CodePipeline
AWS CodeDeploy
Amazon EC2
Docker
GitHub
Cloud
Python
Flask
Continuous Delivery
