Curso

Imagina que has trabajado en un problema de machine learning de extremo a extremo y has llegado a la mejor solución con los modelos óptimos. Sin embargo, cuando envías tu código al equipo de ingeniería, lo que funcionaba en tu máquina no funciona en sus servidores, que pueden tener otro sistema operativo y versiones de librerías distintas.
A pesar de tu esfuerzo y cuidado, esta situación puede ocurrir y resulta frustrante. Casi todos los desarrolladores la viven alguna vez. ¿La solución? Ahí es donde entra Docker. Con Docker puedes definir un entorno preciso y consistente para tu proyecto y asegurarte de que el código se ejecutará sin problemas, independientemente del sistema o la configuración subyacente.
Este tutorial te presentará Docker y sus conceptos relacionados, y explicará por qué es importante para las personas que trabajan con datos. Además, te ayudará a instalar la herramienta y a usarla en tu próximo proyecto con ejemplos. Por último, conocerás las mejores prácticas del sector al trabajar con Docker y resolverás todas tus dudas habituales.
¿Qué son Docker, los contenedores y las imágenes?
Docker es una plataforma para crear, ejecutar y distribuir aplicaciones.
Los contenedores son paquetes ejecutables, ligeros e independientes que incluyen todo lo necesario para ejecutar una aplicación: el código, un runtime, librerías, variables de entorno y archivos de configuración.
Una imagen de Docker es un archivo de solo lectura que contiene todas las instrucciones necesarias para crear un contenedor. Se utilizan para crear e iniciar nuevos contenedores en tiempo de ejecución.
Docker ayuda a empaquetar las aplicaciones junto con sus dependencias en un contenedor que puede ejecutarse en cualquier máquina que tenga Docker instalado.
En cierto modo, es como si te dieran una máquina nueva para cada proyecto: instalas los paquetes, copias los archivos necesarios y ejecutas los scripts. Luego puedes enviar esa “máquina” a otra parte. Es un ejemplo simplificado, pero se entiende la idea.
¿En qué se diferencian los contenedores de las máquinas virtuales?
Al definir contenedores, es normal preguntarse en qué se diferencian de las máquinas virtuales, ya que ambas tecnologías permiten ejecutar varios entornos aislados en la misma máquina física.
Observa la diferencia de arquitectura en la imagen siguiente e intenta detectar el matiz.

