├── .gitignore ├── Dockerfile ├── app ├── model.joblib └── server.py ├── client.py ├── readme.rst └── requirements.txt /.gitignore: -------------------------------------------------------------------------------- 1 | /.vscode -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM python:3.11 2 | 3 | WORKDIR /code 4 | 5 | COPY ./requirements.txt /code/requirements.txt 6 | 7 | RUN pip install --no-cache-dir -r /code/requirements.txt 8 | 9 | COPY ./app /code/app 10 | 11 | EXPOSE 8000 12 | 13 | CMD ["uvicorn", "app.server:app", "--host", "0.0.0.0", "--port", "8000"] -------------------------------------------------------------------------------- /app/model.joblib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DanilZherebtsov/ml-docker-flask-api/0420f81b58461a5d3d1f0ff4c68ca20a5fb21b13/app/model.joblib -------------------------------------------------------------------------------- /app/server.py: -------------------------------------------------------------------------------- 1 | from fastapi import FastAPI 2 | import joblib 3 | import numpy as np 4 | 5 | model = joblib.load('app/model.joblib') 6 | 7 | class_names = np.array(['setosa', 'versicolor', 'virginica']) 8 | 9 | app = FastAPI() 10 | 11 | @app.get('/') 12 | def read_root(): 13 | return {'message': 'Iris model API'} 14 | 15 | @app.post('/predict') 16 | def predict(data: dict): 17 | """ 18 | Predicts the class of a given set of features. 19 | 20 | Args: 21 | data (dict): A dictionary containing the features to predict. 22 | e.g. {"features": [1, 2, 3, 4]} 23 | 24 | Returns: 25 | dict: A dictionary containing the predicted class. 26 | """ 27 | features = np.array(data['features']).reshape(1, -1) 28 | prediction = model.predict(features) 29 | class_name = class_names[prediction][0] 30 | return {'predicted_class': class_name} 31 | 32 | -------------------------------------------------------------------------------- /client.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Script for inferencing the deployed model 3 | ''' 4 | 5 | import json 6 | import requests 7 | 8 | data = [[4.3, 3. , 1.1, 0.1], 9 | [5.8, 4. , 1.2, 0.2], 10 | [5.7, 4.4, 1.5, 0.4], 11 | [5.4, 3.9, 1.3, 0.4], 12 | [5.1, 3.5, 1.4, 0.3], 13 | [5.7, 3.8, 1.7, 0.3], 14 | [5.1, 3.8, 1.5, 0.3], 15 | [5.4, 3.4, 1.7, 0.2], 16 | [5.1, 3.7, 1.5, 0.4], 17 | [4.6, 3.6, 1. , 0.2], 18 | [5.1, 3.3, 1.7, 0.5], 19 | [4.8, 3.4, 1.9, 0.2]] 20 | 21 | url = 'http://0.0.0.0:8000/predict/' 22 | 23 | predictions = [] 24 | for record in data: 25 | payload = {'features': record} 26 | payload = json.dumps(payload) 27 | response = requests.post(url, data=payload) 28 | predictions.append(response.json()['predicted_class']) 29 | 30 | print(predictions) 31 | 32 | 33 | -------------------------------------------------------------------------------- /readme.rst: -------------------------------------------------------------------------------- 1 | ML model deployment example 2 | =========================== 3 | 4 | Complete code (including a trained model) to deploy and inference a machine learning model (built on the iris dataset) using Docker and FastAPI. 5 | 6 | 1. With terminal navigate to the root of this repository 7 | -------------------------------------------------------- 8 | 9 | 2. Build docker image 10 | --------------------- 11 | .. code-block:: 12 | 13 | docker build -t image_name . 14 | 15 | 3. Run container 16 | ---------------- 17 | .. code-block:: 18 | 19 | docker run --name container_name -p 8000:8000 image_name 20 | 21 | 4. Output will contain 22 | ---------------------- 23 | INFO: Uvicorn running on http://0.0.0.0:8000 24 | 25 | Use this url in chrome to see the model frontend; 26 | use http://0.0.0.0:8000/docs for testing the model in the web interface. 27 | 28 | 5. Query model 29 | -------------- 30 | 31 | #. Via web interface (chrome): 32 | http://0.0.0.0:8000/docs -> test model 33 | 34 | #. Via python client: 35 | client.py 36 | 37 | #. Via curl request: 38 | .. code-block:: 39 | 40 | curl -X POST "http://0.0.0.0:8000/predict" -H "accept: application/json" -H "Content-Type: application/json" -d '{"features": [5.1, 3.5, 1.4, 0.2]}' 41 | 42 | This repository supports a YouTube `video <>`_ -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | scikit-learn==1.3.1 2 | fastapi 3 | numpy 4 | uvicorn --------------------------------------------------------------------------------