Containerize ML Models with Docker

Learn to package ML models with Docker for reproducible, portable deployments. This tutorial covers Docker basics, writing a Dockerfile, building and running a container, and best practices for data science workflows.

Focus: containerize ml models with docker

Sponsored

You've trained a model that achieves great metrics in your notebook, but when your colleague tries to run the same code on their machine, it fails with cryptic dependency errors. Or your production server runs a different Python version, so your model outputs gibberish. This is the classic "works on my machine" problem, and it's a major source of friction in data science. But there's a proven solution: containerizing your ML models with Docker. By packaging your code, dependencies, and runtime into a self-contained unit, you can ship models that run identically anywhere—on your laptop, your colleague's desktop, or a cloud server. In this lesson, you'll learn the core concepts and hands-on steps to containerize your ML models, making your work reproducible, portable, and ready for production.

The problem this lesson solves

You've just spent hours tuning a Random Forest classifier and the results are brilliant—in your Jupyter notebook. But when you try to deploy it as a REST API on a server, everything falls apart. Why? Here are the usual culprits:

  • Dependency hell: Your model needs scikit-learn==1.2.0, but the server has 1.1.0, and the API behaves differently.
  • Python version mismatch: Your code uses match statements (Python 3.10+), but the server runs Python 3.8.
  • System-level packages: Your model relies on a compiled library like libgomp that isn't installed on the target machine.

Even in a team environment, sharing your model means sharing a whole environment—which is fragile and error-prone. The pain is real: hours of debugging that should take minutes.

Containerization fixes this by bundling your model, code, dependencies, and runtime into a single artifact that runs anywhere Docker is installed. That's the promise of Docker for ML.

Core concept / mental model

Think of Docker as a shipping container for software. In logistics, a shipping container holds goods securely and can be moved by ship, train, or truck without opening it. Similarly, a Docker container holds your application—code, libraries, system tools, settings—and can run on any system with Docker installed, without conflicts.

Key definitions

  • Image: A read-only template. Think of a snapshot of your environment, including your code and all dependencies.
  • Container: A running instance of an image. It's like starting a process from the snapshot.
  • Dockerfile: A text file with instructions on how to build an image. It's like a recipe.

Why this matters for ML

Machine learning models are particularly sensitive to environment changes. The version of NumPy, the exact implementation of a solver, or a random seed can alter predictions. By containerizing your model, you ensure that the same code always produces the same result, regardless of where it runs.

Here's a simple analogy: your model is a pizza. The Dockerfile is the recipe. The image is the frozen pizza kit. The container is the cooked pizza. You can hand out the kit, and everyone gets the same tasty result.

Pro tip: Docker also solves the "but it works on my machine" problem for your future self. Even you will forget the exact setup six months from now—a container preserves it forever.

How it works step by step

The process of containerizing an ML model has a clear workflow:

  1. Write a Dockerfile: Define the base image, copy your code, install dependencies, and set the command to run.
  2. Build the image: Use docker build to create the image from the Dockerfile.
  3. Run the container: Use docker run to execute the model inside the container.

Let's explore each step with a focus on ML-specific considerations.

Step 1: Write a Dockerfile

The Dockerfile is the heart of containerization. Here's a minimal example for an ML model that loads a saved model and makes predictions:

# Use an official Python runtime as the base image
FROM python:3.10-slim

# Set the working directory inside the container
WORKDIR /app

# Copy the requirements file first (leverage Docker layer caching)
COPY requirements.txt .

# Install dependencies
RUN pip install --no-cache-dir -r requirements.txt

# Copy the rest of the application code
COPY . .

# Command to run the model server
CMD ["python", "predict.py"]

Step 2: Build the image

Navigate to the folder containing your Dockerfile and run:

docker build -t my-ml-model .

This creates an image tagged my-ml-model. Docker executes each instruction in the Dockerfile, creating a new layer for each step. This layering is powerful: if you change only your code, Docker can reuse cached layers for the unaffected steps, speeding up subsequent builds.

Step 3: Run the container

docker run -p 5000:5000 my-ml-model

This starts a container from the image and maps port 5000 of your host to port 5000 in the container, so your API is accessible at http://localhost:5000.

Hands-on walkthrough

Let's put this into practice with a complete example. We'll create a simple ML model that predicts house prices, then containerize it.

1. Create your model files

First, create a directory and add the following files.

model.py – trains a simple linear regression model and saves it:

import numpy as np
from sklearn.linear_model import LinearRegression
import joblib

# Dummy data: house size in square feet vs price
X = np.array([[750], [800], [850], [900], [950]])
y = np.array([150000, 160000, 170000, 180000, 190000])

# Train
model = LinearRegression()
model.fit(X, y)

# Save
joblib.dump(model, 'house_price_model.pkl')
print("Model trained and saved.")

predict.py – loads the model and provides a prediction function:

import joblib
import numpy as np

# Load the model
model = joblib.load('house_price_model.pkl')

# Simple prediction
size = float(input("Enter house size (sq ft): "))
prediction = model.predict(np.array([[size]]))[0]
print(f"Predicted price: ${prediction:,.2f}")

requirements.txt – specify dependencies:

scikit-learn==1.2.0
numpy==1.24.0
joblib==1.2.0

2. Train and save the model

