Changes to How Docker Handles Personal Authentication Tokens 

A personal access token (PAT) is a replacement for a password that can have specific scopes for repository access. Docker is improving the visibility of Docker Desktop and Hub users’ personal access tokens. Specifically, we are changing how tokens are handled across sessions between the two tools. Read on to learn more about this security improvement.

What is changing with PATs and Docker?

To authenticate with Docker Hub, the Docker CLI uses PATs. To gain authenticated access to Hub from Docker CLI after a successful login from Docker Desktop, an API creates PATs on behalf of a Desktop user. These tokens were created after a user had successfully authenticated to Docker Hub through the login flow they have active for their organization (and thus had the required bearer tokens). 

Within Docker Hub, if you navigate to your profile, select Edit > Security, you can see all of your access tokens, including ones created by Docker Desktop for the CLI on your behalf with Docker Hub (Figure 1).

Figure 1: Auto-generated and manual access tokens displayed.

Docker has improved the visibility of these auto-generated tokens, and now all PATs are displayed inside a user’s profile for their active access tokens. 

Users will be able to see if the tokens are auto-generated or if they were manually created. Users can also deactivate or delete these auto-generated session tokens just as they can with other PATs. 

For security reasons, Docker encourages users to check their active tokens regularly. These auto-generated tokens will only maintain the five most recently used tokens. Any tokens outside those five auto-generated tokens will be deleted (Figure 2).

Figure 2: Regularly check active tokens.

Note that using Docker Single Sign-On (SSO) functionality, requiring multi-factor authentication (MFA), and enforcing sign-in for Docker Desktop significantly reduces the risk of an account becoming compromised where any of a user’s personal access tokens could be exploited. 

Appropriate monitoring around your software development lifecycle (SDLC) is essential, as all images should be scanned for malware and viruses as part of secure code analysis and on an ongoing basis.  

Conclusion

Docker Hub, Docker Desktop, and the Docker CLI will continue to behave how users expect.

We encourage you to use the latest Docker Desktop and Docker CLI versions to get the newest features and security releases.

We also encourage you to use your new visibility into these PATs for Docker CLI and include all of your PATs in the regular security review for your organization and Docker accounts. 

As always, we encourage security best practices for Docker users and will continue strengthening Docker’s tooling as we update and add new features.

Learn more

Learn about Docker SSO.

Enable two-factor authentication.

Enforce Docker Desktop sign-in.

Get the latest release of Docker Desktop.

Try Docker Scout.

Vote on what’s next! Check out our public roadmap.

Have questions? The Docker community is here to help.

New to Docker? Get started.

Quelle: https://blog.docker.com/feed/

How IKEA Retail Standardizes Docker Images for Efficient Machine Learning Model Deployment

What do Docker and IKEA Retail have in common? Both companies have changed how products are built, stored, and shipped. In IKEA Retail’s case, they created the market of flat-packed furniture items, which made everything from shipping, warehousing, and delivering their furniture to the end location much easier and more cost effective. This parallels what Docker has done for developers. Docker has changed the way that software is built, shipped, and stored, with Docker Images taking up much less space “shelf” space. 

In this post, contributing authors Karan Honavar and Fernando Dorado Rueda from IKEA Retail walk through their MLOps solution, built with Docker.

Machine learning (ML) deployment, the act of shifting an ML model from the developmental stage to a live production environment, is paramount to translating complex algorithms into real-world solutions. Yet, this intricate process isn’t without its challenges, including:

Complexity and opacity: With ML models often veiled in complexity, deciphering their logic can be taxing. This obscurity impedes trust and complicates the explanation of decisions to stakeholders.

Adaptation to changing data patterns: The shifting landscape of real-world data can deviate from training sets, causing “concept drift.” Addressing this requires vigilant retraining, an arduous task that wastes time and resources.

Real-time data processing: Handling the deluge of data necessary for accurate predictions can burden systems and impede scalability.

Varied deployment methods: Whether deployed locally, in the cloud, or via web services, each method brings unique challenges, adding layers of complexity to an already intricate procedure.

Security and compliance: Ensuring that ML models align with rigorous regulations, particularly around private information, necessitates a focus on lawful implementation.

Ongoing maintenance and monitoring: The journey doesn’t end with deployment. Constant monitoring is vital to sustain the model’s health and address emerging concerns.

These factors represent substantial obstacles, but they are not insurmountable. We can streamline the journey from the laboratory to the real world by standardizing Docker images for efficient ML model deployment. 

This article will delve into the creation, measurement, deployment, and interaction with Dockerized ML models. We will demystify the complexities and demonstrate how Docker can catalyze cutting-edge concepts into tangible benefits.

Standardization deployment process via Docker

In the dynamic realm of today’s data-driven enterprises, such as our case at IKEA Retail, the multitude of tools and deployment strategies serves both as a boon and a burden. Innovation thrives, but so too does complexity, giving rise to inconsistency and delays. The antidote? Standardization. It’s more than just a buzzword; it’s a method to pave the way to efficiency, compliance, and seamless integration.

Enter Docker, the unsung hero in this narrative. In the evolving field of ML deployment, Docker offers agility and uniformity. It has reshaped the landscape by offering a consistent environment from development to production. The beauty of Docker lies in its containerization technology, enabling developers to wrap up an application with all the parts it needs, such as libraries and other dependencies, and ship it all out as one package.

At IKEA Retail, diverse teams — including hybrid data scientist teams and R&D units — conceptualize and develop models, each selecting drivers and packaging libraries according to their preferences and requirements. Although virtual environments provide a certain level of support, they can also present compatibility challenges when transitioning to a production environment. 

This is where Docker becomes an essential tool in our daily operations, offering simplification and a marked acceleration in the development and deployment process. Here are key advantages:

Portability: With Docker, the friction between different computing environments melts away. A container runs uniformly, regardless of where it’s deployed, bringing robustness to the entire pipeline.

Efficiency: Docker’s lightweight nature ensures that resources are optimally utilized, thereby reducing overheads and boosting performance.

Scalability: With Docker, scaling your application or ML models horizontally becomes a breeze. It aligns perfectly with the orchestrated symphony that large-scale deployment demands.

Then, there’s Seldon-Core, a solution chosen by IKEA Retail’s forward-thinking MLOps (machine learning operations) team. Why? Because it transforms ML models into production-ready microservices, regardless of the model’s origin (TensorFlow, PyTorch, H2O, etc.) or language (Python, Java, etc.). But that’s not all. Seldon-Core scales precisely, enabling everything from advanced metrics and logging to explainers and A/B testing.

This combination of Docker and Seldon-Core forms the heart of our exploration today. Together, they sketch the blueprint for a revolution in ML deployment. This synergy is no mere technical alliance; it’s a transformative collaboration that redefines deploying, monitoring, and interacting with ML models.

Through the looking glass of IKEA Retail’s experience, we’ll unearth how this robust duo — Docker and Seldon-Core — can turn a convoluted task into a streamlined, agile operation and how you can harness real-time metrics for profound insights.

Dive into this new MLOps era with us. Unlock efficiency, scalability, and a strategic advantage in ML production. Your innovation journey begins here, with Docker and Seldon-Core leading the way. This is more than a solution; it’s a paradigm shift.

In the rest of this article, we will cover deployment steps, including model preparation, encapsulating the model into an Docker image, and testing. Let’s get started.

Prerequisites

The following items must be present to replicate this example:

Docker: Ensure Docker is up and running, easily achievable through solutions like Docker Desktop

Python: Have a local installation at the ready (+3.7)

Model preparation

Model training and simple evaluation

Embarking on the journey to deploying an ML model is much like crafting a masterpiece: The canvas must be prepared, and every brushstroke must be deliberate. However, the focus of this exploration isn’t the art itself but rather the frame that holds it — the standardization of ML models, regardless of their creation or the frameworks used.

The primary objective of this demonstration is not to augment the model’s performance but rather to elucidate the seamless transition from local development to production deployment. It is imperative to note that the methodology we present is universally applicable across different models and frameworks. Therefore, we have chosen a straightforward model as a representative example. This choice is intentional, allowing readers to concentrate on the underlying process flows, which can be readily adapted to more sophisticated models that may require refined hyperparameter tuning and meticulous model selection. 

By focusing on these foundational principles, we aim to provide a versatile and accessible guide that transcends the specificities of individual models or use cases. Let’s delve into this process.

To align with our ethos of transparency and consumer privacy and to facilitate your engagement with this approach, a public dataset is employed for a binary classification task.

In the following code excerpt, you’ll find the essence of our training approach, reflecting how we transform raw data into a model ready for real-world challenges:

import os
import pickle
import numpy as np
import pandas as pd
from sklearn import datasets
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LogisticRegression, Perceptron
from sklearn.metrics import accuracy_score, precision_score, recall_score, f1_score

# Load the breast cancer dataset
X, y = datasets.load_breast_cancer(return_X_y=True)

# Split the dataset into training and testing sets
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.9, random_state=0)

# Combine X_test and y_test into a single DataFrame
X_test_df = pd.DataFrame(X_test, columns=[f"feature_{i}" for i in range(X_test.shape[1])])
y_test_df = pd.DataFrame(y_test, columns=["target"])

df_test = pd.concat([X_test_df, y_test_df], axis=1)

# Define the path to store models
model_path = "models/"

# Create the folder if it doesn’t exist
if not os.path.exists(model_path):
os.makedirs(model_path)

# Define a list of classifier parameters
parameters = [
{"clf": LogisticRegression(solver="liblinear", multi_class="ovr"), "name": f"{model_path}/binary-lr.joblib"},
{"clf": Perceptron(eta0=0.1, random_state=0), "name": f"{model_path}/binary-percept.joblib"},
]

# Iterate through each parameter configuration
for param in parameters:
clf = param["clf"] # Retrieve the classifier from the parameter dictionary
clf.fit(X_train, y_train) # Fit the classifier on the training data
# Save the trained model to a file using pickle
model_filename = f"{param[’name’]}"
with open(model_filename, ‘wb’) as model_file:
pickle.dump(clf, model_file)
print(f"Model saved in {model_filename}")

# Simple Model Evaluation
model_path = ‘models/binary-lr.joblib’
with open(model_path, ‘rb’) as model_file:
loaded_model = pickle.load(model_file)

# Make predictions using the loaded model
predictions = loaded_model.predict(X_test)

# Calculate metrics (accuracy, precision, recall, f1-score)
accuracy = accuracy_score(y_test, predictions)
precision = precision_score(y_test, predictions)
recall = recall_score(y_test, predictions)
f1 = f1_score(y_test, predictions)

Model class creation

With the model files primed, the task at hand shifts to the crafting of the model class — an essential architectural element that will later reside within the Docker image. Like a skilled sculptor, we must shape this class, adhering to the exacting standards proposed by Seldon:

import joblib
import logging

class Score:
"""
Class to hold metrics for binary classification, including true positives (TP), false positives (FP),
true negatives (TN), and false negatives (FN).
"""
def __init__(self, TP=0, FP=0, TN=0, FN=0):
self.TP = TP # True Positives
self.FP = FP # False Positives
self.TN = TN # True Negatives
self.FN = FN # False Negatives

class DockerModel:
"""
Class for loading and predicting using a pre-trained model, handling feedback to update metrics,
and providing those metrics.
"""
result = {} # Dictionary to store input data

def __init__(self, model_name="models/binary-lr.joblib"):
"""
Initialize DockerModel with metrics and model name.
:param model_name: Path to the pre-trained model.
"""
self.scores = Score(0, 0, 0, 0)
self.loaded = False
self.model_name = model_name

def load(self):
"""
Load the model from the provided path.
"""
self.model = joblib.load(self.model_name)
logging.info(f"Model {self.model_name} Loaded")

def predict(self, X, features_names=None, meta=None):
"""
Predict the target using the loaded model.
:param X: Features for prediction.
:param features_names: Names of the features, optional.
:param meta: Additional metadata, optional.
:return: Predicted target values.
"""
self.result[’shape_input_data’] = str(X.shape)
logging.info(f"Received request: {X}")
if not self.loaded:
self.load()
self.loaded = True
predictions = self.model.predict(X)
return predictions

def send_feedback(self, features, feature_names, reward, truth, routing=""):
"""
Provide feedback on predictions and update the metrics.
:param features: Features used for prediction.
:param feature_names: Names of the features.
:param reward: Reward signal, not used in this context.
:param truth: Ground truth target values.
:param routing: Routing information, optional.
:return: Empty list as return value is not used.
"""
predicted = self.predict(features)
logging.info(f"Predicted: {predicted[0]}, Truth: {truth[0]}")
if int(truth[0]) == 1:
if int(predicted[0]) == int(truth[0]):
self.scores.TP += 1
else:
self.scores.FN += 1
else:
if int(predicted[0]) == int(truth[0]):
self.scores.TN += 1
else:
self.scores.FP += 1
return [] # Ignore return statement as its not used

def calculate_metrics(self):
"""
Calculate the accuracy, precision, recall, and F1-score.
:return: accuracy, precision, recall, f1_score
"""
total_samples = self.scores.TP + self.scores.TN + self.scores.FP + self.scores.FN

# Check if there are any samples to avoid division by zero
if total_samples == 0:
logging.warning("No samples available to calculate metrics.")
return 0, 0, 0, 0 # Return zeros for all metrics if no samples

accuracy = (self.scores.TP + self.scores.TN) / total_samples

# Check if there are any positive predictions to calculate precision
positive_predictions = self.scores.TP + self.scores.FP
precision = self.scores.TP / positive_predictions if positive_predictions != 0 else 0

# Check if there are any actual positives to calculate recall
actual_positives = self.scores.TP + self.scores.FN
recall = self.scores.TP / actual_positives if actual_positives != 0 else 0

# Check if precision and recall are non-zero to calculate F1-score
if precision + recall == 0:
f1_score = 0
else:
f1_score = 2 * (precision * recall) / (precision + recall)

# Return the calculated metrics
return accuracy, precision, recall, f1_score

def metrics(self):
"""
Generate metrics for monitoring.
:return: List of dictionaries containing accuracy, precision, recall, and f1_score.
"""
accuracy, precision, recall, f1_score = self.calculate_metrics()
return [
{"type": "GAUGE", "key": "accuracy", "value": accuracy},
{"type": "GAUGE", "key": "precision", "value": precision},
{"type": "GAUGE", "key": "recall", "value": recall},
{"type": "GAUGE", "key": "f1_score", "value": f1_score},
]

def tags(self):
"""
Retrieve metadata when generating predictions
:return: Dictionary the intermediate information
"""
return self.result

Let’s delve into the details of the functions and classes within the DockerModel class that encapsulates these four essential aspects:

Loading and predicting:

load(): This function is responsible for importing the pretrained model from the provided path. It’s usually called internally before making predictions to ensure the model is available.

