Contents

Docker - Example Apps

List of cool system designs created with docker

Tutorial: Building an Image Classifier App with Docker Compose, FastAPI, and Scikit-learn

In this tutorial, we’ll create a web application where users can upload images to classify using a machine learning model. We’ll utilize Docker Compose to manage multiple containers, FastAPI for the API, and scikit-learn for image classification.

Step 1: Setting Up the Project Structure

Create a directory for your project and organize the structure:

mkdir image_classifier_app
cd image_classifier_app

Inside this directory, create the following structure:

image_classifier_app
│   ├── frontend
│   │   ├── Dockerfile
│   │   ├── templates/index.html
│   │   └── app.py
│   ├── backend
│   │   ├── Dockerfile
│   │   ├── classify.py
│   │   └── requirements.txt
│   ├── database
│   │   └── ...
│   ├── docker-compose.yml
│   └── README.md

Step 2: Frontend Container

frontend/Dockerfile

FROM python:3.9-slim

WORKDIR /app

COPY requirements.txt .

RUN pip install --no-cache-dir -r requirements.txt

COPY . .

EXPOSE 5000

CMD ["python", "app.py"]

frontend/app.py

from flask import Flask, render_template, request, redirect, url_for
import requests
import os

app = Flask(__name__)

@app.route('/', methods=['GET', 'POST'])
def index():
    if request.method == 'POST':
        file = request.files['file']
        if file:
            file.save(os.path.join('uploads', file.filename))
            response = requests.post('http://backend:8000/classify/', files={'file': open(f'uploads/{file.filename}', 'rb')})
            classification_result = response.json()['result']
            return render_template('index.html', result=classification_result, filename=file.filename)
    return render_template('index.html', result=None, filename=None)

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=5000)

frontend/templates/index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Image Classifier</title>
</head>
<body>
    <h1>Image Classifier</h1>
    <form method="POST" enctype="multipart/form-data">
        <input type="file" name="file">
        <button type="submit">Upload</button>
    </form>
    {% if filename %}
    <h2>Uploaded Image: {{ filename }}</h2>
    {% endif %}
    {% if result %}
    <h2>Classification Result: {{ result }}</h2>
    {% endif %}
</body>
</html>

frontend/Dockerfile

FROM tiangolo/uvicorn-gunicorn-fastapi:python3.9-slim

COPY ./app /app

RUN mkdir -p /app/uploads

RUN pip install requests

EXPOSE 80

Step 3: Building the Backend Container

backend/Dockerfile

FROM python:3.9-slim

WORKDIR /app

COPY requirements.txt .

RUN pip install --no-cache-dir -r requirements.txt

COPY . .

EXPOSE 8000

CMD ["uvicorn", "classify:app", "--host", "0.0.0.0", "--port", "8000"]

backend/classify.py

from fastapi import FastAPI, File, UploadFile
from fastapi.responses import JSONResponse
import shutil

app = FastAPI()

@app.post("/classify/")
async def classify_image(file: UploadFile = File(...)):
    try:
        # Save the uploaded file temporarily
        with open(f'./temp/{file.filename}', 'wb') as buffer:
            shutil.copyfileobj(file.file, buffer)

        # Perform image classification here using scikit-learn
        # Example:
        # classification_result = some_function_to_classify_image(f'./temp/{file.filename}')

        # Dummy response for demonstration
        classification_result = {'result': 'Some classification result'}

        return JSONResponse(content=classification_result)

    except Exception as e:
        return JSONResponse(content={'error': str(e)})

Step 4: Docker Compose Configuration

docker-compose.yml

version: '3'

services:
  frontend:
    build:
      context: ./frontend
    ports:
      - "80:80"
    depends_on:
      - backend

  backend:
    build:
      context: ./backend
    ports:
      - "8000:8000"

Step 5: Running the Application

To run the application, navigate to the project directory and execute the following command:

docker-compose up --build

Once the containers are up and running, you can access the frontend application at http://localhost in your web browser. Upload an image, and the frontend will forward it to the backend for classification. The classification result will be returned to the frontend and displayed to the user.

That’s it! You’ve successfully built an image classifier web application using Docker Compose, FastAPI, and scikit-learn. Feel free to extend and customize it further according to your requirements.