Imagen del autor
Cada máquina virtual es un entorno aislado que puede ejecutar distintos sistemas operativos y configuraciones. Esto implica que cada VM requiere una copia completa del sistema operativo, lo que consume muchos recursos. Una aplicación en contenedor, en cambio, se ejecuta en un entorno aislado sin necesitar una copia completa del sistema operativo, por lo que es más ligera y eficiente.
Aunque las máquinas virtuales son útiles, los contenedores suelen ser suficientes e ideales para distribuir aplicaciones.
¿Por qué Docker para profesionales de datos?
Puede que te preguntes por qué deberías aprender Docker siendo científico o científica de datos. ¿No está para eso el equipo de DevOps que se encarga de la infraestructura?
Buena pregunta, pero Docker es clave para data scientists, incluso si hay un equipo de DevOps. Veamos por qué es tan útil.
Integración con el equipo de DevOps
Tener un equipo de DevOps no elimina las ventajas de usar Docker; de hecho, ayuda a tender puentes entre desarrollo y operaciones. Quien hace ciencia de datos puede empaquetar su código con Docker y pasarlo al equipo de DevOps para su despliegue y escalado. Esto es habitual en equipos de datos bien organizados.
Entorno consistente y reproducibilidad
En ciencia de datos se trabaja con dependencias y configuraciones complejas que hay que instalar y mantener. El entorno debe permanecer estable para obtener resultados equivalentes. Docker permite crear y compartir un entorno consistente con todas las dependencias y configuraciones preinstaladas, que otras personas pueden replicar con facilidad.
Portabilidad
Los contenedores de Docker pueden ejecutarse en cualquier entorno con Docker instalado: portátiles, servidores y plataformas en la nube. Así podrás mover tu trabajo entre entornos sin fricción.
Aislamiento de recursos
Docker permite ejecutar varios contenedores en la misma máquina, cada uno con sus recursos aislados. Esto ayuda a gestionar los recursos de forma más eficiente y evita conflictos con otras aplicaciones. Si tienes varios proyectos de ML, esta funcionalidad te puede salvar la vida.
Facilita la colaboración
Docker permite compartir el trabajo con cualquiera, incluidos equipos remotos, empaquetándolo en contenedores. La colaboración es esencial en ciencia de datos y Docker reduce la fricción.
La mayoría de profesionales con experiencia coincide: con Docker, podrás centrarte en el trabajo sin preocuparte por la infraestructura subyacente.
Tutorial de Docker: úsalo en tu próximo proyecto
Ya que hemos visto por qué Docker es necesario para perfiles de datos, vamos al grano. Primero instalaremos Docker en nuestra máquina y nos familiarizaremos con los comandos básicos.
Instalar Docker en tu equipo o servidor local
Docker está disponible para los principales sistemas operativos: Linux, Windows y Mac. La instalación es sencilla y lo mejor es seguir la documentación oficial.
- Instrucciones para instalar Docker en Linux.
- Instrucciones para instalar Docker en Windows.
- Instrucciones para instalar Docker en Mac.
Si quieres crear tus propias imágenes y subirlas a Docker Hub (como verás en algunos comandos más abajo), debes crear una cuenta en Docker Hub. Piensa en Docker Hub como un lugar central donde la comunidad guarda y comparte imágenes de Docker.
Familiarizarte con los comandos comunes de Docker
Una vez hayas configurado Docker en tu máquina (o servidor), el siguiente paso es familiarizarte con algunos comandos. Aquí tienes la lista de referencia en la documentación oficial de Docker.
Para empezar, te resumimos los diez comandos más usados que vas a encontrar sí o sí.
- docker run: se usa para ejecutar un contenedor a partir de una imagen. La opción -p mapea un puerto de la máquina anfitriona con un puerto del contenedor. Por ejemplo, el siguiente comando ejecuta un contenedor a partir de la imagen "nginx" y mapea el puerto 80 del host al 80 del contenedor.
docker run -p 80:80 nginx- docker ps: lista todos los contenedores en ejecución. Es útil cuando tenemos varios contenedores aislados en la misma máquina.
docker ps- docker stop: detiene un contenedor en ejecución.
docker stop <container_id>- docker rm: elimina un contenedor detenido.
docker rm <container_id>- docker images: lista todas las imágenes en la máquina anfitriona. Sirve para ver qué imágenes locales tenemos antes de crear un contenedor a partir de ellas.
docker images- docker rmi: elimina una imagen.
docker rmi <image_id>- docker build: construye una imagen desde un Dockerfile. La opción -t especifica el nombre de la imagen y el . final indica el contexto de build (el directorio actual).
docker build -t my_image .- docker exec: ejecuta un comando dentro de un contenedor en ejecución.
docker exec -it <container_id> /bin/bash- docker pull: descarga una imagen de un registro como Docker Hub.
docker pull <image_name>- docker push: sube una imagen a un registro.
docker push <image_name>
Ahora que ya sabes configurar Docker y manejar los comandos básicos, el siguiente objetivo es dockerizar una aplicación de machine learning.
¿Te gustaría obtener una certificación de Docker? Echa un vistazo a nuestra guía para conseguir una Docker certification.
Dockerizar una aplicación sencilla de machine learning
Dockerizar una aplicación de machine learning es más fácil de lo que parece si sigues un enfoque en tres pasos.

Imagen del autor.
Para mantenerlo simple, usaremos un script de iniciación cuyo objetivo es mostrar cómo dockerizarlo. El ejemplo crea un modelo de regresión logística sobre el conjunto de datos iris.
# Load the libraries
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import accuracy_score
# Load the iris dataset
iris = load_iris()
X = iris.data
y = iris.target
# Split the data
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2)
# Train a logistic regression model
clf = LogisticRegression()
clf.fit(X_train, y_train)
# Make predictions
y_pred = clf.predict(X_test)
# Print the accuracy of the model
accuracy_score = accuracy_score(y_test, y_pred)
print(f'Accuracy: {accuracy_score}')
1. Definir el entorno
Necesitas conocer con precisión tu entorno actual para poder replicarlo en otro sitio. La forma más sencilla (y común) es crear un archivo requirements.txt que detalle todas las librerías del proyecto con sus versiones.
Así podría verse el contenido del archivo:
scikit-learn==1.2.0
Nota: una aplicación de machine learning más compleja usará más librerías como NumPy, pandas, matplotlib, etc. Por eso, crear un archivo requirements.txt tiene más sentido que instalar paquetes sueltos (hablaremos más de ello en las mejores prácticas).
2. Escribir un Dockerfile
El siguiente paso es crear un archivo llamado Dockerfile que cree el entorno y ejecute nuestra aplicación en él. En otras palabras, es el manual de instrucciones para Docker: qué entorno usar, qué incluir y cómo ejecutar.
FROM python:3.9
WORKDIR /src
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
CMD ["python","iris_classification.py"]
Este Dockerfile usa la imagen oficial de Python como base, establece el directorio de trabajo, copia el requirements.txt e instala las dependencias, copia el código de la aplicación y ejecuta el comando python iris_classification.py para iniciarla.
3. Construir la imagen
El último paso para crear un entorno reproducible es generar una imagen (una especie de plantilla) con la que podrás crear cualquier número de contenedores con la misma configuración.
Puedes construir la imagen ejecutando el comando docker build -t <image-name> . en el mismo directorio donde está el Dockerfile.
Ahora que has dockerizado la aplicación sencilla que vimos, ya puedes usar docker run para crear contenedores y detenerlos cuando lo necesites. Los comandos básicos ya los cubrimos antes.
Pasemos ahora de lo básico a lo que se espera en la industria.
Mejores prácticas del sector al usar Docker
Con lo básico basta para empezar, pero en entornos profesionales es clave seguir buenas prácticas.
Mantener pocas capas
Cada instrucción del Dockerfile genera una capa nueva. Demasiadas capas hacen la imagen más pesada y lenta de transferir.
Observa este ejemplo de código:
# Use the official Python image as the build image
FROM python:3.9
# Install the dependencies
RUN pip install pandas
RUN pip install matplotlib
RUN pip install seaborn
# Copy neccesary files
COPY my_script.py .
COPY data/ .
# Run the script
CMD ["python","my_script.py"]
¿Qué problema ves? El uso de varios comandos run y copy es innecesario. Así podemos mejorarlo:
# Use the official Python image as the build image
FROM python:3.9
# Install the dependencies using requirements.txt
COPY my_script.py requirements.txt data/ .
RUN pip install --no-cache-dir -r requirements.txt
# Run the script
CMD ["python","my_script.py"]
Aunque aquí se ve claro por ser un archivo pequeño, te sorprendería lo a menudo que escribimos Dockerfiles más grandes de lo necesario. Agrupar comandos que hacen funciones similares o modifican los mismos archivos es una forma sencilla de reducir capas.
Usar imágenes oficiales
Las imágenes oficiales son mantenidas y soportadas por el editor de la imagen. Suelen ser más estables y seguras que otras.
A veces, por las prisas, tiramos de una imagen no oficial. Siempre que puedas, usa imágenes oficiales como base para tus propias imágenes.
Compilaciones multietapa para optimizar
Una compilación multietapa en Docker te permite usar varias instrucciones FROM en un solo Dockerfile.
Podemos usar una imagen más grande para compilar la aplicación y luego copiar los archivos necesarios a una imagen de ejecución más pequeña. Al no incluir archivos innecesarios, reducimos el tamaño final de la imagen, optimizamos el rendimiento y además mejoramos la seguridad.
Veámoslo con un ejemplo muy habitual en la industria:
# Use the official Python image as the build image
FROM python:3.9 AS build
# Set the working directory
WORKDIR /app
# Copy the requirements.txt file
COPY requirements.txt ./
# Install the dependencies
RUN pip install --no-cache-dir -r requirements.txt
# Copy the application files
COPY . .
# Train the model
RUN python train.py
# Use the official Alpine Linux image as the runtime image
FROM alpine:3
# Set the working directory
WORKDIR /app
# Copy the model files from the build image
COPY --from=build /app/models /app/models
# Copy the requirements.txt file
COPY --from=build /app/requirements.txt /app
# Install the dependencies
RUN pip install --no-cache-dir -r requirements.txt
# Run the application
CMD ["python","predict.py"]
Desglosando el ejemplo: primero usamos la imagen oficial de Python como imagen de compilación e instalamos las dependencias en esa etapa.
Tras ejecutar train.py, copiamos los archivos del modelo generado y el requirements.txt a una imagen más pequeña de Alpine Linux para la ejecución, que usaremos para poner en marcha la aplicación. Gracias a la compilación multietapa y a no incluir dependencias de build ni el intérprete de Python en la imagen final, conseguimos un tamaño mucho menor.
Usar volúmenes para persistir datos
Los datos dentro de un contenedor se pierden cuando se detiene y elimina. A veces necesitas conservar los resultados de los experimentos o compartir datos entre varios contenedores.
Con volúmenes, los datos se guardan fuera del contenedor. Aquí tienes un ejemplo:
# Use the official Python image as the base image
FROM python:3.9
# Set the working directory
WORKDIR /app
# Copy the requirements.txt file
COPY requirements.txt ./
# Install the dependencies
RUN pip install --no-cache-dir -r requirements.txt
# Copy the rest of the application files
COPY . .
# Create a directory for storing data
RUN mkdir /app/data
# Define a volume for the data directory
VOLUME /app/data
# Run the application
CMD ["python","main.py"]
Organizar y versionar imágenes de Docker
Cuando empiezas a trabajar con varias imágenes de Docker, todo puede volverse caótico y conviene organizarlas. Aunque cada organización tiene sus normas, estas son prácticas comunes:
- Seguir una convención de nombres consistente para cada imagen. Por ejemplo, <registry>/<organization>/<image>:<version>. Ayuda a identificar imágenes y versiones en el registro.
- Aplicar versionado de imágenes para poder volver atrás si es necesario. La versión puede seguir el esquema <versión mayor>.<versión menor>.<parche>.
- Etiquetar imágenes con términos significativos como latest, staging, production. Permite identificar rápidamente qué imágenes están destinadas a cada entorno y fase del pipeline de despliegue.
Lo ideal es alinearte con tu organización para que todo el equipo siga la misma convención.
Conclusión
En este artículo hemos visto la importancia de crear código y aplicaciones reproducibles con herramientas como Docker para profesionales de datos. Empezamos por su relevancia, seguimos con la instalación y los comandos más comunes. Después vimos cómo dockerizar aplicaciones de machine learning con ejemplos y repasamos las mejores prácticas del sector.
Si quieres seguir aprendiendo, puedes hacer nuestro curso Introduction to Docker, que cubre los aspectos esenciales. También puedes plantearte obtener una Docker certification si trabajas en el área.
Muchos data scientists se centran en competencias clave como estadística, matemáticas, machine learning, deep learning y programación, pero se olvidan de las buenas prácticas de ingeniería de software que se esperan en la industria.
Si quieres afianzar tus conocimientos troncales en ciencia de datos, échale un ojo al Data Scientist with Python track, que propone un aprendizaje guiado con proyectos. Si en cambio necesitas ponerte al día en ingeniería de software, mira el curso software engineering for data scientists with Python, que cubre conceptos esenciales como modularidad, documentación y pruebas automatizadas.
Docker para profesionales de datos: preguntas frecuentes
¿Deberían las personas que hacen ciencia de datos aprender Docker?
Aprender Docker puede ser muy útil para quienes trabajan con datos porque permite gestionar fácilmente dependencias y entornos, garantizando que el código se ejecute de forma consistente en distintos sistemas. Además, evita depender por completo del equipo de DevOps.
¿Cómo uso Jupyter Notebook en un contenedor de Docker?
Para usar Jupyter Notebook en un contenedor de Docker, de forma similar al tutorial anterior, puedes crear un nuevo Dockerfile y usar el comando RUN para instalar Jupyter. Después, utiliza CMD para iniciar el servidor de Jupyter Notebook. Alternativamente, puedes usar imágenes precompiladas del Docker Hub con Jupyter instalado. Aquí tienes una guía detallada sobre Jupyter Notebook, también a través de Docker.
¿Cómo puedo compartir mis proyectos de ciencia de datos con Docker?
Puedes compartir tus proyectos de ciencia de datos con Docker subiendo tu imagen a un registro como Docker Hub. A partir de ahí, otras personas pueden descargar la imagen y ejecutar el proyecto en su entorno.