predict(X, features_names=None, meta=None): This function deploys the loaded model to make predictions. It takes in the input features X, optional features_names, and optional metadata meta, returning the predicted target values.

Feedback handling:

send_feedback(features, feature_names, reward, truth, routing=””): This function is vital in adapting the model to real-world feedback. It accepts the input data, truth values, and other parameters to assess the model’s performance. The feedback updates the model’s understanding, and the metrics are calculated and stored for real-time analysis. This facilitates continuous retraining of the model.

Metrics calculation:

calculate_metrics(): This function calculates the essential metrics of accuracy, precision, recall, and F1-score. These metrics provide quantitative insights into the model’s performance, enabling constant monitoring and potential improvement.

Score class: This auxiliary class is used within the DockerModel to hold metrics for binary classification, including true positives (TP), false positives (FP), true negatives (TN), and false negatives (FN). It helps keep track of these parameters, which are vital for calculating the aforementioned metrics.

Monitoring assistance:

metrics(): This function generates the metrics for model monitoring. It returns a list of dictionaries containing the calculated accuracy, precision, recall, and F1 score. These metrics are compliant with Prometheus Metrics, facilitating real-time monitoring and analysis.

tags(): This function is designed to retrieve custom metadata data when generating predictions, aiding in monitoring and debugging. It returns a dictionary, which can help track and understand the nature of the requests.

Together, these functions and classes form a cohesive and robust structure that supports the entire lifecycle of an ML model. From the moment of inception (loading and predicting) through its growth (feedback handling) and evaluation (metrics calculation), to its continuous vigilance (monitoring assistance), the architecture is designed to standardize and streamline the process of deploying and maintaining ML models in a real-world production environment.

This model class is more than code; it’s the vessel that carries our ML model from a local environment to the vast sea of production. It’s the vehicle for standardization, unlocking efficiency and consistency in deploying models.

At this stage, we’ve prepared the canvas and outlined the masterpiece. Now, it’s time to dive deeper and explore how this model is encapsulated into a Docker image, an adventure that blends technology and strategy to redefine ML deployment. 

Testing model locally

Before venturing into creating a Docker image, testing the model locally is vital. This step acts as a rehearsal before the main event, providing a chance to ensure that the model is performing as expected with the testing data.

The importance of local testing lies in its ability to catch issues early, avoiding potential complications later in the deployment process. Following the example code provided below, it can confirm that the model is ready for its next phase if it provides the expected prediction in the expected format:

from DockerModel import DockerModel
demoModel = DockerModel()
demoModel.predict(X_test) # Can take the entire testing dataset or individual predictions

The expected output should match the format of the class labels you anticipate from the model. If everything works correctly, you’re assured that the model is well prepared for the next grand step: encapsulation within a Docker image.

Local testing is more than a technical process; it’s a quality assurance measure that stands as a gatekeeper, ensuring that only a well-prepared model moves forward. It illustrates the meticulous care taken in the deployment process, reflecting a commitment to excellence that transcends code and resonates with the core values of standardization and efficiency.

With the local testing accomplished, we stand on the threshold of a new frontier: creating the Docker image. Let’s continue this exciting journey, knowing each step is a stride toward innovation and mastery in ML deployment.

Encapsulating the model into a Docker image

In our IKEA Retail MLOps view, a model is not simply a collection of code. Rather, it is a sophisticated assembly comprising code, dependencies, and ML artifacts, all encapsulated within a versioned and registered Docker image. This composition is carefully designed, reflecting the meticulous planning of the physical infrastructure.

What is Docker’s role in MLOps?

Docker plays a vital role in MLOps, providing a standardized environment that streamlines the transition from development to production:

Streamlining deployment: Docker containers encapsulate everything an ML model needs to run, easing the deployment process.

Facilitating collaboration: Using Docker, data scientists and engineers can ensure that models and their dependencies remain consistent across different stages of development.

Enhancing model reproducibility: Docker provides a uniform environment that enhances the reproducibility of models, a critical aspect in machine learning.

Integrating with orchestration tools: Docker can be used with orchestration platforms like Kubernetes, enabling automated deployment, scaling, and management of containerized applications.

Docker and containerization are more than technology tools; they catalyze innovation and efficiency in MLOps. Ensuring consistency, scalability and agility, Docker unlocks new potential and opens the way for a more agile and robust ML deployment process. Whether you are a developer, a data scientist, or an IT professional, understanding Docker is critical to navigating the complex and multifaceted landscape of modern data-driven applications.

Dockerfile creation

Creating a Dockerfile is like sketching the architectural plan of a building. It outlines the instructions for creating a Docker image to run the application in a coherent, isolated environment. This design ensures that the entire model — including its code, dependencies, and unique ML artifacts — is treated as a cohesive entity, aligning with the overarching vision of IKEA Retail’s MLOps approach.

In our case, we have created a Dockerfile with the express purpose of encapsulating not only the code but all the corresponding artifacts of the model. This deliberate design facilitates a smooth transition to production, effectively bridging the gap between development and deployment.

We used the following Dockerfile for this demonstration, which represents a tangible example of how IKEA Retail’s MLOps approach is achieved through thoughtful engineering and strategic implementation.

# Use an official Python runtime as a parent image.
# Using a slim image for a smaller final size and reduced attack surface.
FROM python:3.9-slim

# Set the maintainer label for metadata.
LABEL maintainer="fernandodorado.rueda@ingka.com"

# Set environment variables for a consistent build behavior.
# Disabling the buffer helps to log messages synchronously.
ENV PYTHONUNBUFFERED=1

# Set a working directory inside the container to store all our project files.
WORKDIR /app

# First, copy the requirements file to leverage Docker’s cache for dependencies.
# By doing this first, changes to the code will not invalidate the cached dependencies.
COPY requirements.txt requirements.txt

# Install the required packages listed in the requirements file.
# It’s a good practice to include the –no-cache-dir flag to prevent the caching of dependencies
# that aren’t necessary for executing the application.
RUN pip install –no-cache-dir -r requirements.txt

# Copy the rest of the code and model files into the image.
COPY DockerModel.py DockerModel.py
COPY models/ models/

# Expose ports that the application will run on.
# Port 5000 for GRPC
# Port 9000 for REST
EXPOSE 5000 9000

# Set environment variables used by the application.
ENV MODEL_NAME DockerModel
ENV SERVICE_TYPE MODEL

# Change the owner of the directory to user 8888 for security purposes.
# It can prevent unauthorised write access by the application itself.
# Make sure to run the application as this non-root user later if applicable.
RUN chown -R 8888 /app

# Use the exec form of CMD so that the application you run will receive UNIX signals.
# This is helpful for graceful shutdown.
# Here we’re using seldon-core-microservice to serve the model.
CMD exec seldon-core-microservice $MODEL_NAME –service-type $SERVICE_TYPE

This Dockerfile contains different parts:

FROM python:3.9-slim: This line chooses the official Python 3.9 slim image as the parent image. It is favored for its reduced size and attack surface, enhancing both efficiency and security.

LABEL maintainer=”fernandodorado.rueda@ingka.com”: A metadata label that specifies the maintainer of the image, providing contact information.

ENV PYTHONUNBUFFERED=1: Disabling Python’s output buffering ensures that log messages are emitted synchronously, aiding in debugging and log analysis.

WORKDIR /app: Sets the working directory inside the container to /app, a centralized location for all project files.

COPY requirements.txt requirements.txt: Copies the requirements file into the image. Doing this before copying the rest of the code leverages Docker’s caching mechanism, making future builds faster. This file must contain the “seldon-core” package:

pandas==1.3.5
requests==2.28.1
numpy==1.20
seldon-core==1.14.1
scikit-learn==1.0.2

RUN pip install –no-cache-dir -r requirements.txt: Installs required packages as listed in the requirements file. The flag -no-cache-dir prevents unnecessary caching of dependencies, reducing the image size.

COPY DockerModel.py DockerModel.py: Copies the main Python file into the image.

COPY models/ models/: Copies the model files into the image.

EXPOSE 5000 9000: Exposes ports 5000 (GRPC) and 9000 (REST), allowing communication with the application inside the container.

ENV MODEL_NAME DockerModel: Sets the environment variable for the model name.

ENV SERVICE_TYPE MODEL: Sets the environment variable for the service type.

RUN chown -R 8888 /app: Changes the owner of the directory to user 8888. Running the application as a non-root user helps mitigate the risk of unauthorized write access.

CMD exec seldon-core-microservice $MODEL_NAME –service-type $SERVICE_TYPE: Executes the command to start the service using seldon-core-microservice. It also includes the model name and service type as parameters. Using exec ensures the application receives UNIX signals, facilitating graceful shutdown.

Building and pushing Docker image

1. Installing Docker Desktop

If not already installed, Docker Desktop is recommended for this task. Docker Desktop provides a graphical user interface that simplifies the process of building, running, and managing Docker containers. Docker Desktop also supports Kubernetes, offering an easy way to create a local cluster.

2. Navigating to the Project directory

Open a terminal or command prompt.

Navigate to the folder where the Dockerfile and other necessary files are located.

3. Building the Image

Execute the command: docker build . -t docker-model:1.0.0.

docker build . instructs Docker to build the image using the current directory (.).

-t docker-model:1.0.0 assigns a name (docker-model) and tag (1.0.0) to the image.

The build process will follow the instructions defined in the Dockerfile, creating a Docker image encapsulating the entire environment needed to run the model.

4. Pushing the image

If needed, the image can be pushed to a container registry like Docker Hub, or a private registry within an organization.

For this demonstration, the image is being kept in the local container registry, simplifying the process and removing the need for authentication with an external registry.

Deploy ML model using Docker: Unleash it into the world

Once the Docker image is built, running it is relatively straightforward. Let’s break down this process:

docker run –rm –name docker-model -p 9000:9000 docker-model:1.0.0

Components of the command:

docker run: This is the base command to run a Docker container.

-rm: This flag ensures that the Docker container is automatically removed once it’s stopped. It helps keep the environment clean, especially when you run containers for testing or short-lived tasks.

-name docker-model: Assigns a name to the running container.

p 9000:9000: This maps port 9000 on the host machine to port 9000 on the Docker container. The format is p <host_port>:<container_port>. Because the Dockerfile mentions that the application will be exposing ports 5000 for GRPC and 9000 for REST, this command makes sure the REST endpoint is available to external users or applications through port 9000 on the host.

docker-model:1.0.0: This specifies the name and tag of the Docker image to run. docker-model is the name, and 1.0.0 is the version tag we assigned during the build process.

What happens next

On executing the command, Docker will initiate a container instance from the docker-model:1.0.0 image.

The application within the Docker container will start and begin listening for requests on port 9000 (as specified).

With the port mapping, any incoming requests on port 9000 of the host machine will be forwarded to port 9000 of the Docker container.

The application can now be accessed and interacted with as if it were running natively on the host machine.

Test deployed model using Docker

With the Docker image in place, it’s time to see the model in action.

Generate predictions

The path from model to prediction is a delicate process, requiring an understanding of the specific input-output type that Seldon accommodates (e.g., ndarray, JSON data, STRDATA).

In our scenario, the model anticipates an array, and thus, the key in our payload is “ndarray.” Here’s how we orchestrate this:

import requests
import json

URL = "http://localhost:9000/api/v1.0/predictions"

def send_prediction_request(data):

