Cómo contenerizar una aplicación utilizando Docker
Aprende a contenerizar aplicaciones de aprendizaje automático con Docker y Kubernetes. Una guía para principiantes sobre cómo crear, desplegar y escalar modelos ML en contenedores en producción.
A medida que las aplicaciones de aprendizaje automático se vuelven más complejas, conseguir que nuestros modelos de aprendizaje automático pasen del desarrollo a la producción no consiste sólo en escribir un buen código. Se trata de garantizar que nuestra aplicación funcione de forma coherente en distintos entornos. Aquí es donde entra en juego la contenedorización. Pero, ¿qué es exactamente la contenedorización y por qué supone un cambio de juego para los flujos de trabajo del aprendizaje automático?
La contenerización es una forma ligera y portátil de empaquetar una aplicación junto con todas sus dependencias, bibliotecas y configuraciones en una única unidad llamada contenedor. A diferencia de las máquinas virtuales (VM) tradicionales, los contenedores comparten el sistema operativo del sistema anfitrión, lo que los hace más rápidos, eficientes y fáciles de escalar.
Para los científicos de datos y los ingenieros de ML, esto significa que puedes construir un modelo en tu máquina local y desplegarlo en cualquier lugar, ya sea en una plataforma en la nube, en un servidor o incluso en el portátil de un colega, sin preocuparte por problemas de compatibilidad.
En este tutorial, veremos cómo contenerizar una aplicación de aprendizaje automático utilizando Docker y Kubernetes. Al final, sabrás cómo hacerlo:
Construye un contenedor Docker para tu aplicación ML.
Despliega y gestiona tu aplicación en contenedores utilizando Kubernetes.
Escala y supervisa tu aplicación ML en un entorno de producción.
Antes de sumergirte en él, debes tener conocimientos básicos de Python, de los flujos de trabajo del aprendizaje automático y de cómo trabajar con la línea de comandos. Familiaridad con conceptos de Docker (por ejemplo, imágenes, contenedores, comandos básicos), y conocimientos básicos de Kubernetes es opcional pero útil para el despliegue y el escalado.
¿Qué es una aplicación en contenedores?
Una aplicación en contenedor es una aplicación de software empaquetada con todas sus dependencias, bibliotecas y configuraciones en una única unidad ligera llamada contenedor. Para las aplicaciones de aprendizaje automático, esto significa empaquetar todo, desde tu modelo entrenado hasta las bibliotecas de Python de las que depende, asegurando que tu aplicación se ejecuta de la misma manera en todas partes.
Aplicación tradicional frente a aplicación en contenedor
Por qué la contenedorización es importante para las aplicaciones de aprendizaje automático
Cuando desarrollas aplicaciones de aprendizaje automático, probablemente te hayas encontrado con el problema de "funciona en mi máquina". Puede que tu modelo funcione perfectamente en tu portátil pero falle al desplegarlo en la nube, o que un colega no pueda reproducir tus resultados porque tienen instaladas versiones diferentes de scikit-learn o TensorFlow.
La contenedorización resuelve estos problemas creando un entorno coherente y aislado para tu aplicación. Esto es lo que hace que las aplicaciones en contenedores sean mejores para el aprendizaje automático:
Coherencia: Tu aplicación se comporta de la misma manera en distintos entornos, desde el desarrollo hasta las pruebas y la producción.
Aislamiento: Cada contenedor se ejecuta en su propio entorno, evitando conflictos entre distintas aplicaciones o dependencias.
Portabilidad: Los contenedores pueden ejecutarse en cualquier plataforma que admita la contenedorización, ya sea tu máquina local, un servicio en la nube o un servidor local.
Escalabilidad: ¿Necesitas gestionar más solicitudes? Los contenedores facilitan el escalado horizontal de tu aplicación mediante la ejecución de múltiples instancias.
Contenedores frente a máquinas virtuales
Aunque tanto los contenedores como las máquinas virtuales (VM) se utilizan para aislar aplicaciones, difieren significativamente en su funcionamiento y en sus casos de uso. Aquí tienes un desglose de las principales diferencias y ventajas:
Aspecto
Contenedores
Máquinas virtuales (VM)
Arquitectura
Comparte el núcleo del SO anfitrión; ligero y aislado.
Incluyen un SO completo; se ejecutan en un hipervisor.
Rendimiento
Ligero, de inicio rápido y baja sobrecarga de recursos.
Arranque más pesado y lento, y mayor uso de recursos debido a la sobrecarga total del SO.
Portabilidad
Altamente portátil; funciona de forma consistente en todos los entornos.
Menos portátil debido a las dependencias del sistema operativo; puede tener problemas de compatibilidad.
Escalabilidad
Fácilmente escalable mediante herramientas de orquestación como Kubernetes.
Escalable, pero requiere más recursos y esfuerzo de gestión.
Seguridad
Depende de la seguridad del SO anfitrión; menos aislamiento que las máquinas virtuales.
Fuerte aislamiento gracias a las instancias separadas del SO; más seguro para las aplicaciones sensibles.
Para las aplicaciones de aprendizaje automático, estas diferencias son importantes. Cuando necesites escalar tu modelo para manejar más predicciones, o cuando quieras desplegar varias versiones de tu modelo para pruebas A/B, los contenedores te proporcionan la agilidad y la eficiencia de recursos que necesitas.
Cómo contenerizar una aplicación de aprendizaje automático
En las secciones siguientes, hemos esbozado una guía paso a paso sobre cómo contenerizar una aplicación:
1. Configurar tu entorno
Antes de empezar a contenerizar nuestra aplicación de aprendizaje automático, tenemos que configurar las herramientas necesarias y preparar nuestro entorno. Esta sección te guiará a través de la instalación de Docker y la preparación de una sencilla aplicación de aprendizaje automático para la contenedorización.
Herramientas que necesitarás
Para contenerizar una aplicación de aprendizaje automático, necesitarás las siguientes herramientas:
Docker: Una plataforma para construir, enviar y gestionar contenedores.
Kubernetes (opcional): Una herramienta de orquestación para gestionar contenedores a escala. (Esto lo veremos más adelante en el tutorial).
Empecemos por instalar Docker.
Paso 1: Instalar Docker
Docker está disponible para Windows, macOS y Linux. A continuación se indican los pasos para instalar Docker en tu sistema.
Sigue las instrucciones de instalación proporcionadas por el instalador.
Para Linux (Ubuntu/Debian):
Abre tu terminal y ejecuta los siguientes comandos para instalar Docker:
# Update your package listsudoapt-get update
# Install required packages to allow apt to use a repository over HTTPSsudoapt-getinstall-y apt-transport-https ca-certificates curl software-properties-common
# Add Docker’s official GPG keycurl-fsSL https://download.docker.com/linux/ubuntu/gpg |sudo gpg --dearmor-o /usr/share/keyrings/docker-archive-keyring.gpg
# Add the Docker repository to your systemecho"deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"|sudotee /etc/apt/sources.list.d/docker.list > /dev/null
# Update your package list againsudoapt-get update
# Install Dockersudoapt-getinstall-y docker-ce docker-ce-cli containerd.io
# Verify Docker installationsudodocker--versionCon la tecnología de
Este proceso de instalación añade el repositorio Docker a tu sistema, verifica su autenticidad con la clave GPG e instala el motor Docker junto con sus herramientas de línea de comandos.
Paso 2: Verifica la instalación de Docker
Una vez instalado Docker, comprueba que funciona correctamente ejecutando el siguiente comando en el símbolo del sistema:
# Check Docker versiondocker--version# Run hello-world containerdocker run hello-worldCon la tecnología de
Esto extrae una imagen de prueba ligera y la ejecuta como contenedor. Si tiene éxito, verás un mensaje de bienvenida confirmando que la instalación funciona correctamente, como se muestra a continuación:
2. Preparar tu aplicación de aprendizaje automático
Ahora que Docker está instalado, vamos a preparar una sencilla aplicación de aprendizaje automático para la contenerización. Para este tutorial, utilizaremos un script básico de Python que carga un modelo preentrenado y sirve predicciones a través de una API de Flask.
Paso 1: Crear una aplicación ML sencilla
Crea un nuevo directorio para tu proyecto y añade los siguientes archivos:
app.py: Un script en Python para servir predicciones a través de una API de Flask.
requisitos.txt: Un archivo con las dependencias de Python.
Aquí tienes el código de app.py:
# Import required librariesfrom sklearn.datasets import load_iris
from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import train_test_split
from flask import Flask, request, jsonify
import numpy as np
# Initialize Flask app
app = Flask(__name__)# Load and prepare the model
iris = load_iris()
X, y = iris.data, iris.target
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
model = RandomForestClassifier(random_state=42)
model.fit(X_train, y_train)@app.route('/predict', methods=['POST'])defpredict():# Get features from request
features = request.json['features']# Make prediction
prediction = model.predict([features])return jsonify({'prediction':int(prediction[0]),'class_name': iris.target_names[prediction[0]]})if __name__ =='__main__':
app.run(host='0.0.0.0', port=5000)Con la tecnología de
El código carga el conjunto de datos Iris, entrena un clasificador Random Foresty configura un punto final de la API de Flask que acepta valores de características y devuelve predicciones. Estamos construyendo esto como un servicio web para que sea adecuado para la contenedorización.
Paso 2: Crea requirements.txt
El archivorequirements.txt enumera las bibliotecas Python necesarias para ejecutar el script. Crea este archivo en el mismo directorio que app.py:
# requirements.txt
scikit-learn==1.3.0
numpy==1.24.3
flask==2.0.1Con la tecnología de
Especifica las versiones exactas de los paquetes de Python que necesita nuestra aplicación. Tener versiones fijas garantiza que nuestra aplicación en contenedores será coherente y reproducible.
Ahora que nuestro entorno está configurado y nuestra aplicación ML está lista, podemos pasar a construir nuestro primer contenedor Docker. En la siguiente sección, escribiremos un Dockerfile y construiremos una imagen Docker para nuestra aplicación ML basada en Flask.
3. Construir tu primer contenedor Docker
Ahora que nuestra aplicación de aprendizaje automático está lista, el siguiente paso es contenerizarla utilizando Docker. Esto implica crear un Dockerfile, que es un script que contiene instrucciones para construir una imagen Docker. Una vez construida la imagen, podemos ejecutarla como contenedor.
Ejemplo de Dockerfile: Escribir un archivo Dockerfile
Un Dockerfile es un documento de texto que contiene todos los comandos para montar una imagen. He aquí cómo crear uno para nuestra aplicación ML basada en Flask.
En el mismo directorio que app.py y requirements.txtcrea un nuevo archivo llamado Dockerfile (sin extensión de archivo).
Añade el siguiente contenido al campo Dockerfile:
# Use an official Python runtime as the base image
FROM python:3.9-slim
# Set the working directory in the container
WORKDIR /app
# Copy the requirements file into the container
COPY requirements.txt .# Install the Python dependencies
RUN pip install --no-cache-dir -r requirements.txt
# Copy the rest of the application code into the container
COPY ..# Expose port 5000 for the Flask app
EXPOSE 5000# Define the command to run the Flask app
CMD ["python", "app.py"]Con la tecnología de
Explicación:
FROM python:3.9-slim: Estamos utilizando la imagen slim oficial de Python 3.9 como imagen base. La versión delgada es ligera e ideal para aplicaciones en contenedores.
WORKDIR /app: Esto establece el directorio de trabajo dentro del contenedor en /app. Todos los comandos posteriores se ejecutarán desde este directorio.
COPY requirements.txt .: Copia el archivorequirements.txt de tu máquina local al contenedor.
RUN pip install --no-cache-dir -r requirements.txt: Instala las dependencias de Python enumeradas en requirements.txt. La bandera--no-cache-dir reduce el tamaño de la imagen al no almacenar la caché.
COPY . .: Copia todos los archivos del directorio actual de tu máquina local al directorio /app del contenedor.
EXPOSE 5000: Expone el puerto 5000, que es el puerto en el que escucha nuestra aplicación Flask.
CMD ["python", "app.py"]: Define el comando para ejecutar la aplicación Flask cuando se inicie el contenedor.
Construir y probar la imagen Docker
Con el Dockerfile en su lugar, ahora podemos construir la imagen Docker y ejecutarla como un contenedor.
Paso 1: Construye la imagen Docker
Ejecuta el siguiente comando en el terminal para construir la imagen Docker:
Este comando crea una imagen Docker a partir del archivo Dockerfile del directorio actual. La bandera -t ml-flask-app etiqueta la imagen con el nombre ml-flask-app, facilitando su posterior consulta.
Paso 2: Ejecuta el contenedor Docker
Una vez construida la imagen, ejecútala como contenedor utilizando el siguiente comando:
Este comando inicia un contenedor desde la imagenml-flask-app. La bandera -p 5000:5000 asigna el puerto 5000 de tu máquina local al puerto 5000 del contenedor, lo que te permite acceder a la aplicación Flask desde tu navegador o desde una herramienta como curl.
Paso 3: Prueba la aplicación en contenedor
Abre una nueva ventana de terminal y envía una petición de prueba a la aplicación Flask que se ejecuta dentro del contenedor:
curl-X POST -H"Content-Type: application/json"-d'{"input": [5.1, 3.5, 1.4, 0.2]}' http://localhost:5000/predictCon la tecnología de
Verifica la sintaxis del Dockerfile:Comprueba dos veces que el Dockerfile no contenga errores tipográficos o de sintaxis.
Comprueba los conflictos de puertos:Asegúrate de que el puerto 5000 no está ya en uso en tu máquina local. Si es así, puedes asignar el contenedor a un puerto diferente, así
Ahora que hemos construido y probado con éxito nuestro contenedor Docker, el siguiente paso es aprender a gestionar y escalar la aplicación en contenedor. En la siguiente sección, exploraremos cómo utilizar Kubernetes para desplegar y escalar nuestra aplicación ML.
Ahora que hemos construido nuestro contenedor Docker, veamos cómo gestionarlo eficazmente. Esta sección te guiará a través de los comandos esenciales de Docker para iniciar, detener e inspeccionar contenedores, así como para trabajar con registros y puertos.
Utilizar Docker para gestionar contenedores
Docker proporciona un conjunto de potentes comandos para gestionar contenedores. Repasemos los más utilizados.
Iniciar un contenedor
Para iniciar un contenedor desde una imagen, utiliza el comandodocker run. Por ejemplo:
Enumera todos los contenedores en ejecución junto con sus ID, nombres y otros detalles. Una vez que tengas el ID del contenedor, detén el contenedor con:
Muestra la salida de tu aplicación, incluidos los errores o mensajes impresos en la consola. Si quieres seguir los registros en tiempo real (como tail -f ), añade la bandera-f:
Esto asigna el puerto 5000 del contenedor al puerto 5000 de tu máquina local. Si el puerto 5000 ya está en uso, puedes asignarlo a un puerto diferente, así:
Enumera las asignaciones de puertos del contenedor, lo que resulta útil para depurar problemas de conectividad. En la siguiente sección, veremos cómo desplegar nuestra aplicación ML en contenedores en Kubernetes y gestionarla a escala.
Escalar con Kubernetes
Una vez que nuestra aplicación está en contenedores, podemos desplegarla utilizando Kubernetes. Kubernetes automatiza el despliegue, escalado y gestión de aplicaciones en contenedores, facilitando el manejo de cargas de trabajo a gran escala. En esta sección, veremos cómo desplegar nuestra aplicación ML en un clúster Kubernetes.
Desplegar contenedores en Kubernetes
Kubernetes utiliza archivos YAML para definir el estado deseado de tu aplicación. Estos archivos describen cómo deben desplegarse, escalarse y gestionarse tus contenedores. Empecemos creando un despliegue Kubernetes para nuestra aplicación ML basada en Flask.
Paso 1: Escribe un archivo YAML de despliegue de Kubernetes
Crea un archivo llamado ml-flask-app-deployment.yaml con el siguiente contenido:
apiVersion: apps/v1
kind: Deployment
metadata:name: ml-flask-app
spec:replicas:3selector:matchLabels:app: ml-flask-app
template:metadata:labels:app: ml-flask-app
spec:containers:-name: ml-flask-app
image: ml-flask-app
ports:-containerPort:5000Con la tecnología de
Este archivo YAML define:
Un despliegue llamado ml-flask-app.
Tres réplicas de la aplicación, garantizando una alta disponibilidad.
Un contenedor utilizando la ml-flask-app que hemos creado antes.
Un containerPort de 5000, que es el puerto en el que escucha nuestra aplicación Flask.
Paso 2: Despliega la aplicación
Para desplegar la aplicación en Kubernetes, utiliza el comando kubectl apply comando
Muestra el estado de tu despliegue, incluido el número de réplicas en ejecución.
Paso 3: Exponer la aplicación
Para que la aplicación sea accesible fuera del clúster Kubernetes, crea un Servicio. Crea un archivo llamado ml-flask-app-service.yaml con el siguiente contenido:
apiVersion: v1
kind: Service
metadata:name: ml-flask-app-service
spec:type: LoadBalancer
ports:-port:80targetPort:5000selector:app: ml-flask-appCon la tecnología de
Este archivo YAML define:
Un Servicio llamado ml-flask-app-service.
Un tipo de LoadBalancer, que expone la aplicación a Internet.
Un mapeo del puerto 80 (externo) al puerto 5000 (interno).
Kubernetes también admite el Autoescalado Horizontal de Pods (HPA), que escala automáticamente el número de pods en función del uso de CPU o memoria. Para activar el autoescalado, ejecuta
kubectl autoscale deployment ml-flask-app --cpu-percent=50--min=3--max=10Con la tecnología de
Esto garantiza que el despliegue escale entre 3 y 10 réplicas en función del uso de la CPU.
Buenas prácticas para el despliegue de Kubernetes
Estas son algunas de las mejores prácticas que debes seguir cuando despliegues aplicaciones en Kubernetes.
Utiliza los límites de recursos
Define límites de CPU y memoria para tus contenedores, para evitar el agotamiento de recursos:
Añade comprobaciones de salud para asegurarte de que tu aplicación funciona correctamente:
livenessProbe:httpGet:path: /health
port:5000initialDelaySeconds:5periodSeconds:10readinessProbe:httpGet:path: /ready
port:5000initialDelaySeconds:5periodSeconds:10Con la tecnología de
Utilizar espacios de nombres
Organiza tus recursos utilizando espacios de nombres para evitar conflictos:
kubectl create namespace ml-app
kubectl apply -f ml-flask-app-deployment.yaml -n ml-appCon la tecnología de
En la siguiente sección, veremos consejos para optimizar los archivos Docker, gestionar las dependencias y garantizar la seguridad.
Buenas prácticas para contenerizar aplicaciones ML
La contenedorización de aplicaciones de aprendizaje automático conlleva su propio conjunto de retos, como gestionar grandes dependencias, garantizar la reproducibilidad y mantener la seguridad. Aquí tienes algunas buenas prácticas que te ayudarán a superar estos retos y a crear sólidas aplicaciones ML en contenedores.
Optimizar archivos Docker
Un Dockerfile bien optimizado puede reducir significativamente los tiempos de compilación y el tamaño de las imágenes. Aquí tienes algunos consejos para optimizar tus archivos Docker:
Utiliza construcciones multietapa
Las construcciones multietapa nos permiten utilizar varias sentencias FROM en un único archivo Dockerfile. Esto ayuda a reducir el tamaño final de la imagen al descartar archivos innecesarios y dependencias de etapas intermedias. Por ejemplo:
# Stage 1: Build the application
FROM python:3.9-slim as builder
WORKDIR /app
COPY requirements.txt .
RUN pip install--user-r requirements.txt
COPY ..# Stage 2: Create the final image
FROM python:3.9-slim
WORKDIR /app
COPY --from=builder /root/.local /root/.local
COPY --from=builder /app .
ENV PATH=/root/.local/bin:$PATH
EXPOSE 5000
CMD ["python", "app.py"]Con la tecnología de
Este Dockerfile:
Utiliza una builder para instalar las dependencias y crear la aplicación.
Copia sólo los archivos necesarios (por ejemplo, las dependencias instaladas y el código de la aplicación) en la imagen final, reduciendo su tamaño.
Minimizar capas
Cada instrucción de un archivo Docker crea una nueva capa. Para minimizar el número de capas y reducir el tamaño de la imagen:
Combina varias RUN comandos en uno solo utilizando &&.
Utiliza COPY en lugar de ADD a menos que necesites la funcionalidad adicional de ADD.
Por ejemplo:
RUN apt-get update &&\apt-getinstall-y --no-install-recommends build-essential &&\rm-rf /var/lib/apt/lists/*Con la tecnología de
Utiliza imágenes base ligeras
Elige imágenes base ligeras como python:3.9-slim en lugar de otras más grandes como python:3.9. Las imágenes delgadas sólo contienen los paquetes esenciales, reduciendo el tamaño total de la imagen.
Gestión de dependencias y reproducibilidad
La reproducibilidad es fundamental en los flujos de trabajo del aprendizaje automático. He aquí cómo gestionar las dependencias y garantizar la reproducibilidad en tus aplicaciones en contenedores.
Utiliza requirements.txt o pipen
Lista todas tus dependencias de Python en un archivo requirements.txt o utiliza pipenv para gestionarlas. Por ejemplo:
# requirements.txt
scikit-learn==1.3.0
numpy==1.24.3
Flask==2.3.2Con la tecnología de
Instala las dependencias en tu Dockerfile:
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txtCon la tecnología de
Versiones de dependencia de las clavijas
Fija siempre las versiones de tus dependencias para evitar cambios inesperados. Por ejemplo:
Utilizar variables de entorno para la configuración
Utiliza variables de entorno para configurar la aplicación en lugar de codificar valores. Esto hace que tu contenedor sea más flexible y fácil de configurar en distintos entornos. Por ejemplo:
La seguridad es un aspecto crítico de las aplicaciones en contenedores. He aquí algunas buenas prácticas para asegurar tus aplicaciones de ML:
Evita ejecutar como root
Ejecutar contenedores como usuario deroot puede exponer tu sistema a riesgos de seguridad. En su lugar, crea un usuario que no sea root y ejecuta el contenedor como ese usuario. Por ejemplo:
# Create a non-root user
RUN useradd-m myuser
# Switch to the non-root userUSER myuser
# Set the working directory
WORKDIR /home/myuser/app
# Copy the application code
COPY --chown=myuser:myuser ..# Run the application
CMD ["python", "app.py"]Con la tecnología de
Escanea imágenes en busca de vulnerabilidades
Utiliza herramientas como Trivy o Clair para escanear tus imágenes Docker en busca de vulnerabilidades. Por ejemplo, para escanear una imagen con Trivy:
Nunca codifiques información sensible, como claves API o credenciales de bases de datos, en tu archivo Docker o en el código de la aplicación. En su lugar, utiliza Kubernetes Secrets o Docker Secrets para gestionar los datos sensibles. Por ejemplo, en Kubernetes:
apiVersion: v1
kind: Secret
metadata:name: my-secret
type: Opaque
data:api_key: <base64-encoded-api-key>Con la tecnología de
Luego, monta el secreto como una variable de entorno en tu despliegue:
env:-name: API_KEY
valueFrom:secretKeyRef:name: my-secret
key: api_keyCon la tecnología de
Pruebas y depuración
Las pruebas y la depuración son esenciales para garantizar que tu aplicación en contenedores funciona como esperas. Aquí tienes algunos consejos:
Prueba local
Antes de desplegarlo en Kubernetes, prueba tu contenedor localmente utilizando Docker. Por ejemplo:
Utiliza canalizaciones CI/CD para automatizar las pruebas y el despliegue de tus aplicaciones en contenedores. Herramientas como GitHub Actions, GitLab CI o Jenkins pueden ayudarnos a establecer flujos de trabajo automatizados.
Siguiendo estas prácticas recomendadas, podemos crear aplicaciones de aprendizaje automático en contenedores eficientes, reproducibles y seguras. Desde optimizar los archivos Docker hasta gestionar las dependencias y garantizar la seguridad, estas estrategias nos ayudarán a agilizar nuestros flujos de trabajo de ML y a desplegar modelos con confianza.
Conclusión
La contenedorización de aplicaciones de aprendizaje automático con Docker y Kubernetes agiliza el despliegue, garantiza la reproducibilidad y mejora la escalabilidad. Siguiendo las mejores prácticas, como optimizar los archivos Docker, gestionar las dependencias y priorizar la seguridad, podemos construir flujos de trabajo de ML robustos, eficientes y seguros.
Para seguir aprendiendo sobre la contenedorización y mejorar tus flujos de trabajo de aprendizaje automático, consulta estos cursos:
Soy redactora de contenidos de ciencia de datos. Me encanta crear contenidos sobre temas de IA/ML/DS. También exploro nuevas herramientas de IA y escribo sobre ellas.
Descubre todo lo que necesitas saber sobre los tipos de modelos de machine learning, incluyendo para qué se utilizan y ejemplos de cómo ponerlos en práctica.
Aprende a instalar y configurar la base de datos MySQL dentro de contenedores Docker. El tutorial incluye conceptos como conectarse a servidores MySQL, ejecutar clientes MySQL para conectarse a contenedores, etc.
A medida que las aplicaciones de aprendizaje automático se vuelven más complejas, conseguir que nuestros modelos de aprendizaje automático pasen del desarrollo a la producción no consiste sólo en escribir un buen código. Se trata de garantizar que nuestra aplicación funcione de forma coherente en distintos entornos. Aquí es donde entra en juego la contenedorización. Pero, ¿qué es exactamente la contenedorización y por qué supone un cambio de juego para los flujos de trabajo del aprendizaje automático?
La contenerización es una forma ligera y portátil de empaquetar una aplicación junto con todas sus dependencias, bibliotecas y configuraciones en una única unidad llamada contenedor. A diferencia de las máquinas virtuales (VM) tradicionales, los contenedores comparten el sistema operativo del sistema anfitrión, lo que los hace más rápidos, eficientes y fáciles de escalar.
Para los científicos de datos y los ingenieros de ML, esto significa que puedes construir un modelo en tu máquina local y desplegarlo en cualquier lugar, ya sea en una plataforma en la nube, en un servidor o incluso en el portátil de un colega, sin preocuparte por problemas de compatibilidad.
En este tutorial, veremos cómo contenerizar una aplicación de aprendizaje automático utilizando Docker y Kubernetes. Al final, sabrás cómo hacerlo:
Si eres nuevo en Docker, consulta nuestra guía sobre Cómo aprender Docker desde cero. También puedes realizar nuestro curso Containerización y Virtualización con Docker y Kubernetes.
Requisitos previos
Antes de sumergirte en él, debes tener conocimientos básicos de Python, de los flujos de trabajo del aprendizaje automático y de cómo trabajar con la línea de comandos. Familiaridad con conceptos de Docker (por ejemplo, imágenes, contenedores, comandos básicos), y conocimientos básicos de Kubernetes es opcional pero útil para el despliegue y el escalado.
¿Qué es una aplicación en contenedores?
Una aplicación en contenedor es una aplicación de software empaquetada con todas sus dependencias, bibliotecas y configuraciones en una única unidad ligera llamada contenedor. Para las aplicaciones de aprendizaje automático, esto significa empaquetar todo, desde tu modelo entrenado hasta las bibliotecas de Python de las que depende, asegurando que tu aplicación se ejecuta de la misma manera en todas partes.
Aplicación tradicional frente a aplicación en contenedor
Por qué la contenedorización es importante para las aplicaciones de aprendizaje automático
Cuando desarrollas aplicaciones de aprendizaje automático, probablemente te hayas encontrado con el problema de "funciona en mi máquina". Puede que tu modelo funcione perfectamente en tu portátil pero falle al desplegarlo en la nube, o que un colega no pueda reproducir tus resultados porque tienen instaladas versiones diferentes de scikit-learn o TensorFlow.
La contenedorización resuelve estos problemas creando un entorno coherente y aislado para tu aplicación. Esto es lo que hace que las aplicaciones en contenedores sean mejores para el aprendizaje automático:
Contenedores frente a máquinas virtuales
Aunque tanto los contenedores como las máquinas virtuales (VM) se utilizan para aislar aplicaciones, difieren significativamente en su funcionamiento y en sus casos de uso. Aquí tienes un desglose de las principales diferencias y ventajas:
Aspecto
Contenedores
Máquinas virtuales (VM)
Arquitectura
Comparte el núcleo del SO anfitrión; ligero y aislado.
Incluyen un SO completo; se ejecutan en un hipervisor.
Rendimiento
Ligero, de inicio rápido y baja sobrecarga de recursos.
Arranque más pesado y lento, y mayor uso de recursos debido a la sobrecarga total del SO.
Portabilidad
Altamente portátil; funciona de forma consistente en todos los entornos.
Menos portátil debido a las dependencias del sistema operativo; puede tener problemas de compatibilidad.
Escalabilidad
Fácilmente escalable mediante herramientas de orquestación como Kubernetes.
Escalable, pero requiere más recursos y esfuerzo de gestión.
Seguridad
Depende de la seguridad del SO anfitrión; menos aislamiento que las máquinas virtuales.
Fuerte aislamiento gracias a las instancias separadas del SO; más seguro para las aplicaciones sensibles.
Para las aplicaciones de aprendizaje automático, estas diferencias son importantes. Cuando necesites escalar tu modelo para manejar más predicciones, o cuando quieras desplegar varias versiones de tu modelo para pruebas A/B, los contenedores te proporcionan la agilidad y la eficiencia de recursos que necesitas.
Para saber más sobre la contenedorización y la virtualización, consulta esta pista de aprendizaje: Containerización y virtualización con Docker y Kubernetes.
Cómo contenerizar una aplicación de aprendizaje automático
En las secciones siguientes, hemos esbozado una guía paso a paso sobre cómo contenerizar una aplicación:
1. Configurar tu entorno
Antes de empezar a contenerizar nuestra aplicación de aprendizaje automático, tenemos que configurar las herramientas necesarias y preparar nuestro entorno. Esta sección te guiará a través de la instalación de Docker y la preparación de una sencilla aplicación de aprendizaje automático para la contenedorización.
Herramientas que necesitarás
Para contenerizar una aplicación de aprendizaje automático, necesitarás las siguientes herramientas:
Empecemos por instalar Docker.
Paso 1: Instalar Docker
Docker está disponible para Windows, macOS y Linux. A continuación se indican los pasos para instalar Docker en tu sistema.
Para Windows/macOS:
Para Linux (Ubuntu/Debian):
Abre tu terminal y ejecuta los siguientes comandos para instalar Docker:
Este proceso de instalación añade el repositorio Docker a tu sistema, verifica su autenticidad con la clave GPG e instala el motor Docker junto con sus herramientas de línea de comandos.
Paso 2: Verifica la instalación de Docker
Una vez instalado Docker, comprueba que funciona correctamente ejecutando el siguiente comando en el símbolo del sistema:
Esto extrae una imagen de prueba ligera y la ejecuta como contenedor. Si tiene éxito, verás un mensaje de bienvenida confirmando que la instalación funciona correctamente, como se muestra a continuación:
2. Preparar tu aplicación de aprendizaje automático
Ahora que Docker está instalado, vamos a preparar una sencilla aplicación de aprendizaje automático para la contenerización. Para este tutorial, utilizaremos un script básico de Python que carga un modelo preentrenado y sirve predicciones a través de una API de Flask.
Paso 1: Crear una aplicación ML sencilla
Crea un nuevo directorio para tu proyecto y añade los siguientes archivos:
Aquí tienes el código de app.py:
El código carga el conjunto de datos Iris, entrena un clasificador Random Foresty configura un punto final de la API de Flask que acepta valores de características y devuelve predicciones. Estamos construyendo esto como un servicio web para que sea adecuado para la contenedorización.
Paso 2: Crea
requirements.txtEl archivo
requirements.txtenumera las bibliotecas Python necesarias para ejecutar el script. Crea este archivo en el mismo directorio que app.py:Especifica las versiones exactas de los paquetes de Python que necesita nuestra aplicación. Tener versiones fijas garantiza que nuestra aplicación en contenedores será coherente y reproducible.
Ahora que nuestro entorno está configurado y nuestra aplicación ML está lista, podemos pasar a construir nuestro primer contenedor Docker. En la siguiente sección, escribiremos un
Dockerfiley construiremos una imagen Docker para nuestra aplicación ML basada en Flask.3. Construir tu primer contenedor Docker
Ahora que nuestra aplicación de aprendizaje automático está lista, el siguiente paso es contenerizarla utilizando Docker. Esto implica crear un
Dockerfile, que es un script que contiene instrucciones para construir una imagen Docker. Una vez construida la imagen, podemos ejecutarla como contenedor.Ejemplo de Dockerfile: Escribir un archivo Dockerfile
Un
Dockerfilees un documento de texto que contiene todos los comandos para montar una imagen. He aquí cómo crear uno para nuestra aplicación ML basada en Flask.app.pyyrequirements.txtcrea un nuevo archivo llamadoDockerfile(sin extensión de archivo).Dockerfile:Explicación:
FROM python:3.9-slim: Estamos utilizando la imagen slim oficial de Python 3.9 como imagen base. La versión delgada es ligera e ideal para aplicaciones en contenedores.WORKDIR /app: Esto establece el directorio de trabajo dentro del contenedor en /app. Todos los comandos posteriores se ejecutarán desde este directorio.COPY requirements.txt .: Copia el archivo requirements.txt de tu máquina local al contenedor.RUN pip install --no-cache-dir -r requirements.txt: Instala las dependencias de Python enumeradas en requirements.txt. La bandera --no-cache-dir reduce el tamaño de la imagen al no almacenar la caché.COPY . .: Copia todos los archivos del directorio actual de tu máquina local al directorio /app del contenedor.EXPOSE 5000: Expone el puerto 5000, que es el puerto en el que escucha nuestra aplicación Flask.CMD ["python", "app.py"]: Define el comando para ejecutar la aplicación Flask cuando se inicie el contenedor.Construir y probar la imagen Docker
Con el Dockerfile en su lugar, ahora podemos construir la imagen Docker y ejecutarla como un contenedor.
Paso 1: Construye la imagen Docker
Ejecuta el siguiente comando en el terminal para construir la imagen Docker:
Este comando crea una imagen Docker a partir del archivo Dockerfile del directorio actual. La bandera
-t ml-flask-appetiqueta la imagen con el nombreml-flask-app, facilitando su posterior consulta.Paso 2: Ejecuta el contenedor Docker
Una vez construida la imagen, ejecútala como contenedor utilizando el siguiente comando:
Este comando inicia un contenedor desde la imagen
ml-flask-app. La bandera-p 5000:5000asigna el puerto 5000 de tu máquina local al puerto 5000 del contenedor, lo que te permite acceder a la aplicación Flask desde tu navegador o desde una herramienta comocurl.Paso 3: Prueba la aplicación en contenedor
Abre una nueva ventana de terminal y envía una petición de prueba a la aplicación Flask que se ejecuta dentro del contenedor:
Deberías ver una respuesta como ésta:
Esto significa que la aplicación Flask en contenedor se está ejecutando correctamente y está lista para servir predicciones.
Depuración de problemas comunes
Si te encuentras con problemas mientras construyes o ejecutas el contenedor, aquí tienes algunos consejos que te ayudarán a solucionarlos:
Comprueba los registros de Docker:Utiliza el siguiente comando para ver los registros de un contenedor en ejecución:
Verifica la sintaxis del Dockerfile:Comprueba dos veces que el Dockerfile no contenga errores tipográficos o de sintaxis.
Comprueba los conflictos de puertos:Asegúrate de que el puerto 5000 no está ya en uso en tu máquina local. Si es así, puedes asignar el contenedor a un puerto diferente, así
Reconstruye la imagen:
Si realizas cambios en el archivo Docker o en el código de la aplicación, reconstruye la imagen utilizando:
Ahora que hemos construido y probado con éxito nuestro contenedor Docker, el siguiente paso es aprender a gestionar y escalar la aplicación en contenedor. En la siguiente sección, exploraremos cómo utilizar Kubernetes para desplegar y escalar nuestra aplicación ML.
Echa un vistazo a más proyectos Docker en nuestra guía 10 Ideas de Proyectos Docker: De principiante a avanzado.
Ejecutar tu aplicación en contenedores
Ahora que hemos construido nuestro contenedor Docker, veamos cómo gestionarlo eficazmente. Esta sección te guiará a través de los comandos esenciales de Docker para iniciar, detener e inspeccionar contenedores, así como para trabajar con registros y puertos.
Utilizar Docker para gestionar contenedores
Docker proporciona un conjunto de potentes comandos para gestionar contenedores. Repasemos los más utilizados.
Iniciar un contenedor
Para iniciar un contenedor desde una imagen, utiliza el comando
docker run. Por ejemplo:Este comando inicia un contenedor desde la imagen
ml-flask-appy asigna el puerto 5000 de tu máquina local al puerto 5000 del contenedor.Si quieres ejecutar el contenedor en segundo plano (modo separado), añade la bandera
-dbandera:Esto permite que el contenedor se ejecute en segundo plano, liberando tu terminal.
Detener un contenedor
Para detener un contenedor en ejecución, busca primero su ID de contenedor utilizando:
Enumera todos los contenedores en ejecución junto con sus ID, nombres y otros detalles. Una vez que tengas el ID del contenedor, detén el contenedor con:
Por ejemplo:
Inspeccionar un contenedor
Para ver información detallada sobre un contenedor, utiliza el comando
docker inspectcomando:Esto proporciona una salida JSON con detalles como la configuración de red del contenedor, los volúmenes montados y las variables de entorno.
Listado de contenedores
Para ver todos los contenedores (tanto en ejecución como parados), utiliza
Esto es útil para comprobar el estado de tus contenedores y encontrar los ID de contenedor.
Trabajar con registros y puertos
Los logs y los puertos son fundamentales para depurar y acceder a nuestra aplicación en contenedores. Exploremos cómo trabajar con ellos.
Ver los registros del contenedor
Para ver los registros de un contenedor en ejecución, utiliza:
Por ejemplo:
Muestra la salida de tu aplicación, incluidos los errores o mensajes impresos en la consola. Si quieres seguir los registros en tiempo real (como
tail -f), añade la bandera-f:Asignación de puertos
Al ejecutar un contenedor, puedes asignar los puertos del contenedor a tu máquina local utilizando la bandera-p. Por ejemplo:
Esto asigna el puerto 5000 del contenedor al puerto 5000 de tu máquina local. Si el puerto 5000 ya está en uso, puedes asignarlo a un puerto diferente, así:
Ahora, tu aplicación Flask estará accesible en
http://localhost:5001.Comprobar los enlaces de los puertos
Para ver qué puertos están asignados a un contenedor en ejecución, utiliza
Enumera las asignaciones de puertos del contenedor, lo que resulta útil para depurar problemas de conectividad. En la siguiente sección, veremos cómo desplegar nuestra aplicación ML en contenedores en Kubernetes y gestionarla a escala.
Escalar con Kubernetes
Una vez que nuestra aplicación está en contenedores, podemos desplegarla utilizando Kubernetes. Kubernetes automatiza el despliegue, escalado y gestión de aplicaciones en contenedores, facilitando el manejo de cargas de trabajo a gran escala. En esta sección, veremos cómo desplegar nuestra aplicación ML en un clúster Kubernetes.
Desplegar contenedores en Kubernetes
Kubernetes utiliza archivos YAML para definir el estado deseado de tu aplicación. Estos archivos describen cómo deben desplegarse, escalarse y gestionarse tus contenedores. Empecemos creando un despliegue Kubernetes para nuestra aplicación ML basada en Flask.
Paso 1: Escribe un archivo YAML de despliegue de Kubernetes
Crea un archivo llamado
ml-flask-app-deployment.yamlcon el siguiente contenido:Este archivo YAML define:
ml-flask-app.ml-flask-appque hemos creado antes.Paso 2: Despliega la aplicación
Para desplegar la aplicación en Kubernetes, utiliza el comando
kubectl applycomandoEste comando indica a Kubernetes que cree los recursos definidos en el archivo YAML. Puedes comprobar el estado del despliegue utilizando:
Muestra el estado de tu despliegue, incluido el número de réplicas en ejecución.
Paso 3: Exponer la aplicación
Para que la aplicación sea accesible fuera del clúster Kubernetes, crea un Servicio. Crea un archivo llamado
ml-flask-app-service.yamlcon el siguiente contenido:Este archivo YAML define:
ml-flask-app-service.Aplica el Servicio utilizando:
Puedes comprobar el estado del Servicio utilizando:
Muestra la dirección IP externa desde la que se puede acceder a tu aplicación.
Escalado y seguimiento
Kubernetes facilita el escalado de tu aplicación y la supervisión de su rendimiento. Exploremos cómo hacerlo.
Escalar la aplicación
Para escalar tu aplicación, actualiza el número de réplicas en la implantación. Por ejemplo, para escalar a 5 réplicas, ejecuta
También puedes actualizar el campo
replicascampo en el archivo YAML y volver a aplicarlo:Entonces corre:
Supervisar la aplicación
Kubernetes proporciona varias herramientas para monitorizar nuestra aplicación. Veamos algunas herramientas para monitorizar nuestra aplicación.
Utiliza
kubectl logspara ver los registros de un pod concreto:Utiliza
kubectl get podspara comprobar el estado de tus pods:Utiliza
kubectl toppara ver el uso de CPU y memoria:Autoescalado
Kubernetes también admite el Autoescalado Horizontal de Pods (HPA), que escala automáticamente el número de pods en función del uso de CPU o memoria. Para activar el autoescalado, ejecuta
Esto garantiza que el despliegue escale entre 3 y 10 réplicas en función del uso de la CPU.
Buenas prácticas para el despliegue de Kubernetes
Estas son algunas de las mejores prácticas que debes seguir cuando despliegues aplicaciones en Kubernetes.
Utiliza los límites de recursos
Define límites de CPU y memoria para tus contenedores, para evitar el agotamiento de recursos:
Utiliza sondas de liveness y readiness
Añade comprobaciones de salud para asegurarte de que tu aplicación funciona correctamente:
Utilizar espacios de nombres
Organiza tus recursos utilizando espacios de nombres para evitar conflictos:
En la siguiente sección, veremos consejos para optimizar los archivos Docker, gestionar las dependencias y garantizar la seguridad.
Buenas prácticas para contenerizar aplicaciones ML
La contenedorización de aplicaciones de aprendizaje automático conlleva su propio conjunto de retos, como gestionar grandes dependencias, garantizar la reproducibilidad y mantener la seguridad. Aquí tienes algunas buenas prácticas que te ayudarán a superar estos retos y a crear sólidas aplicaciones ML en contenedores.
Optimizar archivos Docker
Un Dockerfile bien optimizado puede reducir significativamente los tiempos de compilación y el tamaño de las imágenes. Aquí tienes algunos consejos para optimizar tus archivos Docker:
Utiliza construcciones multietapa
Las construcciones multietapa nos permiten utilizar varias sentencias
FROMen un único archivo Dockerfile. Esto ayuda a reducir el tamaño final de la imagen al descartar archivos innecesarios y dependencias de etapas intermedias. Por ejemplo:Este Dockerfile:
builderpara instalar las dependencias y crear la aplicación.Minimizar capas
Cada instrucción de un archivo Docker crea una nueva capa. Para minimizar el número de capas y reducir el tamaño de la imagen:
RUNcomandos en uno solo utilizando&&.COPYen lugar deADDa menos que necesites la funcionalidad adicional deADD.Por ejemplo:
Utiliza imágenes base ligeras
Elige imágenes base ligeras como
python:3.9-slimen lugar de otras más grandes comopython:3.9. Las imágenes delgadas sólo contienen los paquetes esenciales, reduciendo el tamaño total de la imagen.Gestión de dependencias y reproducibilidad
La reproducibilidad es fundamental en los flujos de trabajo del aprendizaje automático. He aquí cómo gestionar las dependencias y garantizar la reproducibilidad en tus aplicaciones en contenedores.
Utiliza requirements.txt o pipen
Lista todas tus dependencias de Python en un archivo
requirements.txto utilizapipenvpara gestionarlas. Por ejemplo:Instala las dependencias en tu Dockerfile:
Versiones de dependencia de las clavijas
Fija siempre las versiones de tus dependencias para evitar cambios inesperados. Por ejemplo:
Utilizar variables de entorno para la configuración
Utiliza variables de entorno para configurar la aplicación en lugar de codificar valores. Esto hace que tu contenedor sea más flexible y fácil de configurar en distintos entornos. Por ejemplo:
A continuación, accede a la variable de entorno en tu aplicación:
Consideraciones de seguridad
La seguridad es un aspecto crítico de las aplicaciones en contenedores. He aquí algunas buenas prácticas para asegurar tus aplicaciones de ML:
Evita ejecutar como root
Ejecutar contenedores como usuario de
rootpuede exponer tu sistema a riesgos de seguridad. En su lugar, crea un usuario que no sea root y ejecuta el contenedor como ese usuario. Por ejemplo:Escanea imágenes en busca de vulnerabilidades
Utiliza herramientas como Trivy o Clair para escanear tus imágenes Docker en busca de vulnerabilidades. Por ejemplo, para escanear una imagen con Trivy:
Gestiona los secretos de forma segura
Nunca codifiques información sensible, como claves API o credenciales de bases de datos, en tu archivo Docker o en el código de la aplicación. En su lugar, utiliza Kubernetes Secrets o Docker Secrets para gestionar los datos sensibles. Por ejemplo, en Kubernetes:
Luego, monta el secreto como una variable de entorno en tu despliegue:
Pruebas y depuración
Las pruebas y la depuración son esenciales para garantizar que tu aplicación en contenedores funciona como esperas. Aquí tienes algunos consejos:
Prueba local
Antes de desplegarlo en Kubernetes, prueba tu contenedor localmente utilizando Docker. Por ejemplo:
Utiliza los registros para depurar
Utiliza
docker logsokubectl logspara depurar problemas en tu aplicación en contenedor. Por ejemplo:Automatizar las pruebas
Utiliza canalizaciones CI/CD para automatizar las pruebas y el despliegue de tus aplicaciones en contenedores. Herramientas como GitHub Actions, GitLab CI o Jenkins pueden ayudarnos a establecer flujos de trabajo automatizados.
Siguiendo estas prácticas recomendadas, podemos crear aplicaciones de aprendizaje automático en contenedores eficientes, reproducibles y seguras. Desde optimizar los archivos Docker hasta gestionar las dependencias y garantizar la seguridad, estas estrategias nos ayudarán a agilizar nuestros flujos de trabajo de ML y a desplegar modelos con confianza.
Conclusión
La contenedorización de aplicaciones de aprendizaje automático con Docker y Kubernetes agiliza el despliegue, garantiza la reproducibilidad y mejora la escalabilidad. Siguiendo las mejores prácticas, como optimizar los archivos Docker, gestionar las dependencias y priorizar la seguridad, podemos construir flujos de trabajo de ML robustos, eficientes y seguros.
Para seguir aprendiendo sobre la contenedorización y mejorar tus flujos de trabajo de aprendizaje automático, consulta estos cursos: