← All posts

Docker made my model portable, and my results reproducible

5 min read
MLOpsDockerPython

There is a specific kind of despair that comes from an experiment that ran perfectly last Tuesday and refuses to run today. Same code. Same data. Different answer.

Almost always, the culprit is the environment.

The invisible dependency

A machine learning project depends on far more than its import statements. It depends on the Python minor version, the CUDA version, a system library that happened to be installed, and the exact version of a package that changed its default parameter three releases ago.

None of that is in your repository. All of it changes your results.

Containers as a lab notebook

A Dockerfile is the honest version of your setup instructions — it fails loudly if a step is missing, which is exactly what a README never does.

FROM python:3.11-slim

WORKDIR /app

# Dependencies first: this layer is cached until requirements.txt changes.
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

COPY . .

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

Copying requirements.txt before the rest of the source is the small trick that saves the most time. Docker caches layers, so editing train.py no longer reinstalls every dependency.

Things that surprised me

  • Pin your versions. pip install pandas today and in six months are different programs. pandas==2.2.3 is a fact; pandas is a wish.
  • Slim images are worth it. Swapping the full Python image for -slim cut my image by hundreds of megabytes, and I never missed what was removed.
  • Data does not belong inside the image. Mount it as a volume. An image that carries a dataset is an image nobody wants to pull.
  • .dockerignore matters more than expected. Without it I was copying .git, virtual environments, and checkpoints into every build.

The part that actually changed how I work

Once the container existed, “run my experiment” became one command that behaves identically on my laptop and on a cloud instance. Reproducibility stopped being a thing I hoped for and became a property of the setup.

That is the whole point of MLOps, as far as I can tell: making the boring parts boring.

got thoughts?

Let's talk

© 2026 Prashansa Soni