# Create the headers for the request
headers = {‘Content-Type': ‘application/json’}

try:
# Send the POST request
response = requests.post(URL, headers=headers, json=data)

# Check if the request was successful
response.raise_for_status() # Will raise HTTPError if the HTTP request returned an unsuccessful status code

# If successful, return the JSON data
return response.json()
except requests.ConnectionError:
raise Exception("Failed to connect to the server. Is it running?")
except requests.Timeout:
raise Exception("Request timed out. Please try again later.")
except requests.RequestException as err:
# For any other requests exceptions, re-raise it
raise Exception(f"An error occurred with your request: {err}")

X_test

# Define the data payload (We can also use X_test[0:1].tolist() instead of the raw array)
data_payload = {
"data": {
"ndarray": [
[
1.340e+01, 2.052e+01, 8.864e+01, 5.567e+02, 1.106e-01, 1.469e-01,
1.445e-01, 8.172e-02, 2.116e-01, 7.325e-02, 3.906e-01, 9.306e-01,
3.093e+00, 3.367e+01, 5.414e-03, 2.265e-02, 3.452e-02, 1.334e-02,
1.705e-02, 4.005e-03, 1.641e+01, 2.966e+01, 1.133e+02, 8.444e+02,
1.574e-01, 3.856e-01, 5.106e-01, 2.051e-01, 3.585e-01, 1.109e-01
]
]
}
}

# Get the response and print it
try:
response = send_prediction_request(data_payload)
pretty_json_response = json.dumps(response, indent=4)
print(pretty_json_response)
except Exception as err:
print(err)

The prediction of our model will be similar to this dictionary:

{
"data": {
"names": [],
"ndarray": [
0
]
},
"meta": {
"metrics": [
{
"key": "accuracy",
"type": "GAUGE",
"value": 0
},
{
"key": "precision",
"type": "GAUGE",
"value": 0
},
{
"key": "recall",
"type": "GAUGE",
"value": 0
},
{
"key": "f1_score",
"type": "GAUGE",
"value": 0
}
],
"tags": {
"shape_input_data": "(1, 30)"
}
}
}

The response from the model will contain several keys:

“data”: Provides the generated output by our model. In our case, it’s the predicted class.

“meta”: Contains metadata and model metrics. It shows the actual values of the classification metrics, including accuracy, precision, recall, and f1_score.

“tags”: Contains intermediate metadata. This could include anything you want to track, such as the shape of the input data.

The structure outlined above ensures that not only can we evaluate the final predictions, but we also gain insights into intermediate results. These insights can be instrumental in understanding predictions and debugging any potential issues.

This stage marks a significant milestone in our journey from training a model to deploying and testing it within a Docker container. We’ve seen how to standardize an ML model and how to set it up for real-world predictions. With this foundation, you’re well-equipped to scale, monitor, and further integrate this model into a full-fledged production environment.

Send feedback in real-time and calculate metrics

The provisioned /feedback endpoint facilitates this learning by allowing truth values to be sent back to the model once they are available. As these truth values are received, the model’s metrics are updated and can be scraped by other tools for real-time analysis and monitoring. In the following code snippet, we iterate over the test dataset and send the truth value to the /feedback endpoint, using a POST request:

import requests
import json

URL = "http://localhost:9000/api/v1.0/feedback"

def send_prediction_feedback(data):

# Create the headers for the request
headers = {‘Content-Type': ‘application/json’}

try:
# Send the POST request
response = requests.post(URL, headers=headers, json=data)

# Check if the request was successful
response.raise_for_status() # Will raise HTTPError if the HTTP request returned an unsuccessful status code

# If successful, return the JSON data
return response.json()
except requests.ConnectionError:
raise Exception("Failed to connect to the server. Is it running?")
except requests.Timeout:
raise Exception("Request timed out. Please try again later.")
except requests.RequestException as err:
# For any other requests exceptions, re-raise it
raise Exception(f"An error occurred with your request: {err}")

for i in range(len(X_test)):
payload = {‘request': {‘data': {‘ndarray': [X_test[i].tolist()]}}, ‘truth': {‘data': {‘ndarray': [int(y_test[i])]}}}

# Get the response and print it
try:
response = send_prediction_feedback(payload)
pretty_json_response = json.dumps(response, indent=4) # Pretty-print JSON
print(pretty_json_response)
except Exception as err:
print(err)

After processing the feedback, the model calculates and returns key metrics, including accuracy, precision, recall, and F1-score. These metrics are then available for analysis:

{
"data": {
"ndarray": []
},
"meta": {
"metrics": [
{
"key": "accuracy",
"type": "GAUGE",
"value": 0.92607003
},
{
"key": "precision",
"type": "GAUGE",
"value": 0.9528302
},
{
"key": "recall",
"type": "GAUGE",
"value": 0.9294478
},
{
"key": "f1_score",
"type": "GAUGE",
"value": 0.9409938
}
],
"tags": {
"shape_input_data": "(1, 30)"Ω
}
}
}

What makes this approach truly powerful is that the model’s evolution is no longer confined to the training phase. Instead, it’s in a continual state of learning, adjustment, and refinement, based on real-world feedback.

This way, we’re not just deploying a static prediction engine but fostering an evolving intelligent system that can better align itself with the changing landscape of data it interprets. It’s a holistic approach to machine learning deployment that encourages continuous improvement and real-time adaptation.

Conclusions

At IKEA Retail, Docker has become an indispensable element in our daily MLOps activities, serving as a catalyst that accelerates the development and deployment of models, especially when transitioning to production. The transformative impact of Docker unfolds through a spectrum of benefits that not only streamlines our workflow but also fortifies it:

Standardization: Docker orchestrates a consistent environment during the development and deployment of any ML model, fostering uniformity and coherence across the lifecycle.

Compatibility: With support for diverse environments and seamless multi-cloud or on-premise integration, Docker bridges gaps and ensures a harmonious workflow.

Isolation: Docker ensures that applications and resources are segregated, offering an isolated environment that prioritizes efficiency and integrity.

Security: Beyond mere isolation, Docker amplifies security by completely segregating applications from each other. This robust separation empowers us with precise control over traffic flow and management, laying a strong foundation of trust.

These attributes translate into tangible advantages in our MLOps journey, sculpting a landscape that’s not only innovative but also robust:

Agile development and deployment environment: Docker ignites a highly responsive development and deployment environment, enabling seamless creation, updating, and deployment of ML models.

Optimized resource utilization: Utilize compute/GPU resources efficiently within a shared model, maximizing performance without compromising flexibility.

Scalable deployment: Docker’s architecture allows for the scalable deployment of ML models, adapting effortlessly to growing demands.

Smooth release cycles: Integrating seamlessly with our existing CI/CD pipelines, Docker smoothens the model release cycle, ensuring a continuous flow of innovation.

Effortless integration with monitoring tools: Docker’s compatibility extends to monitoring stacks like Prometheus + Grafana, creating a cohesive ecosystem fully aligned with our MLOps approach when creating and deploying models in production.

The convergence of these benefits elevates IKEA Retail’s MLOps strategy, transforming it into a symphony of efficiency, security, and innovation. Docker is not merely a tool: Docker is a philosophy that resonates with our pursuit of excellence. Docker is the bridge that connects creativity with reality, and innovation with execution.

In the complex world of ML deployment, we’ve explored a path less trodden but profoundly rewarding. We’ve tapped into the transformative power of standardization, unlocking an agile and responsive way to deploy and engage with ML models in real-time.

But this is not a conclusion; it’s a threshold. New landscapes beckon, brimming with opportunities for growth, exploration, and innovation. The following steps will continue the current approach: 

Scaling with Kubernetes: Unleash the colossal potential of Kubernetes, a beacon of flexibility and resilience, guiding you to a horizon of unbounded possibilities.

Applying real-time monitoring and alerting systems based on open source technologies, such as Prometheus and Grafana.

Connecting a data-drift detector for real-time detection: Deployment and integration of drift detectors to detect changes in data in real-time.

We hope this exploration will empower you to redefine your paths, ignite new ideas, and push the boundaries of what’s possible. The gateway to an extraordinary future is open, and the key is in our hands.

Learn more

Read our Docker AI/ML article collection.

Visit Docker Hub, the world’s largest container image registry.

Get the latest release of Docker Desktop.

Vote on what’s next! Check out our public roadmap.

Have questions? The Docker community is here to help.

New to Docker? Get started.

Quelle: https://blog.docker.com/feed/

How IKEA Standardizes Docker Images for Efficient Machine Learning Model Deployment

What do Docker and IKEA have in common? Both companies have changed how products are built, stored, and shipped. In IKEA’s case, they created the market of flat-packed furniture items, which made everything from shipping, warehousing, and delivering their furniture to the end location much easier and more cost effective. This parallels what Docker has done for developers. Docker has changed the way that software is built, shipped, and stored, with Docker Images taking up much less space “shelf” space. 

In this post, contributing authors Karan Honavar and Fernando Dorado Rueda from IKEA walk through their MLOps solution, built with Docker.

Machine learning (ML) deployment, the act of shifting an ML model from the developmental stage to a live production environment, is paramount to translating complex algorithms into real-world solutions. Yet, this intricate process isn’t without its challenges, including:

Complexity and opacity: With ML models often veiled in complexity, deciphering their logic can be taxing. This obscurity impedes trust and complicates the explanation of decisions to stakeholders.

Adaptation to changing data patterns: The shifting landscape of real-world data can deviate from training sets, causing “concept drift.” Addressing this requires vigilant retraining, an arduous task that wastes time and resources.

Real-time data processing: Handling the deluge of data necessary for accurate predictions can burden systems and impede scalability.

Varied deployment methods: Whether deployed locally, in the cloud, or via web services, each method brings unique challenges, adding layers of complexity to an already intricate procedure.

Security and compliance: Ensuring that ML models align with rigorous regulations, particularly around private information, necessitates a focus on lawful implementation.

Ongoing maintenance and monitoring: The journey doesn’t end with deployment. Constant monitoring is vital to sustain the model’s health and address emerging concerns.

These factors represent substantial obstacles, but they are not insurmountable. We can streamline the journey from the laboratory to the real world by standardizing Docker images for efficient ML model deployment. 

This article will delve into the creation, measurement, deployment, and interaction with Dockerized ML models. We will demystify the complexities and demonstrate how Docker can catalyze cutting-edge concepts into tangible benefits.

Standardization deployment process via Docker

In the dynamic realm of today’s data-driven enterprises, such as our case at IKEA, the multitude of tools and deployment strategies serves both as a boon and a burden. Innovation thrives, but so too does complexity, giving rise to inconsistency and delays. The antidote? Standardization. It’s more than just a buzzword; it’s a method to pave the way to efficiency, compliance, and seamless integration.

Enter Docker, the unsung hero in this narrative. In the evolving field of ML deployment, Docker offers agility and uniformity. It has reshaped the landscape by offering a consistent environment from development to production. The beauty of Docker lies in its containerization technology, enabling developers to wrap up an application with all the parts it needs, such as libraries and other dependencies, and ship it all out as one package.

At IKEA, diverse teams — including hybrid data scientist teams and R&D units — conceptualize and develop models, each selecting drivers and packaging libraries according to their preferences and requirements. Although virtual environments provide a certain level of support, they can also present compatibility challenges when transitioning to a production environment. 

This is where Docker becomes an essential tool in our daily operations, offering simplification and a marked acceleration in the development and deployment process. Here are key advantages:

Portability: With Docker, the friction between different computing environments melts away. A container runs uniformly, regardless of where it’s deployed, bringing robustness to the entire pipeline.

Efficiency: Docker’s lightweight nature ensures that resources are optimally utilized, thereby reducing overheads and boosting performance.

Scalability: With Docker, scaling your application or ML models horizontally becomes a breeze. It aligns perfectly with the orchestrated symphony that large-scale deployment demands.

Then, there’s Seldon-Core, a solution chosen by IKEA’s forward-thinking MLOps (machine learning operations) team. Why? Because it transforms ML models into production-ready microservices, regardless of the model’s origin (TensorFlow, PyTorch, H2O, etc.) or language (Python, Java, etc.). But that’s not all. Seldon-Core scales precisely, enabling everything from advanced metrics and logging to explainers and A/B testing.

This combination of Docker and Seldon-Core forms the heart of our exploration today. Together, they sketch the blueprint for a revolution in ML deployment. This synergy is no mere technical alliance; it’s a transformative collaboration that redefines deploying, monitoring, and interacting with ML models.

Through the looking glass of IKEA’s experience, we’ll unearth how this robust duo — Docker and Seldon-Core — can turn a convoluted task into a streamlined, agile operation and how you can harness real-time metrics for profound insights.

Dive into this new MLOps era with us. Unlock efficiency, scalability, and a strategic advantage in ML production. Your innovation journey begins here, with Docker and Seldon-Core leading the way. This is more than a solution; it’s a paradigm shift.

In the rest of this article, we will cover deployment steps, including model preparation, encapsulating the model into an Docker image, and testing. Let’s get started.

Prerequisites

The following items must be present to replicate this example:

Docker: Ensure Docker is up and running, easily achievable through solutions like Docker Desktop

Python: Have a local installation at the ready (+3.7)

Model preparation

Model training and simple evaluation

Embarking on the journey to deploying an ML model is much like crafting a masterpiece: The canvas must be prepared, and every brushstroke must be deliberate. However, the focus of this exploration isn’t the art itself but rather the frame that holds it — the standardization of ML models, regardless of their creation or the frameworks used.

The primary objective of this demonstration is not to augment the model’s performance but rather to elucidate the seamless transition from local development to production deployment. It is imperative to note that the methodology we present is universally applicable across different models and frameworks. Therefore, we have chosen a straightforward model as a representative example. This choice is intentional, allowing readers to concentrate on the underlying process flows, which can be readily adapted to more sophisticated models that may require refined hyperparameter tuning and meticulous model selection. 

By focusing on these foundational principles, we aim to provide a versatile and accessible guide that transcends the specificities of individual models or use cases. Let’s delve into this process.

To align with our ethos of transparency and consumer privacy and to facilitate your engagement with this approach, a public dataset is employed for a binary classification task.

In the following code excerpt, you’ll find the essence of our training approach, reflecting how we transform raw data into a model ready for real-world challenges:

import os
import pickle
import numpy as np
import pandas as pd
from sklearn import datasets
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LogisticRegression, Perceptron
from sklearn.metrics import accuracy_score, precision_score, recall_score, f1_score

# Load the breast cancer dataset
X, y = datasets.load_breast_cancer(return_X_y=True)

# Split the dataset into training and testing sets
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.9, random_state=0)

# Combine X_test and y_test into a single DataFrame
X_test_df = pd.DataFrame(X_test, columns=[f"feature_{i}" for i in range(X_test.shape[1])])
y_test_df = pd.DataFrame(y_test, columns=["target"])

df_test = pd.concat([X_test_df, y_test_df], axis=1)

# Define the path to store models
model_path = "models/"

# Create the folder if it doesn’t exist
if not os.path.exists(model_path):
os.makedirs(model_path)

# Define a list of classifier parameters
parameters = [
{"clf": LogisticRegression(solver="liblinear", multi_class="ovr"), "name": f"{model_path}/binary-lr.joblib"},
{"clf": Perceptron(eta0=0.1, random_state=0), "name": f"{model_path}/binary-percept.joblib"},
]

# Iterate through each parameter configuration
for param in parameters:
clf = param["clf"] # Retrieve the classifier from the parameter dictionary
clf.fit(X_train, y_train) # Fit the classifier on the training data
# Save the trained model to a file using pickle
model_filename = f"{param[’name’]}"
with open(model_filename, ‘wb’) as model_file:
pickle.dump(clf, model_file)
print(f"Model saved in {model_filename}")

# Simple Model Evaluation
model_path = ‘models/binary-lr.joblib’
with open(model_path, ‘rb’) as model_file:
loaded_model = pickle.load(model_file)

# Make predictions using the loaded model
predictions = loaded_model.predict(X_test)

# Calculate metrics (accuracy, precision, recall, f1-score)
accuracy = accuracy_score(y_test, predictions)
precision = precision_score(y_test, predictions)
recall = recall_score(y_test, predictions)
f1 = f1_score(y_test, predictions)

Model class creation

With the model files primed, the task at hand shifts to the crafting of the model class — an essential architectural element that will later reside within the Docker image. Like a skilled sculptor, we must shape this class, adhering to the exacting standards proposed by Seldon:

import joblib
import logging

class Score:
"""
Class to hold metrics for binary classification, including true positives (TP), false positives (FP),
true negatives (TN), and false negatives (FN).
"""
def __init__(self, TP=0, FP=0, TN=0, FN=0):
self.TP = TP # True Positives
self.FP = FP # False Positives
self.TN = TN # True Negatives
self.FN = FN # False Negatives

class DockerModel:
"""
Class for loading and predicting using a pre-trained model, handling feedback to update metrics,
and providing those metrics.
"""
result = {} # Dictionary to store input data

def __init__(self, model_name="models/binary-lr.joblib"):
"""
Initialize DockerModel with metrics and model name.
:param model_name: Path to the pre-trained model.
"""
self.scores = Score(0, 0, 0, 0)
self.loaded = False
self.model_name = model_name

def load(self):
"""
Load the model from the provided path.
"""
self.model = joblib.load(self.model_name)
logging.info(f"Model {self.model_name} Loaded")

def predict(self, X, features_names=None, meta=None):
"""
Predict the target using the loaded model.
:param X: Features for prediction.
:param features_names: Names of the features, optional.
:param meta: Additional metadata, optional.
:return: Predicted target values.
"""
self.result[’shape_input_data’] = str(X.shape)
logging.info(f"Received request: {X}")
if not self.loaded:
self.load()
self.loaded = True
predictions = self.model.predict(X)
return predictions

def send_feedback(self, features, feature_names, reward, truth, routing=""):
"""
Provide feedback on predictions and update the metrics.
:param features: Features used for prediction.
:param feature_names: Names of the features.
:param reward: Reward signal, not used in this context.
:param truth: Ground truth target values.
:param routing: Routing information, optional.
:return: Empty list as return value is not used.
"""
predicted = self.predict(features)
logging.info(f"Predicted: {predicted[0]}, Truth: {truth[0]}")
if int(truth[0]) == 1:
if int(predicted[0]) == int(truth[0]):
self.scores.TP += 1
else:
self.scores.FN += 1
else:
if int(predicted[0]) == int(truth[0]):
self.scores.TN += 1
else:
self.scores.FP += 1
return [] # Ignore return statement as its not used

def calculate_metrics(self):
"""
Calculate the accuracy, precision, recall, and F1-score.
:return: accuracy, precision, recall, f1_score
"""
total_samples = self.scores.TP + self.scores.TN + self.scores.FP + self.scores.FN

# Check if there are any samples to avoid division by zero
if total_samples == 0:
logging.warning("No samples available to calculate metrics.")
return 0, 0, 0, 0 # Return zeros for all metrics if no samples

accuracy = (self.scores.TP + self.scores.TN) / total_samples

# Check if there are any positive predictions to calculate precision
positive_predictions = self.scores.TP + self.scores.FP
precision = self.scores.TP / positive_predictions if positive_predictions != 0 else 0

# Check if there are any actual positives to calculate recall
actual_positives = self.scores.TP + self.scores.FN
recall = self.scores.TP / actual_positives if actual_positives != 0 else 0

# Check if precision and recall are non-zero to calculate F1-score
if precision + recall == 0:
f1_score = 0
else:
f1_score = 2 * (precision * recall) / (precision + recall)

# Return the calculated metrics
return accuracy, precision, recall, f1_score

def metrics(self):
"""
Generate metrics for monitoring.
:return: List of dictionaries containing accuracy, precision, recall, and f1_score.
"""
accuracy, precision, recall, f1_score = self.calculate_metrics()
return [
{"type": "GAUGE", "key": "accuracy", "value": accuracy},
{"type": "GAUGE", "key": "precision", "value": precision},
{"type": "GAUGE", "key": "recall", "value": recall},
{"type": "GAUGE", "key": "f1_score", "value": f1_score},
]

def tags(self):
"""
Retrieve metadata when generating predictions
:return: Dictionary the intermediate information
"""
return self.result

Let’s delve into the details of the functions and classes within the DockerModel class that encapsulates these four essential aspects:

Loading and predicting:

load(): This function is responsible for importing the pretrained model from the provided path. It’s usually called internally before making predictions to ensure the model is available.

predict(X, features_names=None, meta=None): This function deploys the loaded model to make predictions. It takes in the input features X, optional features_names, and optional metadata meta, returning the predicted target values.

Feedback handling:

send_feedback(features, feature_names, reward, truth, routing=””): This function is vital in adapting the model to real-world feedback. It accepts the input data, truth values, and other parameters to assess the model’s performance. The feedback updates the model’s understanding, and the metrics are calculated and stored for real-time analysis. This facilitates continuous retraining of the model.

Metrics calculation:

calculate_metrics(): This function calculates the essential metrics of accuracy, precision, recall, and F1-score. These metrics provide quantitative insights into the model’s performance, enabling constant monitoring and potential improvement.

Score class: This auxiliary class is used within the DockerModel to hold metrics for binary classification, including true positives (TP), false positives (FP), true negatives (TN), and false negatives (FN). It helps keep track of these parameters, which are vital for calculating the aforementioned metrics.

Monitoring assistance:

metrics(): This function generates the metrics for model monitoring. It returns a list of dictionaries containing the calculated accuracy, precision, recall, and F1 score. These metrics are compliant with Prometheus Metrics, facilitating real-time monitoring and analysis.

tags(): This function is designed to retrieve custom metadata data when generating predictions, aiding in monitoring and debugging. It returns a dictionary, which can help track and understand the nature of the requests.

Together, these functions and classes form a cohesive and robust structure that supports the entire lifecycle of an ML model. From the moment of inception (loading and predicting) through its growth (feedback handling) and evaluation (metrics calculation), to its continuous vigilance (monitoring assistance), the architecture is designed to standardize and streamline the process of deploying and maintaining ML models in a real-world production environment.

This model class is more than code; it’s the vessel that carries our ML model from a local environment to the vast sea of production. It’s the vehicle for standardization, unlocking efficiency and consistency in deploying models.

At this stage, we’ve prepared the canvas and outlined the masterpiece. Now, it’s time to dive deeper and explore how this model is encapsulated into a Docker image, an adventure that blends technology and strategy to redefine ML deployment. 

Testing model locally

Before venturing into creating a Docker image, testing the model locally is vital. This step acts as a rehearsal before the main event, providing a chance to ensure that the model is performing as expected with the testing data.

The importance of local testing lies in its ability to catch issues early, avoiding potential complications later in the deployment process. Following the example code provided below, it can confirm that the model is ready for its next phase if it provides the expected prediction in the expected format:

from DockerModel import DockerModel
demoModel = DockerModel()
demoModel.predict(X_test) # Can take the entire testing dataset or individual predictions

The expected output should match the format of the class labels you anticipate from the model. If everything works correctly, you’re assured that the model is well prepared for the next grand step: encapsulation within a Docker image.

Local testing is more than a technical process; it’s a quality assurance measure that stands as a gatekeeper, ensuring that only a well-prepared model moves forward. It illustrates the meticulous care taken in the deployment process, reflecting a commitment to excellence that transcends code and resonates with the core values of standardization and efficiency.

With the local testing accomplished, we stand on the threshold of a new frontier: creating the Docker image. Let’s continue this exciting journey, knowing each step is a stride toward innovation and mastery in ML deployment.

Encapsulating the model into a Docker image

In our IKEA MLOps view, a model is not simply a collection of code. Rather, it is a sophisticated assembly comprising code, dependencies, and ML artifacts, all encapsulated within a versioned and registered Docker image. This composition is carefully designed, reflecting the meticulous planning of the physical infrastructure.

What is Docker’s role in MLOps?

Docker plays a vital role in MLOps, providing a standardized environment that streamlines the transition from development to production:

Streamlining deployment: Docker containers encapsulate everything an ML model needs to run, easing the deployment process.

Facilitating collaboration: Using Docker, data scientists and engineers can ensure that models and their dependencies remain consistent across different stages of development.

Enhancing model reproducibility: Docker provides a uniform environment that enhances the reproducibility of models, a critical aspect in machine learning.

Integrating with orchestration tools: Docker can be used with orchestration platforms like Kubernetes, enabling automated deployment, scaling, and management of containerized applications.

Docker and containerization are more than technology tools; they catalyze innovation and efficiency in MLOps. Ensuring consistency, scalability and agility, Docker unlocks new potential and opens the way for a more agile and robust ML deployment process. Whether you are a developer, a data scientist, or an IT professional, understanding Docker is critical to navigating the complex and multifaceted landscape of modern data-driven applications.

Dockerfile creation

Creating a Dockerfile is like sketching the architectural plan of a building. It outlines the instructions for creating a Docker image to run the application in a coherent, isolated environment. This design ensures that the entire model — including its code, dependencies, and unique ML artifacts — is treated as a cohesive entity, aligning with the overarching vision of IKEA’s MLOps approach.

In our case, we have created a Dockerfile with the express purpose of encapsulating not only the code but all the corresponding artifacts of the model. This deliberate design facilitates a smooth transition to production, effectively bridging the gap between development and deployment.

We used the following Dockerfile for this demonstration, which represents a tangible example of how IKEA’s MLOps approach is achieved through thoughtful engineering and strategic implementation.

# Use an official Python runtime as a parent image.
# Using a slim image for a smaller final size and reduced attack surface.
FROM python:3.9-slim

# Set the maintainer label for metadata.
LABEL maintainer="fernandodorado.rueda@ingka.com"

# Set environment variables for a consistent build behavior.
# Disabling the buffer helps to log messages synchronously.
ENV PYTHONUNBUFFERED=1

# Set a working directory inside the container to store all our project files.
WORKDIR /app

# First, copy the requirements file to leverage Docker’s cache for dependencies.
# By doing this first, changes to the code will not invalidate the cached dependencies.
COPY requirements.txt requirements.txt

# Install the required packages listed in the requirements file.
# It’s a good practice to include the –no-cache-dir flag to prevent the caching of dependencies
# that aren’t necessary for executing the application.
RUN pip install –no-cache-dir -r requirements.txt

# Copy the rest of the code and model files into the image.
COPY DockerModel.py DockerModel.py
COPY models/ models/

# Expose ports that the application will run on.
# Port 5000 for GRPC
# Port 9000 for REST
EXPOSE 5000 9000

# Set environment variables used by the application.
ENV MODEL_NAME DockerModel
ENV SERVICE_TYPE MODEL

# Change the owner of the directory to user 8888 for security purposes.
# It can prevent unauthorised write access by the application itself.
# Make sure to run the application as this non-root user later if applicable.
RUN chown -R 8888 /app

# Use the exec form of CMD so that the application you run will receive UNIX signals.
# This is helpful for graceful shutdown.
# Here we’re using seldon-core-microservice to serve the model.
CMD exec seldon-core-microservice $MODEL_NAME –service-type $SERVICE_TYPE

This Dockerfile contains different parts:

FROM python:3.9-slim: This line chooses the official Python 3.9 slim image as the parent image. It is favored for its reduced size and attack surface, enhancing both efficiency and security.

LABEL maintainer=”fernandodorado.rueda@ingka.com”: A metadata label that specifies the maintainer of the image, providing contact information.

ENV PYTHONUNBUFFERED=1: Disabling Python’s output buffering ensures that log messages are emitted synchronously, aiding in debugging and log analysis.

WORKDIR /app: Sets the working directory inside the container to /app, a centralized location for all project files.

COPY requirements.txt requirements.txt: Copies the requirements file into the image. Doing this before copying the rest of the code leverages Docker’s caching mechanism, making future builds faster. This file must contain the “seldon-core” package:

pandas==1.3.5
requests==2.28.1
numpy==1.20
seldon-core==1.14.1
scikit-learn==1.0.2

RUN pip install –no-cache-dir -r requirements.txt: Installs required packages as listed in the requirements file. The flag -no-cache-dir prevents unnecessary caching of dependencies, reducing the image size.

COPY DockerModel.py DockerModel.py: Copies the main Python file into the image.

COPY models/ models/: Copies the model files into the image.

EXPOSE 5000 9000: Exposes ports 5000 (GRPC) and 9000 (REST), allowing communication with the application inside the container.

ENV MODEL_NAME DockerModel: Sets the environment variable for the model name.

ENV SERVICE_TYPE MODEL: Sets the environment variable for the service type.

RUN chown -R 8888 /app: Changes the owner of the directory to user 8888. Running the application as a non-root user helps mitigate the risk of unauthorized write access.

CMD exec seldon-core-microservice $MODEL_NAME –service-type $SERVICE_TYPE: Executes the command to start the service using seldon-core-microservice. It also includes the model name and service type as parameters. Using exec ensures the application receives UNIX signals, facilitating graceful shutdown.

Building and pushing Docker image

1. Installing Docker Desktop

If not already installed, Docker Desktop is recommended for this task. Docker Desktop provides a graphical user interface that simplifies the process of building, running, and managing Docker containers. Docker Desktop also supports Kubernetes, offering an easy way to create a local cluster.

2. Navigating to the Project directory

Open a terminal or command prompt.

Navigate to the folder where the Dockerfile and other necessary files are located.

3. Building the Image

Execute the command: docker build . -t docker-model:1.0.0.

docker build . instructs Docker to build the image using the current directory (.).

-t docker-model:1.0.0 assigns a name (docker-model) and tag (1.0.0) to the image.

The build process will follow the instructions defined in the Dockerfile, creating a Docker image encapsulating the entire environment needed to run the model.

4. Pushing the image

If needed, the image can be pushed to a container registry like Docker Hub, or a private registry within an organization.

For this demonstration, the image is being kept in the local container registry, simplifying the process and removing the need for authentication with an external registry.

Deploy ML model using Docker: Unleash it into the world

Once the Docker image is built, running it is relatively straightforward. Let’s break down this process:

docker run –rm –name docker-model -p 9000:9000 docker-model:1.0.0

Components of the command:

docker run: This is the base command to run a Docker container.

-rm: This flag ensures that the Docker container is automatically removed once it’s stopped. It helps keep the environment clean, especially when you run containers for testing or short-lived tasks.

-name docker-model: Assigns a name to the running container.

p 9000:9000: This maps port 9000 on the host machine to port 9000 on the Docker container. The format is p <host_port>:<container_port>. Because the Dockerfile mentions that the application will be exposing ports 5000 for GRPC and 9000 for REST, this command makes sure the REST endpoint is available to external users or applications through port 9000 on the host.

docker-model:1.0.0: This specifies the name and tag of the Docker image to run. docker-model is the name, and 1.0.0 is the version tag we assigned during the build process.

What happens next

On executing the command, Docker will initiate a container instance from the docker-model:1.0.0 image.

The application within the Docker container will start and begin listening for requests on port 9000 (as specified).

With the port mapping, any incoming requests on port 9000 of the host machine will be forwarded to port 9000 of the Docker container.

The application can now be accessed and interacted with as if it were running natively on the host machine.

Test deployed model using Docker

With the Docker image in place, it’s time to see the model in action.

Generate predictions

The path from model to prediction is a delicate process, requiring an understanding of the specific input-output type that Seldon accommodates (e.g., ndarray, JSON data, STRDATA).

In our scenario, the model anticipates an array, and thus, the key in our payload is “ndarray.” Here’s how we orchestrate this:

import requests
import json

URL = "http://localhost:9000/api/v1.0/predictions"

def send_prediction_request(data):

# Create the headers for the request
headers = {‘Content-Type': ‘application/json’}

try:
# Send the POST request
response = requests.post(URL, headers=headers, json=data)

# Check if the request was successful
response.raise_for_status() # Will raise HTTPError if the HTTP request returned an unsuccessful status code

# If successful, return the JSON data
return response.json()
except requests.ConnectionError:
raise Exception("Failed to connect to the server. Is it running?")
except requests.Timeout:
raise Exception("Request timed out. Please try again later.")
except requests.RequestException as err:
# For any other requests exceptions, re-raise it
raise Exception(f"An error occurred with your request: {err}")

X_test

# Define the data payload (We can also use X_test[0:1].tolist() instead of the raw array)
data_payload = {
"data": {
"ndarray": [
[
1.340e+01, 2.052e+01, 8.864e+01, 5.567e+02, 1.106e-01, 1.469e-01,
1.445e-01, 8.172e-02, 2.116e-01, 7.325e-02, 3.906e-01, 9.306e-01,
3.093e+00, 3.367e+01, 5.414e-03, 2.265e-02, 3.452e-02, 1.334e-02,
1.705e-02, 4.005e-03, 1.641e+01, 2.966e+01, 1.133e+02, 8.444e+02,
1.574e-01, 3.856e-01, 5.106e-01, 2.051e-01, 3.585e-01, 1.109e-01
]
]
}
}

# Get the response and print it
try:
response = send_prediction_request(data_payload)
pretty_json_response = json.dumps(response, indent=4)
print(pretty_json_response)
except Exception as err:
print(err)

The prediction of our model will be similar to this dictionary:

{
"data": {
"names": [],
"ndarray": [
0
]
},
"meta": {
"metrics": [
{
"key": "accuracy",
"type": "GAUGE",
"value": 0
},
{
"key": "precision",
"type": "GAUGE",
"value": 0
},
{
"key": "recall",
"type": "GAUGE",
"value": 0
},
{
"key": "f1_score",
"type": "GAUGE",
"value": 0
}
],
"tags": {
"shape_input_data": "(1, 30)"
}
}
}

The response from the model will contain several keys:

“data”: Provides the generated output by our model. In our case, it’s the predicted class.

“meta”: Contains metadata and model metrics. It shows the actual values of the classification metrics, including accuracy, precision, recall, and f1_score.

“tags”: Contains intermediate metadata. This could include anything you want to track, such as the shape of the input data.

The structure outlined above ensures that not only can we evaluate the final predictions, but we also gain insights into intermediate results. These insights can be instrumental in understanding predictions and debugging any potential issues.

This stage marks a significant milestone in our journey from training a model to deploying and testing it within a Docker container. We’ve seen how to standardize an ML model and how to set it up for real-world predictions. With this foundation, you’re well-equipped to scale, monitor, and further integrate this model into a full-fledged production environment.

Send feedback in real-time and calculate metrics

The provisioned /feedback endpoint facilitates this learning by allowing truth values to be sent back to the model once they are available. As these truth values are received, the model’s metrics are updated and can be scraped by other tools for real-time analysis and monitoring. In the following code snippet, we iterate over the test dataset and send the truth value to the /feedback endpoint, using a POST request:

import requests
import json

URL = "http://localhost:9000/api/v1.0/feedback"

def send_prediction_feedback(data):

# Create the headers for the request
headers = {‘Content-Type': ‘application/json’}

try:
# Send the POST request
response = requests.post(URL, headers=headers, json=data)

# Check if the request was successful
response.raise_for_status() # Will raise HTTPError if the HTTP request returned an unsuccessful status code

# If successful, return the JSON data
return response.json()
except requests.ConnectionError:
raise Exception("Failed to connect to the server. Is it running?")
except requests.Timeout:
raise Exception("Request timed out. Please try again later.")
except requests.RequestException as err:
# For any other requests exceptions, re-raise it
raise Exception(f"An error occurred with your request: {err}")

for i in range(len(X_test)):
payload = {‘request': {‘data': {‘ndarray': [X_test[i].tolist()]}}, ‘truth': {‘data': {‘ndarray': [int(y_test[i])]}}}

# Get the response and print it
try:
response = send_prediction_feedback(payload)
pretty_json_response = json.dumps(response, indent=4) # Pretty-print JSON
print(pretty_json_response)
except Exception as err:
print(err)

After processing the feedback, the model calculates and returns key metrics, including accuracy, precision, recall, and F1-score. These metrics are then available for analysis:

{
"data": {
"ndarray": []
},
"meta": {
"metrics": [
{
"key": "accuracy",
"type": "GAUGE",
"value": 0.92607003
},
{
"key": "precision",
"type": "GAUGE",
"value": 0.9528302
},
{
"key": "recall",
"type": "GAUGE",
"value": 0.9294478
},
{
"key": "f1_score",
"type": "GAUGE",
"value": 0.9409938
}
],
"tags": {
"shape_input_data": "(1, 30)"Ω
}
}
}

What makes this approach truly powerful is that the model’s evolution is no longer confined to the training phase. Instead, it’s in a continual state of learning, adjustment, and refinement, based on real-world feedback.

This way, we’re not just deploying a static prediction engine but fostering an evolving intelligent system that can better align itself with the changing landscape of data it interprets. It’s a holistic approach to machine learning deployment that encourages continuous improvement and real-time adaptation.

Conclusions

At IKEA, Docker has become an indispensable element in our daily MLOps activities, serving as a catalyst that accelerates the development and deployment of models, especially when transitioning to production. The transformative impact of Docker unfolds through a spectrum of benefits that not only streamlines our workflow but also fortifies it:

Standardization: Docker orchestrates a consistent environment during the development and deployment of any ML model, fostering uniformity and coherence across the lifecycle.

Compatibility: With support for diverse environments and seamless multi-cloud or on-premise integration, Docker bridges gaps and ensures a harmonious workflow.

Isolation: Docker ensures that applications and resources are segregated, offering an isolated environment that prioritizes efficiency and integrity.

Security: Beyond mere isolation, Docker amplifies security by completely segregating applications from each other. This robust separation empowers us with precise control over traffic flow and management, laying a strong foundation of trust.

These attributes translate into tangible advantages in our MLOps journey, sculpting a landscape that’s not only innovative but also robust:

Agile development and deployment environment: Docker ignites a highly responsive development and deployment environment, enabling seamless creation, updating, and deployment of ML models.

Optimized resource utilization: Utilize compute/GPU resources efficiently within a shared model, maximizing performance without compromising flexibility.

Scalable deployment: Docker’s architecture allows for the scalable deployment of ML models, adapting effortlessly to growing demands.

Smooth release cycles: Integrating seamlessly with our existing CI/CD pipelines, Docker smoothens the model release cycle, ensuring a continuous flow of innovation.

Effortless integration with monitoring tools: Docker’s compatibility extends to monitoring stacks like Prometheus + Grafana, creating a cohesive ecosystem fully aligned with our MLOps approach when creating and deploying models in production.

The convergence of these benefits elevates IKEA’s MLOps strategy, transforming it into a symphony of efficiency, security, and innovation. Docker is not merely a tool: Docker is a philosophy that resonates with our pursuit of excellence. Docker is the bridge that connects creativity with reality, and innovation with execution.

In the complex world of ML deployment, we’ve explored a path less trodden but profoundly rewarding. We’ve tapped into the transformative power of standardization, unlocking an agile and responsive way to deploy and engage with ML models in real-time.

But this is not a conclusion; it’s a threshold. New landscapes beckon, brimming with opportunities for growth, exploration, and innovation. The following steps will continue the current approach: 

Scaling with Kubernetes: Unleash the colossal potential of Kubernetes, a beacon of flexibility and resilience, guiding you to a horizon of unbounded possibilities.

Applying real-time monitoring and alerting systems based on open source technologies, such as Prometheus and Grafana.

Connecting a data-drift detector for real-time detection: Deployment and integration of drift detectors to detect changes in data in real-time.

We hope this exploration will empower you to redefine your paths, ignite new ideas, and push the boundaries of what’s possible. The gateway to an extraordinary future is open, and the key is in our hands.

Learn more

Read our Docker AI/ML article collection.

Visit Docker Hub, the world’s largest container image registry.

Get the latest release of Docker Desktop.

Vote on what’s next! Check out our public roadmap.

Have questions? The Docker community is here to help.

New to Docker? Get started.

Quelle: https://blog.docker.com/feed/

How to Get Started with the Weaviate Vector Database on Docker

Vector databases have been getting a lot of attention since the developer community realized how they can enhance large language models (LLMs). Weaviate is an open source vector database that enables modern search capabilities, such as vector search, hybrid search, and generative search. With Weaviate, you can build advanced LLM applications, next-level search systems, recommendation systems, and more.

This article explains what vector databases are and highlights key features of the Weaviate vector database. Learn how to install Weaviate on Docker using Docker Compose so you can take advantage of semantic search within your Dockerized environment.

Introducing the Weaviate vector database

The core feature of vector databases is storing vector embeddings of data objects. This functionality is especially helpful with the growing amount of unstructured data (e.g., text or images), which is difficult to manage and process with traditional relational databases. The vector embeddings are a numerical representation of the data objects — usually generated by a machine learning (ML) model — and enable the search and retrieval of data based on semantic similarity (vector search).

Vector databases do much more than just store vector embeddings: As you can imagine, retrieving data based on similarity requires a lot of comparing between objects and thus can take a long time. In contrast to other types of databases that can store vector embeddings, a vector database can retrieve data fast. To enable low-latency search queries, vector databases use specific algorithms to index the data.

Additionally, some vector databases, like Weaviate, store the vector embeddings and the original data object, which lets you combine traditional search with modern vector search for more accurate search results.

With these functionalities, vector databases are usually used in search or similar tasks (e.g., recommender systems). With the recent advancements in the LLM space, however, vector databases have also proven effective at providing long-term memory and domain-specific context to conversational LLMs. This means that you can leverage LLM capabilities on your private data or your specific field of expertise.

Key highlights of the Weaviate vector database include:

Open source: Weaviate is open source and available for anybody to use wherever they want. It is also available as a managed service with SaaS and hybrid SaaS options.

Horizontal scalability: You can scale seamlessly into billions of data objects for your exact needs, such as maximum ingestion, largest possible dataset size, maximum queries per second, etc.

Lightning-fast vector search: You can perform lightning-fast pure vector similarity search over raw vectors or data objects, even with filters. Weaviate typically performs nearest-neighbor searches of millions of objects in considerably less than 100ms (see our benchmark).

Combined keyword and vector search (hybrid search): You can store both data objects and vector embeddings. This approach allows you to combine keyword-based and vector searches for state-of-the-art search results.

Optimized for cloud-native environments: Weaviate has the fault tolerance of a cloud-native database, and the core Docker image is comparably small at 18 MB.

Modular ecosystem for seamless integrations: You can use Weaviate standalone (aka “bring your own vectors”) or with various optional modules that integrate directly with OpenAI, Cohere, Hugging Face, etc., to enable easy use of state-of-the-art ML models. These modules can be used as vectorizers to automatically vectorize any media type (text, images, etc.) or as generative modules to extend Weaviate’s core capabilities (e.g., question answering, generative search, etc.).

Prerequisites

Ensure you have both the docker and the docker-compose CLI tools installed. For the following section, we assume you have Docker 17.09.0 or higher and Docker Compose V2 installed. If your system has Docker Compose V1 installed instead of V2, use docker-compose  instead of docker compose. You can check your Docker Compose version with:

$ docker compose version

How to Configure the Docker Compose File for Weaviate

To start Weaviate with Docker Compose, you need a Docker Compose configuration file, typically called docker-compose.yml. Usually, there’s no need to obtain individual images, as we distribute entire Docker Compose files.

You can obtain a Docker Compose file for Weaviate in two different ways:

Docker Compose configurator on the Weaviate website (recommended): The configurator allows you to customize your docker-compose.yml file for your purposes (including all module containers) and directly download it.

Manually: Alternatively, if you don’t want to use the configurator, copy and paste one of the example files from the documentation and manually modify it.

This article will review the steps to configure your Docker Compose file with the Weaviate Docker Compose configurator.

Step 1: Version

First, define which version of Weaviate you want to use (Figure 1). We recommend always using the latest version.

Figure 1: The first step when using the Weaviate Docker Compose configurator, suggesting that the latest version be used.

The following shows a minimal example of a Docker Compose setup for Weaviate:

version: ‘3.4’
services:
weaviate:
image: semitechnologies/weaviate:1.20.5
ports:
– 8080:8080
restart: on-failure:0
environment:
QUERY_DEFAULTS_LIMIT: 25
AUTHENTICATION_ANONYMOUS_ACCESS_ENABLED: ‘true’
PERSISTENCE_DATA_PATH: ‘/var/lib/weaviate’
DEFAULT_VECTORIZER_MODULE: ‘none’
CLUSTER_HOSTNAME: ‘node1′

Step 2: Persistent volume

Configure persistent volume for Docker Compose file (Figure 2):

Figure 2: Weaviate Docker Compose configurator “Persistent Volume” configuration options.

Setting up a persistent volume to avoid data loss when you restart the container and improve reading and writing speeds is recommended.

You can set a persistent volume in two ways:

With a named volume: Docker will create a named volume weaviate_data and mount it to the PERSISTENCE_DATA_PATH inside the container after starting Weaviate with Docker Compose:

services:
weaviate:
volumes:
– weaviate_data:/var/lib/weaviate
# etc.

volumes:
weaviate_data:

With host binding: Docker will mount  ./weaviate_data  on the host to the PERSISTENCE_DATA_PATH inside the container after starting Weaviate with Docker Compose:

services:
weaviate:
volumes:
– ./weaviate_data:/var/lib/weaviate
# etc.

Step 3: Modules

Weaviate can be used with various modules, which integrate directly with inferencing services like OpenAI, Cohere, or Hugging Face. These modules can be used to vectorize any media type at import and search time automatically or to extend Weaviate’s core capabilities with generative modules.

You can also use Weaviate without any modules (standalone). In this case, no model inference is performed at import or search time, meaning you need to provide your own vectors in both scenarios. If you don’t need any modules, you can skip to Step 4: Runtime.

Configure modules for Docker Compose file (Figure 3):

Figure 3: The Weaviate Docker Compose configurator step to define if modules will be used, or if running standalone is desired.

Currently, Weaviate integrates three categories of modules:

Retriever and vectorizer modules automatically vectorize any media type (text, images, etc.) at import and search time. There are also re-ranker modules available for re-ranking search results.

Reader and generator modules can be used to extend Weaviate’s core capabilities after retrieving the data for generative search, question answering, named entity recognition (NER), and summarization.

Other modules are available for spell checking or for enabling using your custom modules.

Note that many modules (e.g., transformer models) are neural networks built to run on GPUs. Although you can run them on CPU, enabling GPU  `ENABLE_CUDA=1`, if available, will result in faster inference.

The following shows an example of a Docker Compose setup for Weaviate with the sentence-transformers model:

version: ‘3.4’
services:
weaviate:
image: semitechnologies/weaviate:1.20.5
restart: on-failure:0
ports:
– "8080:8080"
environment:
QUERY_DEFAULTS_LIMIT: 20
AUTHENTICATION_ANONYMOUS_ACCESS_ENABLED: ‘true’
PERSISTENCE_DATA_PATH: "./data"
DEFAULT_VECTORIZER_MODULE: text2vec-transformers
ENABLE_MODULES: text2vec-transformers
TRANSFORMERS_INFERENCE_API: http://t2v-transformers:8080
CLUSTER_HOSTNAME: ‘node1′
t2v-transformers:
image: semitechnologies/transformers-inference:sentence-transformers-multi-qa-MiniLM-L6-cos-v1
environment:

Step 4: Runtime

In the final step of the configurator, select Docker Compose for your runtime (Figure 4):

Figure 4: The final step of the Weaviate Docker Compose configurator where “Docker Compose” can be selected as the runtime.

Step 5: Download and further customization

Once your configuration is complete, you will see a snippet similar to the following to download the docker-compose.yml file, which has been adjusted to your selected configuration.

$ curl -o docker-compose.yml "https://configuration.weaviate.io/v2/docker-compose/docker-compose.yml?<YOUR-CONFIGURATION>"

After downloading the Docker Compose file from the configurator, you can directly start Weaviate on Docker or customize it further.

You can set additional environment variables to further customize your Weaviate setup (e.g., by defining authentication and authorization). Additionally, you can create a multi-node setup with Weaviate by defining a founding member and other members in the cluster.

Founding member: Set up one node as a “founding” member by configuring CLUSTER_GOSSIP_BIND_PORT and CLUSTER_DATA_BIND_PORT:

weaviate-node-1: # Founding member service name
… # truncated for brevity
environment:
CLUSTER_HOSTNAME: ‘node1′
CLUSTER_GOSSIP_BIND_PORT: ‘7100’
CLUSTER_DATA_BIND_PORT: ‘7101’

Other members in the cluster: For each further node, configure CLUSTER_GOSSIP_BIND_PORT and CLUSTER_DATA_BIND_PORT and configure to join the founding member’s cluster using the CLUSTER_JOIN variable:

weaviate-node-2:
… # truncated for brevity
environment:
CLUSTER_HOSTNAME: ‘node2′
CLUSTER_GOSSIP_BIND_PORT: ‘7102’
CLUSTER_DATA_BIND_PORT: ‘7103’
CLUSTER_JOIN: ‘weaviate-node-1:7100′ # This must be the service name of the "founding" member node.

Optionally, you can set a hostname for each node using CLUSTER_HOSTNAME.

Note that it’s a Weaviate convention to set the CLUSTER_DATA_BIND_PORT to 1 higher than CLUSTER_GOSSIP_BIND_PORT.

How to run Weaviate on Docker

Once you have your Docker Compose file configured to your needs, you can run Weaviate in your Docker environment.

Start Weaviate

Before starting Weaviate on Docker, ensure that the Docker Compose file is named exactly docker-compose.yml and that you are in the same folder as the Docker Compose file.

Then, you can start up with the whole setup by running:

$ docker compose up -d

The -d option runs containers in detached mode. This means that your terminal will not attach to the log outputs of all the containers.

If you want to attach to the logs of specific containers (e.g., Weaviate), you can run the following command:

$ docker compose up -d && docker compose logs -f weaviate

Congratulations! Weaviate is now running and is ready to be used.

Stop Weaviate

To avoid losing your data, shut down Weaviate with the following command:

$ docker compose down

This will write all the files from memory to disk.

Conclusion

This article introduced vector databases and how they can enhance LLM applications. Specifically, we highlighted the open source vector database Weaviate, whose advantages include fast vector search at scale, hybrid search, and integration modules to state-of-the-art ML models from OpenAI, Cohere, Hugging Face, etc.

We also provided a step-by-step guide on how to install Weaviate on Docker using Docker Compose, noting that you can obtain a docker-compose.yml file from the Weaviate Docker Compose configurator, which helps you to customize your Docker Compose file for your specific needs.

Visit our AI/ML page and read the article collection to learn more about how developers are using Docker to accelerate the development of their AI/ML applications.

Learn more

Get the latest release of Docker Desktop.

Vote on what’s next! Check out our public roadmap.

Have questions? The Docker community is here to help.

New to Docker? Get started.

Quelle: https://blog.docker.com/feed/

DockerCon Workshops: What to expect

DockerCon 2023 will be held October 4-5 in Los Angeles, and we are working hard to make it an incredible experience for everyone. The program is now online so you can plan your experience by day, time, and theme, including AI and Machine Learning, Web Application / Web Development, Building and Deploying Applications, Secure Software Delivery, and Open Source. This year we’re offering talks, workshops, and panel discussions, plus the usual vibrant DIY hallway track. We can’t wait to see you there — whether you’re joining virtually or in person. (If this will be your first DockerCon experience, read “4 Reasons I’m Excited to Attend DockerCon 2023” to see why I can’t wait to go to LA next month.)

On October 3, we will have several DockerCon hands-on workshops, organized by fantastic presenters, covering a variety of topics. If you’re joining in person, the workshops are included in the price of your admission. Just don’t forget to register for the workshop you’d like to attend! 

If you’ll be attending DockerCon virtually, the Getting Started with Docker workshop is free, and the other workshops cost US$150. This is a fantastic opportunity to use any learning and development allocations you might have!

What are the workshops and what will they cover? I’m glad you asked! Let’s dive in.

Getting Started with Docker

Are you new to Docker? Are you overwhelmed with everything there is to learn? Are you unsure why you should learn about containers and you don’t understand their benefits? Or do you just want to help your team be more productive? If so, this workshop is for you!

This workshop will walk through the basics of containers and images, including answering the question: Why should I even care about containers? You’ll then learn how to run containers, create your own images, and set up your own development environments to enable the success of your team. The workshop will close out by introducing Docker Compose, which makes it even easier to share your dev environment — devs will only need to run git clone and docker compose up and then focus on their code.

After this session, you’ll have the basic knowledge to help your team be more productive with containerized dev environments. It’ll also be a fantastic primer to help you get the most out of the rest of DockerCon.

Docker for Machine Learning / AI / Data Science

The AI/ML space has exploded with activity and excitement over the past year. There are many great tools available, but keeping up with everything can be hard. If you want to get caught up and started with AI/ML, this is the workshop for you.

This workshop is being provided through a close collaboration with OctoML and Docker. In this workshop, you’ll start with a crash course on the latest developments in generative LLMs and image generation models, after which you’ll learn about fine-tuning your own model. You’ll then take that knowledge and create a multi-modal containerized application using Python and Docker. The workshop wraps up with a fireside chat and Q&A with the presenters and speakers, allowing you to dive in deep!

After this workshop, you’ll have a better understanding of the recent advancements in the AI/ML space and have successfully created your own AI/ML-supported application.

Secure Development with Docker

Modern applications are composed of many libraries and components from various sources being built and deployed on various systems, making it difficult for developers, platform teams, and security professionals to know what software is running and whether it is secure. Issues may arise from your own code, its dependencies, base images, and many other sources — and new vulnerabilities are being discovered all the time! If you want to secure your software supply chain, this is the workshop for you.

In this workshop, you’ll start off by learning about and remediating several common attacks against your software supply chain. From there, you’ll dive deeply into securing the software supply chain, taking a comprehensive view of the problem and possible solutions. With this knowledge, you’ll learn how Docker Scout helps you understand what’s in your images, how those images are constructed, what’s running where, and providing actionable feedback early in the process so concerns are eliminated before they become problems.

After this session, you’ll know how to take these learnings back to your organization so your team:

Understands and can verify how their applications are built

Quickly and easily identifies problems with your software supply chain and remediates them

Uses policies to encourage best practices across your organization without blocking fixes getting to production

Provides visibility into the security stance of your software to others within your organization

Docker for Web Development

Are you a web developer who isn’t quite sure why you should use Docker in your development environment? Or are you just not quite sure how to get started? If so, this workshop is specifically for you.

The Docker for Web Development workshop is being presented by Timo Stark, a Docker Captain and Principal Engineer at NGINX. This hands-on workshop starts with an overview of Docker Desktop, ensuring everyone understands the basics of containers and images. With that foundational knowledge, you’ll spend the remainder of the workshop building an application, containerizing it along the way, using a combination of NodeJS and PHP backends and a React frontend. You’ll learn how to connect multiple services together and build a development environment that will require no installation and configuration (beyond Docker Desktop), helping speed up productivity and ensuring reliable environments across your development team.

After this session, you’ll have a strong understanding of how Docker can be used to speed up your web development stack and how you can help enable your team to be more productive and have more consistent environments.

Register now

DockerCon is coming up quickly! We’d love to see you in person, but you’re welcome to join us virtually as well. Visit the DockerCon site to register for the conference, see the program, and register for workshops now.

Learn more

Register for DockerCon

Register for DockerCon workshops

See the DockerCon program

Get the latest release of Docker Desktop.

Vote on what’s next! Check out our public roadmap.

Have questions? The Docker community is here to help.

New to Docker? Get started.

Quelle: https://blog.docker.com/feed/

Docker Desktop 4.23: New Configuration Integrity Check, Plus Updates to Docker Init, Compose, Watch, Quick Search, and More

Docker Desktop 4.23 is now available and includes numerous enhancements, including ASP.NET support in Docker Init, Configuration Integrity Check to alert on any configuration changes that require attention, and cross-domain identity management. This release also improves Quick Search, allowing for searching across containers, apps, Docker Hub, Docs, and any volume, and performing quick actions (start/stop/delete). VirtioFS is now set to default to provide performance gains for Mac users. With the Docker Desktop 4.23 release, Mac users will also see increased network performance using traditional network connections. 

In this post, we dive into what’s new and updated in the latest release of Docker Desktop.

ASP.NET with Docker Init

We are excited to announce added support for ASP.NET. Whether you’re new to Docker or a seasoned pro, Docker Init now streamlines Dockerization for your ASP.NET projects. With a simple docker init command in your project folder and the latest Docker Desktop version, watch as Docker Init generates tailored Dockerfiles, Compose files, and .dockerignore files.

Figure 1: Docker Init showing available languages, now including ASP.NET.

Specific to ASP.NET, we also improved support and documentation for multi-arch builds. This advancement will help users manage sharing their images across different CPU architectures and streamline deployments on cloud providers such as Azure, AWS, and GCP. Create images that fit various architectures, boosting flexibility and efficiency in cloud deployments.

Get started by ensuring you have the latest Docker Desktop version. Then, execute docker init in your project directory through the command line. Let Docker Init handle the heavy lifting, allowing you to concentrate on your core task — crafting outstanding applications!

Configuration Integrity Check

Ensure Docker Desktop runs smoothly with our new Configuration Integrity Check. This allows you to keep using multiple local applications and tools, sometimes making configuration changes hassle-free. This update automatically detects and alerts to any configuration changes, prompting a simple click and re-establishing Docker Desktop configurations to track and ensure uninterrupted development.

Alerts to any configuration issues will be displayed in the whale menu.

Cross-domain identity management 

User access management for Docker just got more powerful. SCIM helps auto-provision or de-provision users, and group role mapping is now supported so you can organize your teams and their access accordingly: 

You can assign roles to members in your organization in the IdP. To set up a role, you can use optional user-level attributes for the person you want to assign a role. 

You can also set an organization and team to override the default provisioning values set by the SSO connection.

The following table lists the supported optional user-level attributes.

Figure 2: The logic used for defining user access control.

Improvements to Quick Search 

Empowering developers with seamless access to essential resources whenever they’re needed, our revamped Quick Search feature has received significant upgrades. Now, users can effortlessly locate:

Containers and Compose apps: Easily pinpoint any container or Compose app residing on your local system. Additionally, gain quick access to environment variables and perform essential actions such as starting, stopping, or deleting them.

Docker Hub images: Whether it’s public Docker Hub images, local ones, or those from remote repositories, Quick Search will provide fast and relevant results.

Extensions: Discover more about specific extensions and streamline installation with a single click.

Volumes: Effortlessly navigate through your volumes and gain insights into the associated containers.

Documentation: Instantly access invaluable assistance from Docker’s official documentation, all directly from within Docker Desktop.

Enhanced Quick Search is your ultimate tool for resource discovery and management, offering unmatched convenience for developers.

Figure 3: Search results with updated Quick Search within Docker Desktop 4.23.

Standardizing higher performance file sharing with VirtioFS for Mac users

Docker Desktop 4.23 now defaults to utilizing VirtioFS on macOS 12.5+ as the standard to deliver substantial performance gains when sharing files with containers through docker run -v or bind mounts in Compose YAML. VirtioFS minimizes file transfer overhead by allowing containers to access files without volume mounts or network shares.

Figure 4: Setting VirtuoFS to default in the Docker Desktop General settings.

Skipping network file transfer protocols also leads to faster file transfers. We measured performance improvements, decreasing file transfer time from 7:13.21s to 1:4.4s — an 85.15% increase in speed. We do want to note that the measured improvement depends on the size of the file, what other apps are running, and the hardware of the computer.

Figure 5: Tables showing the transfer speeds of a 10GB file over three runs, before and after using VirtioFS.

Docker Desktop network speed improvements for Mac users

Docker Desktop 4.23 comes with improved networking performance for Mac users. Now, when a container requires a traditional network connection, users will experience increased network performance in these ways:

Accessing exposed ports ~10x faster

Transmission Control Protocol (TCP)  ~1.5x – 2x faster

No user action is required to experience these benefits — all Mac users updated to 4.23 will now network faster!

Conclusion

Upgrade now to explore what’s new in the 4.23 release of Docker Desktop. Do you have feedback? Leave feedback on our public GitHub roadmap, and let us know what else you’d like to see in upcoming releases.

Learn more

Read the Docker Desktop Release Notes.

Get the latest release of Docker Desktop.

Have questions? The Docker community is here to help.

New to Docker? Get started.

Quelle: https://blog.docker.com/feed/

Docker Hub Registry IPv6 Support Now Generally Available

As the world becomes increasingly interconnected, it’s essential for the internet to support the growing number of devices and users. That’s where IPv6 comes in.

What is IPv6, and what does it have to do with Docker? 

IPv6 is the latest version of the Internet Protocol, the system that enables devices to communicate with each other over the internet. It’s designed to address the limitations of the previous version, IPv4, which is running out of available addresses. 

As Docker supports more customers, this means we need to support different use cases, like IPv6-only networks. Today, we are pleased to announce the general availability of IPv6 support for the Docker Hub Registry, Docker Docs, and Docker Scout endpoints. 

Why are we adopting IPv6? 

We have heard from the community that you need IPv6 support for Docker software as a service (SaaS) endpoints to work efficiently and effectively. In the past, IPv6-only networks required extra tooling to interact with some of Docker’s SaaS resources. This is no longer the case. Now you can get rid of your NAT64 gateway and docker pull.

What does this mean for my workflows? 

This is my favorite part… nothing! 🥳 During our beta testing of IPv6, we introduced new endpoints for accessing the Docker Hub Registry. Those were only for the beta testing and are no longer needed. Now, if you are on an IPv6-only network, dual-stack network, or an IPv4-only network, these commands will work.

To begin, log in to the Docker Hub:

docker login

Then pull whatever image you need:

docker pull alpine

How will Docker Hub download rate limits work?

If you use authentication when pulling container images from the Docker Hub Registry, nothing changes. Our servers will properly attach rate limit data to the authenticated user ID in the HTTP request. 

If you do not authenticate your docker pull commands by running docker login first, then we’ll need to rate limit the request based on the IP address. For IPv4 addresses, this is done on a per-IP basis. 

For IPv6 addresses, this becomes a harder problem because IPv6 has a much larger IP address range available to customers. Therefore, to accommodate the larger IP address range, we will rate limit against the first 64 bits in the IPv6 address. You can see an example of what our servers use as the source by looking at the docker-ratelimit-source header returned in the following HTTP response:

$ curl https://registry-1.docker.io/v2/ratelimitpreview/test/manifests/latest -I -XGET -6
HTTP/1.1 401 Unauthorized
content-type: application/json
docker-distribution-api-version: registry/2.0
www-authenticate: Bearer realm="https://auth.docker.io/token",service="registry.docker.io",scope="repository:ratelimitpreview/test:pull"
date: Wed, 28 June 2023 01:06:44 GMT
content-length: 164
strict-transport-security: max-age=31536000
docker-ratelimit-source: 2601:245:c100:a71::

How can I verify that IPv6 is being used? 

While browsing the Docker Docs or pulling a Docker container image, you can use network monitoring software like tcpdump to monitor the traffic.

Let’s say that you want to verify the network you use for pulling a container image from the Docker Hub Registry.

First, in your favorite terminal, start a tcpdump capture. This command will produce log records of all of the network connections between your local machine and the Docker Hub servers:

sudo tcpdump host registry-1.docker.io -vv

In another terminal window, pull a container image from Docker Hub:

docker pull registry-1.docker.io/library/alpine:latest

You should see output that looks like this:

🚀 sudo tcpdump host registry-1.docker.io -vv
tcpdump: data link type PKTAP
tcpdump: listening on pktap, link-type PKTAP (Apple DLT_PKTAP), snapshot length 524288 bytes
15:42:16.740577 IP6 (flowlabel 0xa0800, hlim 64, next-header TCP (6) payload length: 44) 2601:245:c100:a71:8454:86d0:52f1:d46f.62630 > 2600:1f18:2148:bc02:cfd8:db68:ea1f:277c.https: Flags [S], cksum 0xb80b (correct), seq 2539670618, win 65535, options [mss 1440,nop,wscale 6,nop,nop,TS val 4154959809 ecr 0,sackOK,eol], length 0
15:42:16.774831 IP6 (class 0x20, hlim 229, next-header TCP (6) payload length: 40) 2600:1f18:2148:bc02:cfd8:db68:ea1f:277c.https > 2601:245:c100:a71:8454:86d0:52f1:d46f.62630: Flags [S.], cksum 0x6b60 (correct), seq 4264170311, ack 2539670619, win 26847, options [mss 1440,sackOK,TS val 2058512533 ecr 4154959809,nop,wscale 12], length 0

When you look at the second column of tab-delimited data, it will say IP6 to denote IPv6 being used. Additionally, the IP addresses you see in the output are in IPv6 format instead of IPv4 format. The quick way to tell is if the IP address has a colon (:) in it, then it is IPv6. If the IP address only has periods (.), then it is IPv4. 🎉

The future

We are excited to be able to provide full dual-stack network capabilities to Docker Hub Registry, Docker Docs, and Docker Scout endpoints. We believe that dual-stack capabilities offer an important performance and reliability benefit to our customers. We intend to provide dual-stack network support for new endpoints as part of our commitment to delivering the best possible experience for our users. 

If you have the ability to control your local network, turn on IPv6 and see Docker Hub Registry, Docker Docs, and Docker Scout endpoints continue to work. If you have access to an IPv6-only network, try docker pull or take a look at our docs pages — they will all continue to work as they did before. 

We look forward to hearing feedback from our community through our hub-feedback GitHub issue tracker.

Learn more

Get the latest release of Docker Desktop.

 Vote on what’s next! Check out our public roadmap.

 Have questions? The Docker community is here to help.

 New to Docker? Get started.

Quelle: https://blog.docker.com/feed/

Accelerating Machine Learning with TensorFlow.js: Using Pretrained Models and Docker

In the rapidly evolving era of machine learning (ML) and artificial intelligence (AI), TensorFlow has emerged as a leading framework for developing and implementing sophisticated models. With the introduction of TensorFlow.js, TensorFlow’s capability is boosted for JavaScript developers. 

TensorFlow.js is a JavaScript machine learning toolkit that facilitates the creation of ML models and their immediate use in browsers or Node.js apps. TensorFlow.js has expanded the capability of TensorFlow into the realm of actual web development. A remarkable aspect of TensorFlow.js is its ability to utilize pretrained models, which opens up a wide range of possibilities for developers. 

In this article, we will explore the concept of pretrained models in TensorFlow.js and Docker and delve into the potential applications and benefits. 

Understanding pretrained models

Pretrained models are a powerful tool for developers because they allow you to use ML models without having to train them yourself. This approach can save a lot of time and effort, and it can also be more accurate than training your own model from scratch.

A pretrained model is an ML model that has been professionally trained on a large volume of data. Because these models have been trained on complex patterns and representations, they are incredibly effective and precise in carrying out specific tasks. Developers may save a lot of time and computing resources by using pretrained models because they can avoid having to train a model from scratch.

Types of pretrained models available

There is a wide range of potential applications for pretrained models in TensorFlow.js. 

For example, developers could use them to:

Build image classification models that can identify objects in images.

Build natural language processing (NLP) models that can understand and respond to text.

Build speech recognition models that can transcribe audio into text.

Build recommendation systems that can suggest products or services to users.

TensorFlow.js and pretrained models

Developers can easily include pretrained models in their web applications using TensorFlow.js. With TensorFlow.js, you can benefit from robust machine learning algorithms without needing to be an expert in model deployment or training. The library offers a wide variety of pretrained models, including those for audio analysis, picture identification, natural language processing, and more (Figure 1).

Figure 1: Available pretrained model types for TensorFlow.

How does it work?

The module allows for the direct loading of models in TensorFlow SavedModel or Keras Model formats. Once the model has been loaded, developers can use its features by invoking certain methods made available by the model API. Figure 2 shows the steps involved for training, distribution, and deployment.

Figure 2: TensorFlow.js model API for a pretrained image classification model.

Training

The training section shows the steps involved in training a machine learning model. The first step is to collect data. This data is then preprocessed, which means that it is cleaned and prepared for training. The data is then fed to a machine learning algorithm, which trains the model.

Preprocess data: This is the process of cleaning and preparing data for training. This includes tasks such as removing noise, correcting errors, and normalizing the data.

TF Hub: TF Hub is a repository of pretrained ML models. These models can be used to speed up the training process or to improve the accuracy of a model.

tf.keras: tf.keras is a high-level API for building and training machine learning models. It is built on top of TensorFlow, which is a low-level library for machine learning.

Estimator: An estimator is a type of model in TensorFlow. It is a simplified way to build and train ML models.

Distribution

Distribution is the process of making a machine learning model available to users. This can be done by packaging the model in a format that can be easily shared, or by deploying the model to a production environment.

The distribution section shows the steps involved in distributing a machine learning model. The first step is to package the model. This means that the model is converted into a format that can be easily shared. The model is then distributed to users, who can then use it to make predictions.

Deployment

The deployment section shows the steps involved in deploying a machine learning model. The first step is to choose a framework. A framework is a set of tools that makes it easier to build and deploy machine learning models. The model is then converted into a format that can be used by the framework. The model is then deployed to a production environment, where it can be used to make predictions.

Benefits of using pretrained models

There are several pretrained models available in TensorFlow.js that can be utilized immediately in any project and offer the following notable advantages:

Savings in time and resources: Building an ML model from scratch might take a lot of time and resources. Developers can skip this phase and use a model that has already learned from lengthy training by using pretrained models. The time and resources needed to implement machine learning solutions are significantly decreased as a result.

State-of-the-art performance: Pretrained models are typically trained on huge datasets and refined by specialists, producing models that give state-of-the-art performance across a range of applications. Developers can benefit from these models’ high accuracy and reliability by incorporating them into TensorFlow.js, even if they lack a deep understanding of machine learning.

Accessibility: TensorFlow.js makes pretrained models powerful for web developers, allowing them to quickly and easily integrate cutting-edge machine learning capabilities into their projects. This accessibility creates new opportunities for developing cutting-edge web-based solutions that make use of machine learning’s capabilities.

Transfer learning: Pretrained models can also serve as the foundation for your process. Using a smaller, domain-specific dataset, developers can further train a pretrained model. Transfer learning enables models to swiftly adapt to particular use cases, making this method very helpful when data is scarce.

Why is containerizing TensorFlow.js important?

Containerizing TensorFlow.js brings several important benefits to the development and deployment process of machine learning applications. Here are five key reasons why containerizing TensorFlow.js is important:

Docker provides a consistent and portable environment for running applications. By containerizing TensorFlow.js, you can package the application, its dependencies, and runtime environment into a self-contained unit. This approach allows you to deploy the containerized TensorFlow.js application across different environments, such as development machines, staging servers, and production clusters, with minimal configuration or compatibility issues.

Docker simplifies the management of dependencies for TensorFlow.js. By encapsulating all the required libraries, packages, and configurations within the container, you can avoid conflicts with other system dependencies and ensure that the application has access to the specific versions of libraries it needs. This containerization eliminates the need for manual installation and configuration of dependencies on different systems, making the deployment process more streamlined and reliable.

Docker ensures the reproducibility of your TensorFlow.js application’s environment. By defining the exact dependencies, libraries, and configurations within the container, you can guarantee that the application will run consistently across different deployments.

Docker enables seamless scalability of the TensorFlow.js application. With containers, you can easily replicate and distribute instances of the application across multiple nodes or servers, allowing you to handle high volumes of user requests.

Docker provides isolation between the application and the host system and between different containers running on the same host. This isolation ensures that the application’s dependencies and runtime environment do not interfere with the host system or other applications. It also allows for easy management of dependencies and versioning, preventing conflicts and ensuring a clean and isolated environment in which the application can operate.

Building a fully functional ML face-detection demo app

By combining the power of TensorFlow.js and Docker, developers can create a fully functional machine learning (ML) face-detection demo app. Once the app is deployed, the TensorFlow.js model can recognize faces in real-time by leveraging the camera. However, with a minor code change, it’s possible for developers to build an app that allows users to upload images or videos to be detected.

In this tutorial, you’ll learn how to build a fully functional face-detection demo app using TensorFlow.js and Docker. Figure 3 shows the file system architecture for this setup. Let’s get started.

Prerequisite

The following key components are essential to complete this walkthrough:

Docker Desktop 

Figure 3: File system architecture for Docker Compose development setup.

Deploying a ML face-detection app is a simple process involving the following steps:

Clone the repository. 

Set up the required configuration files. 

Initialize TensorFlow.js.

Train and run the model. 

Bring up the face-detection app. 

We’ll explain each of these steps below.

Quick demo

If you’re in hurry, you can bring up the complete app by running the following command:

docker run -p 1234:1234 harshmanvar/face-detection-tensorjs:slim-v1

Open URL in browser: http://localhost:1234.

Figure 4: URL opened in a browser.

Getting started

Cloning the project

To get started, you can clone the repository by running the following command:

https://github.com/dockersamples/face-detection-tensorjs

We are utilizing the MediaPipe Face Detector demo for this demonstration. You first create a detector by choosing one of the models from SupportedModels, including MediaPipeFaceDetector.

For example:

const model = faceDetection.SupportedModels.MediaPipeFaceDetector;
const detectorConfig = {
runtime: ‘mediapipe’, // or ‘tfjs’
}
const detector = await faceDetection.createDetector(model, detectorConfig);

Then you can use the detector to detect faces:

const faces = await detector.estimateFaces(image);

File: index.html:

<!DOCTYPE html>
<html>

<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1.0, user-scalable=no">
<style>
body {
margin: 0;
}

#stats {
position: relative;
width: 100%;
height: 80px;
}

#main {
position: relative;
margin: 0;
}

#canvas-wrapper {
position: relative;
}
</style>
</head>

<body>
<div id="stats"></div>
<div id="main">
<div class="container">
<div class="canvas-wrapper">
<canvas id="output"></canvas>
<video id="video" playsinline style="
-webkit-transform: scaleX(-1);
transform: scaleX(-1);
visibility: hidden;
width: auto;
height: auto;
">
</video>
</div>
</div>
</div>
</div>
</body>
<script src="https://cdnjs.cloudflare.com/ajax/libs/dat-gui/0.7.6/dat.gui.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/stats.js/r16/Stats.min.js"></script>
<script src="src/index.js"></script>

</html>

The web application’s principal entry point is the index.html file. It includes the video element needed to display the real-time video stream from the user’s webcam and the basic HTML page structure. The relevant JavaScript scripts for the facial detection capabilities are also imported.

File: src/Index.js:

import ‘@tensorflow/tfjs-backend-webgl';
import ‘@tensorflow/tfjs-backend-webgpu';

import * as tfjsWasm from ‘@tensorflow/tfjs-backend-wasm';

tfjsWasm.setWasmPaths(
`https://cdn.jsdelivr.net/npm/@tensorflow/tfjs-backend-wasm@${
tfjsWasm.version_wasm}/dist/`);

import * as faceDetection from ‘@tensorflow-models/face-detection';

import {Camera} from ‘./camera';
import {setupDatGui} from ‘./option_panel';
import {STATE, createDetector} from ‘./shared/params';
import {setupStats} from ‘./shared/stats_panel';
import {setBackendAndEnvFlags} from ‘./shared/util';