Run model.py to generate the model file:

python model.py

You should see Model trained and saved.

3. Write the Dockerfile

As shown earlier, but with our specific files:

FROM python:3.10-slim

WORKDIR /app

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

COPY . .

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

4. Build the image

docker build -t housing-price-predictor .

Expected output ends with something like:

Successfully built a1b2c3d4e5f6
Successfully tagged housing-price-predictor:latest

5. Run the container

Since predict.py expects input, we'll run it interactively:

docker run -it housing-price-predictor

You'll be prompted:

Enter house size (sq ft):

Enter 1200 and you'll see:

Predicted price: $???,???

You've just executed your ML model inside a container! This same container runs identically on any machine with Docker.

Compare options / when to choose what

Docker is not the only way to package and deploy ML models. Here's a comparison to help you choose:

Approach Pros Cons Best for
Docker container Full control, identical environment, portable, permissive Steeper learning curve, image size can be large General ML models, APIs, microservices
MLflow models Built-in experiment tracking, easy model registry, supports multiple flavors Requires MLflow setup, less control over low-level details Teams already using MLflow for lifecycle management
ONNX Runtime High performance on many platforms, supports model conversion Not all models convert cleanly, no Python code bundling Models that need speed or edge deployment

For most scenarios, Docker is the go-to choice because it gives you total control and works universally. If you need experiment tracking alongside deployment, MLflow is a great complement—you can even run MLflow models inside Docker containers.

Pro tip: If your model is a simple API, consider using a lightweight base image like python:3.10-alpine to reduce size and startup time.

Troubleshooting & edge cases

Even with Docker, things can go wrong. Here are common issues and fixes:

docker: command not found

Docker isn't installed. Download and install Docker Desktop from the official website, then restart your terminal.

Build errors: ERROR: No matching distribution found for scikit-learn==1.2.0

Your base image's Python version may not support that package version. Check your python version in the image (docker run python:3.10-slim python --version) and ensure compatibility.

Model file not found

If the model isn't in the container, you likely forgot to COPY it. Make sure house_price_model.pkl exists before building, and that your Dockerfile includes COPY . ..

Input 0 of layer ... is incompatible with the layer errors

This happens when the model expects a different input shape than what you're passing. Debug by printing the model's expected shape on the host, then match it in your prediction code.

Large image size

ML models and libraries can make images huge. Use multi-stage builds or a slim base to minimize size.

What you learned & what's next

You now understand how to containerize ML models with Docker. You can:

  • Explain why containerization solves reproducibility and portability problems.
  • Write a basic Dockerfile for an ML model.
  • Build and run a Docker image with your model.

This is a game-changer for your data science workflow: you can share your model confidently, deploy it to any server, and ensure consistent results.

What's next? In the next lesson in the Python for data science track, you'll explore deploying models as REST APIs with FastAPI—a natural companion to Docker. You'll learn how to turn your containerized model into a web service that others can query, completing the journey from notebook to production.

To solidify this lesson, try this mini-exercise: modify the example to include a simple API (e.g., using Flask or FastAPI) inside the container. Then rebuild and run it, accessing the API from your browser. This will prepare you for the next step.

Practice recap

As a mini-exercise, modify the house-price example to serve predictions via a simple Flask endpoint inside the container. Create a server.py that returns a JSON response, and adjust the CMD to run the server. Rebuild and run with port mapping, then test with curl to see your model respond as an API.

Common mistakes

  • Forgetting to copy the trained model file (e.g., .pkl) into the image—use COPY . . or explicitly list it.
  • Using a base image with a Python version incompatible with your dependencies—always align versions.
  • Installing all dependencies with pip install without a requirements.txt—makes builds non-reproducible and slower.
  • Neglecting to test the container locally before deployment—a quick docker run avoids production surprises.

Variations

  1. Use a multi-stage Docker build to reduce image size by only copying necessary artifacts (e.g., trained model and minimal runtime).
  2. Leverage --platform flags to build for different architectures (e.g., ARM vs x86) when deploying to diverse hardware.
  3. Combine Docker with MLflow to log and version both the model and the environment, enabling easier rollbacks and experiment comparison.

Real-world use cases

  • Deploying a customer churn prediction model as a microservice in a cloud-native environment (e.g., Kubernetes) using Docker.
  • Serving a computer vision model on edge devices (like a Raspberry Pi) with a lightweight Docker image.
  • Creating a reproducible research environment for a data science team, ensuring everyone runs the same model version for audits.

Key takeaways

  • Docker solves the reproducibility problem by packaging the model, code, and environment into a self-contained artifact.
  • A Dockerfile defines the image: base image, dependencies, and run command—each instruction adds a layer.
  • The build and run workflow is simple: docker build -t <name> . and docker run <name>.
  • Always specify exact dependency versions in requirements.txt and test the container locally to avoid surprises.
  • Containerization is the first step toward production deployment—pair it with an API framework for full model serving.
  • Understand trade-offs between Docker, MLflow, and ONNX to choose the right deployment pattern for your project.

Sponsored

Sponsored

Discussion

Questions, corrections, and tips help everyone reading this page.

0 comments

Add a comment

Shown publicly with your comment.

Be constructive · max 4,000 characters

No comments yet — start the thread.

Related tutorials, quizzes, and articles for this topic.