Note: Can be done in 2-3 groups!
In this project, you are going to design and deploy an image detection service that consists of multiple containers.
The application allows users to upload images and respond with objects that the service detected in the image. Users can interact with the application through a simple web UI or an interactive Telegram bot to obtain object detection results.
The service consists of 4 microservices:
Create a new GitHub repo for the project, clone the repo locally and open it in your favorite IDE (PyCharm, VSCode).
Copy the files under projects/app_development_I
into the root directory of the repo (no need to copy the README.md
).
Never commit sensitive data like secrets in Git repo, even if the repo is private.
For now, save the token in a file called .telegramToken
and add this file to .gitignore
to exclude it completely from the files Git tracks.
Later on in the course we will learn better approaches to store sensitive data.
In the project repo you’ll find a directory for each microservice.
frontend
serviceThis is a lightweight Flask UI which allows users to upload images and be responded with the detected objects.
You can run this service locally by:
cd frontend
python3 app.py
Make sure to install dependencies before by: pip install -r requirements.txt
.
Tip: It’s highly recommended working with a Python virtual environment.
Visit the app using the web browser. Obviously, the app wouldn’t function well since you need the other microservices to be up and running.
You are not provided with a Dockerfile
for this service, create one.
yolo5
serviceYolo5 is a state-of-the-art object detection model. It is known for its high accuracy and real-time performance, allowing for efficient detection of objects in images and videos. You’ll work with a lightweight model that can detect 80 objects while it’s running on your poor machines (on CPU instead GPU).
The service files are under the yolo5
directory. Take a look at the provided Dockerfile
, it’s already implemented for you, no need to touch.
The built image is based on the yolo5 image, which contains most of what you need.
The only thing we add is some Python wrapper which allows sending images for prediction over HTTP (based on Flask, again…).
The app should store client images (both original and predicted) in Amazon S3.
In order to do so, you should implement the TODO
specified in app.py
file. Your bucket name should not be hard-coded in the code, but be stored in config.json
(read this json when app.py
is launching).
Build and run this image, while publishing port 8081
.
Once the image was built successfully, and the container is running, you can communicate with the microservice directly by:
curl -X POST -F 'file=@<path-to-image>' localhost:8081/predict
Replace <path-to-image>
by a file of natural image which you want to predict objects in.
Here is an example image, and the corresponding result:
[
{
"class": "person",
"cx": 0.0770833,
"cy": 0.673675,
"height": 0.0603291,
"width": 0.0145833
},
{
"class": "umbrella",
"cx": 0.883854,
"cy": 0.620658,
"height": 0.0493601,
"width": 0.071875
},
{
"class": "car",
"cx": 0.391146,
"cy": 0.6883,
"height": 0.0530165,
"width": 0.0385417
},
{
"class": "person",
"cx": 0.555208,
"cy": 0.799817,
"height": 0.341865,
"width": 0.0583333
},
{
"class": "car",
"cx": 0.434896,
"cy": 0.718464,
"height": 0.095064,
"width": 0.0739583
},
{
"class": "car",
"cx": 0.717188,
"cy": 0.765996,
"height": 0.16819,
"width": 0.159375
}
]
The model detected 3 cars, 2 persons and 1 umbrella. Try it yourself with different images.
mongo
serviceFor the mongo service we will utilize the pre-built official MongoDB image without any custom modifications.
Please note that the mongo service should be configured to persist the data that was stored in it.
polyBot
serviceThe Telegram bot service is responsible for providing a chat-based interface for users to interact with the service. It utilizes the Telegram Bot API to receive user images and respond with detected objects.
In this microservice we will practice some Python :-) You’ll implement the bot functionality.
Bot
classUnder polybot/app.py
you are given a class called Bot
. This class implements a simple telegram bot, as follows.
The constructor __init__
gets token
arg which is the bot token you have just received from Telegram. Inside the constructor, a TeleBot
object is created. This object is an interface to Telegram API, it allows you to conveniently receive and send messages to/from Telegram.
The function self._bot_internal_handler()
is registered as an internal message handler.
This function is getting called whenever a new message will be sent to the bot via Telegram app.
The default behavior of Bot class is to “echo” the incoming messages.
Run the program and send a message to the bot via Telegram app, observe the response and get an idea of how _bot_internal_handler
and handle_message
are functioning (it’s recommended to run in debug mode with breakpoints).
QuoteBot
classIn app.py
you are given a class called QuoteBot
which inherits from Bot
.
Upon incoming messages, this bot echoing the message while quoting the original message, unless the user is asking politely not to quote.
Run this bot and check its behavior.
ObjectDetectionBot
classIn app.py
you are given a class called ObjectDetectionBot
which inherits from Bot
, again.
Upon incoming messages, this class downloads incoming images from users, and requests the yolo5
service to detect objects in the image.
The bot will then send the detected objects to the user, in any form you like.
A few notes:
ObjectDetectionBot
class, override handle_message
method and implement the needed functionality.Bot
class, you can use all of its methods (such as send_text
…).download_user_photo
, it will save you a lot of work.upload_file
function was implemented in the frontend
service. It will help you to understand how to use the requests
library to communicate with the yolo5
service.At the end, you should have 4 running microservices on your local machine. You should be able to detect objects in images sent from the Telegram Bot service, as well as the web UI.
Note that the web UI stores client detections in mongoDB (different clients are identified by their IP address). In the web UI, you can click the View your recent detection button to retrieve the last detected results. The microservice queries the information from mongoDB.
Go wild!!! add any functionality you wish…
To complete the task, you should create a Docker Compose project.
Define the services for the Telegram bot, Web UI, YOLO5 image detection, and MongoDB in a docker-compose.yaml
file.
Design the different Docker networks that each microservice in connected to, ensuring proper service isolation.
E.g. the user facing services (frontend
, polybot
) can reside in a network considered as “public”, while the internal services (mongo
, yolo5
) can reside in the “private” network.
When submitting the project, your images should be clean from CRITICAL
and HIGH
security vulnerabilities.
Use Snyk to scan the images.
Push the frontend
, yolo5
and polybot
to your account in Dockerhub or ECR.
Deploy your app in a single EC2 instance in a public subnet. Make sure the service is working as expected by communicating with it via the instance’s public IP.
Tag your EC2 instance as follows:
Name
tag key) must start with docker-project-
.Owners
with your name(s) as value.