let detector, camera, stats;
let startInferenceTime, numInferences = 0;
let inferenceTimeSum = 0, lastPanelUpdate = 0;
let rafId;

async function checkGuiUpdate() {
if (STATE.isTargetFPSChanged || STATE.isSizeOptionChanged) {
camera = await Camera.setupCamera(STATE.camera);
STATE.isTargetFPSChanged = false;
STATE.isSizeOptionChanged = false;
}

if (STATE.isModelChanged || STATE.isFlagChanged || STATE.isBackendChanged) {
STATE.isModelChanged = true;

window.cancelAnimationFrame(rafId);

if (detector != null) {
detector.dispose();
}

if (STATE.isFlagChanged || STATE.isBackendChanged) {
await setBackendAndEnvFlags(STATE.flags, STATE.backend);
}

try {
detector = await createDetector(STATE.model);
} catch (error) {
detector = null;
alert(error);
}

STATE.isFlagChanged = false;
STATE.isBackendChanged = false;
STATE.isModelChanged = false;
}
}

function beginEstimateFaceStats() {
startInferenceTime = (performance || Date).now();
}

function endEstimateFaceStats() {
const endInferenceTime = (performance || Date).now();
inferenceTimeSum += endInferenceTime – startInferenceTime;
++numInferences;

const panelUpdateMilliseconds = 1000;
if (endInferenceTime – lastPanelUpdate >= panelUpdateMilliseconds) {
const averageInferenceTime = inferenceTimeSum / numInferences;
inferenceTimeSum = 0;
numInferences = 0;
stats.customFpsPanel.update(
1000.0 / averageInferenceTime, 120);
lastPanelUpdate = endInferenceTime;
}
}

async function renderResult() {
if (camera.video.readyState < 2) {
await new Promise((resolve) => {
camera.video.onloadeddata = () => {
resolve(video);
};
});
}

let faces = null;

if (detector != null) {

beginEstimateFaceStats();

try {
faces =
await detector.estimateFaces(camera.video, {flipHorizontal: false});
} catch (error) {
detector.dispose();
detector = null;
alert(error);
}

endEstimateFaceStats();
}

camera.drawCtx();
if (faces && faces.length > 0 && !STATE.isModelChanged) {
camera.drawResults(
faces, STATE.modelConfig.boundingBox, STATE.modelConfig.keypoints);
}
}

async function renderPrediction() {
await checkGuiUpdate();

if (!STATE.isModelChanged) {
await renderResult();
}

rafId = requestAnimationFrame(renderPrediction);
};

async function app() {
const urlParams = new URLSearchParams(window.location.search);

await setupDatGui(urlParams);

stats = setupStats();

camera = await Camera.setupCamera(STATE.camera);

await setBackendAndEnvFlags(STATE.flags, STATE.backend);

detector = await createDetector();

renderPrediction();
};

app();

JavaScript file that conducts the facial detection logic. TensorFlow.js is loaded, allowing for real-time face detection on the video stream using the pretrained face identification model. The file manages access to the camera, processing of the video frames, and creating bounding boxes around faces that have been recognized in the video feed.

File: src/camera.js:

import {VIDEO_SIZE} from ‘./shared/params';
import {drawResults, isMobile} from ‘./shared/util';

export class Camera {
constructor() {
this.video = document.getElementById(‘video’);
this.canvas = document.getElementById(‘output’);
this.ctx = this.canvas.getContext(‘2d’);
}

static async setupCamera(cameraParam) {
if (!navigator.mediaDevices || !navigator.mediaDevices.getUserMedia) {
throw new Error(
‘Browser API navigator.mediaDevices.getUserMedia not available’);
}

const {targetFPS, sizeOption} = cameraParam;
const $size = VIDEO_SIZE[sizeOption];
const videoConfig = {
‘audio': false,
‘video': {
facingMode: ‘user’,
width: isMobile() ? VIDEO_SIZE[’360 X 270′].width : $size.width,
height: isMobile() ? VIDEO_SIZE[’360 X 270′].height : $size.height,
frameRate: {
ideal: targetFPS,
},
},
};

const stream = await navigator.mediaDevices.getUserMedia(videoConfig);

const camera = new Camera();
camera.video.srcObject = stream;

await new Promise((resolve) => {
camera.video.onloadedmetadata = () => {
resolve(video);
};
});

camera.video.play();

const videoWidth = camera.video.videoWidth;
const videoHeight = camera.video.videoHeight;
// Must set below two lines, otherwise video element doesn’t show.
camera.video.width = videoWidth;
camera.video.height = videoHeight;

camera.canvas.width = videoWidth;
camera.canvas.height = videoHeight;
const canvasContainer = document.querySelector(‘.canvas-wrapper’);
canvasContainer.style = `width: ${videoWidth}px; height: ${videoHeight}px`;
camera.ctx.translate(camera.video.videoWidth, 0);
camera.ctx.scale(-1, 1);

return camera;
}

drawCtx() {
this.ctx.drawImage(
this.video, 0, 0, this.video.videoWidth, this.video.videoHeight);
}

drawResults(faces, boundingBox, keypoints) {
drawResults(this.ctx, faces, boundingBox, keypoints);
}
}

The configuration for the camera’s width, audio, and other setup-related items is managed in camera.js.

File: .babelrc:

The .babelrc file is used to configure Babel, a JavaScript compiler, specifying presets and plugins that define the transformations to be applied during code transpilation.

File: src/shared:

shared % tree
.
├── option_panel.js
├── params.js
├── stats_panel.js
└── util.js

1 directory, 4 files

The parameters and other shared files found in the src/shared folder are needed to run and access the camera, checks, and parameter values. 

Defining services using a Compose file

Here’s how our services appear within a Docker Compose file:

services:
tensorjs:
#build: .
image: harshmanvar/face-detection-tensorjs:v2
ports:
– 1234:1234
volumes:
– ./:/app
– /app/node_modules
command: watch

Your sample application has the following parts:

The tensorjs service is based on the harshmanvar/face-detection-tensorjs:v2 image.

This image contains the necessary dependencies and code to run a face detection system using TensorFlow.js.

It exposes port 1234 to communicate with the TensorFlow.js.

The volume ./:/app sets up a volume mount, linking the current directory (represented by ./) on the host machine to the /app directory within the container. This allows you to share files and code between your host machine and the container.

The watch command specifies the command to run within the container. In this case, it runs the watch command, which suggests that the face detection system will continuously monitor for changes or updates.

Building the image

It’s time to build the development image and install the dependencies to launch the face-detection model.

docker build -t tensor-development:v1

Running the container

docker run -p 1234:1234 -v $(pwd):/app -v /app/node_modules tensor-development:v1 watch

Bringing up the container services

You can launch the application by running the following command:

docker compose up -d

Then, use the docker compose ps command to confirm that your stack is running correctly. Your terminal will produce the following output:

docker compose ps
NAME IMAGE COMMAND SERVICE STATUS PORTS
tensorflow tensorjs:v2 "yarn watch" tensorjs Up 48 seconds 0.0.0.0:1234->1234/tcp

Viewing the containers via Docker Dashboard

You can also leverage the Docker Dashboard to view your container’s ID and easily access or manage your application (Figure 5) container.

Figure 5: Viewing containers in the Docker Dashboard.

Conclusion

Well done! You have acquired the knowledge to utilize a pre-trained machine learning model with JavaScript for a web application, all thanks to TensorFlow.js. In this article, we have demonstrated how Docker Compose lets you quickly create and deploy a fully functional ML face-detection demo app, using just one YAML file.

With this newfound expertise, you can now take this guide as a foundation to build even more sophisticated applications with just a few additional steps. The possibilities are endless, and your ML journey has just begun!

Learn more

Get the latest release of Docker Desktop.

Vote on what’s next! Check out our public roadmap.

Have questions? The Docker community is here to help.

New to Docker? Get started.

Quelle: https://blog.docker.com/feed/

Docker Scout Demo and Q&A

If you missed our webinar “Docker Scout: Live Demo, Insights, and Q&A” — or if you want to watch it again — it’s available on-demand. The audience had more questions than we had time to answer, so we’ve included additional Q&A below.

Many developers — and their employers — are concerned with securing their software supply chain. But what does that mean? Senior Developer Relations Manager Michael Irwin uses a coffee analogy (even though he doesn’t drink coffee himself!). To brew the best cup of coffee, you need many things: clean water, high-quality beans, and good equipment. For the beans and the water, you want assurances that they meet your standards. You might look for beans that have independent certification of their provenance and processing to make sure they are produced sustainably and ethically, for example.

The same concepts apply to producing software. You want to start with trusted content. Using images from Docker Official Images, Docker Verified Publishers, and Docker-Sponsored Open Source lets you know you’re building on a reliable, up-to-date foundation. From those images and your layered software libraries, Docker can build a software bill of materials (SBOM) that you can present to your customers to show exactly what went into making your application. And with Docker Scout, you can automatically check for known vulnerabilities, which helps you find and fix security issues before they reach your customers.

During the webinar, Senior Principal Software Engineer Christian Dupuis demonstrated using Docker Scout. He highlighted how Docker Scout utilizes SBOM and provenance attestation produced by BuildKit. He also showed Docker Scout indicating vulnerabilities by severity. Docker Scout doesn’t stop at showing vulnerabilities, it lets you know where the vulnerability is added to the image and provides suggestions for remediation.

The audience asked great questions during the live Q&A. Since we weren’t able to answer them all during the webinar, we want to take a moment to address them now.

Webinar Q&A

What source does Docker Scout use to determine the CVEs?

Docker Scout gets vulnerability data from approximately 20 advisory sources. This includes Linux distributions and code repository platforms like Debian, Ubuntu, GitHub, GitLab, and other trustworthy providers of advisory metadata.

We constantly cross-reference the SBOM information stored in the Docker Scout system-of-record with advisory data. New vulnerability information is immediately reflected on Docker Desktop, in the Docker Scout CLI, and on scout.docker.com.

How much does Docker Scout cost?

Docker Scout has several different price tiers. You can start for free with up to 3 image repositories; if you need more, we also offer paid plans. The Docker Scout product page has a full comparison to help you pick the right option.

How do I add Docker Scout to my CI pipeline?

The documentation on Docker Scout has a dedicated section on CI integrations. 

How can I contribute?

There are several ways you can engage with the product team behind Docker Scout and influence the roadmap:

For feedback and issues about Docker Scout in the CLI, CI, Docker Desktop or scout.docker.com, open issues at https://github.com/docker/scout-cli.

Learn more about the Docker Scout Design Partner Program.

What platforms are supported?

Docker Scout works on all supported operating systems. You can use Docker Scout in Docker Desktop version 4.17 or later or log in to scout.docker.com to see information across all of your Docker Hub images. Make sure you keep your Docker Desktop version up to date — we’re adding new features and capabilities in every release.

We also provide a Docker Scout CLI plugin. You can find instructions in the scout-cli GitHub repository.

How do I export a list of vulnerabilities?

You can use the Docker Scout CLI to export vulnerabilities into a SARIF file for further processing or export. You can read more about this in the Docker Engine documentation.

How does Docker Scout help if I’m already using scanning tools?

Docker Scout builds upon a system of record for the entire software development life cycle, so you can integrate it with other tools you use in your software delivery process. Talk to us to learn more. 

Get started with Docker Scout

Developers want speed, security, and choice. Docker Scout helps improve developer efficiency and software security by detecting known vulnerabilities early. While it offers remediation suggestions, developers still have the choice in determining the best approach to addressing vulnerabilities. Get started today to see how Docker Scout helps you secure your software supply chain.

Learn more

Watch our webinar “Docker Scout: Live Demo, Insights, and Q&A”.

Get the latest release of Docker Desktop.

Vote on what’s next! Check out our public roadmap.

Have questions? The Docker community is here to help. 

New to Docker? Get started.

Quelle: https://blog.docker.com/feed/

Unleash Docker Desktop 4.22: The Featherweight Heavy-Hitter for Supercharged Rapid Development

Docker is committed to delivering the most efficient and high-performing container development toolset in the market, so we continue to advance our technology to exceed customer expectations. With the latest version 4.22 release, Docker Desktop has undergone significant optimizations, making it streamlined, lightweight, and faster than ever. Not only does this new version offer enhanced performance, but it also contributes to a more environmentally friendly approach, saving energy and reducing resource consumption on local machines:

Network speeds from 3.5 Gbit/sec to 19 Gbit/sec — a 443% improvement

Filesystem improvements that yield 60% faster builds

Enhanced active memory usage from 4GB to 2GB — a 2x improvement

Resource Saver mode — automatically reduces CPU and memory utilization by 10x

Discover how our commitment to delivering exceptional experiences for our developer community and customers shines through in the latest updates to Docker Desktop.

4.19: Networking stack — turbocharging container connectivity

The Docker Desktop 4.19 release brought a substantial boost to Docker Desktop’s networking stack, the technology used by containers to access the internet. This upgrade significantly enhances networking performance, which is particularly beneficial for tasks like docker builds, which often involve downloading and installing numerous packages. 

Benchmark tests using iperf3 on a first-generation M1 Mac Mini demonstrated remarkable progress. The previous unoptimized network stack managed around 3.5 Gbit/sec, whereas the current default networking stack in 4.19+ achieves an impressive 19 Gbit/sec on the same machine. This optimization translates to faster build times and smoother container operations.

4.21: Optimized CPU, memory, and filesharing performance

Docker Desktop 4.21 introduced the first version of what is now a game-changing feature, Resource Saver, which automatically reduces CPU. This intelligent mode detects when Docker Desktop is not running containers and automatically reduces CPU consumption, ensuring that developers can keep the application running in the background without compromising battery life or dealing with noisy laptop fans. Across all Docker Desktop users on 4.21, this innovative feature has saved up to 38,500 CPU hours every day, making it a true productivity booster.

Furthermore, Docker Desktop 4.21 significantly enhanced its active memory usage, slashing it from approximately 4GB to around 2GB — a remarkable 2x advancement. This empowers developers to seamlessly juggle multiple applications alongside Docker Desktop, resulting in an elevated and smoother user experience.

Additionally, Docker Desktop now utilizes VirtioFS on macOS 12.5+ to deliver substantial performance gains when sharing files with containers through docker run -v. Notably, the time needed for a clean (non-incremental) build of redis/redis checked out on the host has been reduced by more than half over recent releases resulting in ~60% faster builds, further solidifying Docker Desktop’s reputation as an indispensable development tool.

4.22: Heightened efficiency — dramatically reducing memory utilization when idle

Now, with the release of Docker Desktop 4.22, we’re excited to announce that  Docker Desktop’s newest performance enhancement feature, Resource Saver, supports automatic low memory mode for Mac, Windows, and Linux. This addition detects when Docker Desktop is not running containers and dramatically reduces its memory footprint by 10x, freeing up valuable resources on developers’ machines for other tasks and minimizing the risk of lag when navigating across different applications. Memory allocation can now be quick and efficient, resulting in a seamless and performant development experience.

But don’t just take it from us. In “What is Resource Saver Mode in Docker Desktop and what problem does it solve?” Ajeet Raina explains how the new Resource Saver feature optimizes efficiency, enhances performance, and simplifies the development workflow.

Conclusion

Docker Desktop continues to evolve. The latest enhancements in version 4.22, combined with the resource-saving features introduced in 4.21 and 4.19, have made Docker Desktop a lighter, faster, and more environmentally friendly solution for developers. 

By optimizing resource usage and maximizing performance, Docker Desktop enables developers to build and release applications faster while being conscious of their environmental impact. As Docker continues to innovate and fine-tune its offerings, developers can expect even greater strides toward a more efficient and productive development experience.

Download or update to the newest version of Docker Desktop today to start saving time and take advantage of these new advancements.

Learn more

Get the latest release of Docker Desktop.

Vote on what’s next! Check out our public roadmap.

Have questions? The Docker community is here to help.

New to Docker? Get started.

Quelle: https://blog.docker.com/feed/