Dockerizar una app Flask para producción

Construyendo aplicaciones analíticas portables con DashForge

Las aplicaciones desarrolladas con Flask son extremadamente flexibles para crear dashboards, plataformas analíticas y sistemas de machine learning interactivos. Sin embargo, cuando el proyecto crece y empieza a desplegarse en servidores reales, surge un problema importante: el entorno.

Distintas versiones de Python, conflictos entre librerías, dependencias del sistema operativo o diferencias entre equipos pueden hacer que una aplicación funcione correctamente en desarrollo pero falle en producción.

Docker resuelve este problema encapsulando toda la aplicación dentro de un contenedor reproducible. El resultado es un entorno completamente aislado que puede ejecutarse exactamente igual en cualquier servidor compatible con Docker.

En este tutorial vamos a dockerizar una aplicación Flask desarrollada con DashForge utilizando una arquitectura preparada para producción.

Docker permite empaquetar una aplicación junto con todas sus dependencias. Todo queda integrado en una única imagen portable. Esto aporta ventajas muy importantes para aplicaciones analíticas:

  • despliegues reproducibles
  • aislamiento entre proyectos
  • facilidad para escalar aplicaciones
  • despliegues automáticos
  • ejecución bajo demanda
  • compatibilidad entre servidores
  • simplificación del entorno de producción

En el caso de DashForge, Docker permite convertir cada dashboard o aplicación analítica en una unidad independiente que puede iniciarse o detenerse dinámicamente desde un portal central.

Instalar docker

Linux

Para instalar en sistemas Debian sigue las siguientes instrucciones :

# Descarga la lista actualizada de los paquetes disponibles en los servidores de Linux
sudo apt update

# Intalar las dependencias
sudo apt install -y ca-certificates curl gnupg

# Añadir clave oficial de Docker
sudo install -m 0755 -d /etc/apt/keyrings

# Descargar y registrar de forma segura la clave pública oficial de Docker en tu sistema
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | \
sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg

# Dar permisos de lectura a todos los usuarios sobre la clave de seguridad de Docker
sudo chmod a+r /etc/apt/keyrings/docker.gpg

Añadir el repositorio Docker

echo \
  "deb [arch=$(dpkg --print-architecture) \
  signed-by=/etc/apt/keyrings/docker.gpg] \
  https://download.docker.com/linux/ubuntu \
  $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \
  sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

Actualizar los índices e instalar Docker

sudo apt update

sudo apt install -y \
    docker-ce \
    docker-ce-cli \
    containerd.io \
    docker-buildx-plugin \
    docker-compose-plugin

Permitir utilizar Docker sin sudo

sudo usermod -aG docker $USER

# reinicia seccion ssh
exit

Verificar la instalación

docker --version

# Probar Docker
docker ps

# verificar servicio
sudo systemctl status docker

Windows

Lo primero, instalar Docker en tu sistema: https://www.docker.com/products/docker-desktop/

Una vez instalado, hay que reiniciar el sistema. Docker instala servicios, WSL, variables y el daemon. Sigue las instrucciones de la aplicación; quizás sea necesario actualizar WSL, Docker Desktop normalmente guía todo automáticamente.

Verifica la instalación de Docker y su daemon, PowerShell ejecuta:

# Verifica la instalacion de docker
docker --version

# Verifica que el daemon este funcionando
docker ps

Preparar el proyecto Flask para Docker

Antes de dockerizar la aplicación, es recomendable mantener una estructura organizada. Una aplicación Flask típica preparada para Docker podría tener esta estructura:

DashForge/

├── app/
├── static/
├── templates/
├── requirements.txt
├── run.py
├── Dockerfile
├── .dockerignore
└── gunicorn.conf.py

Preparando las dependencias del proyecto

Docker necesita conocer todas las librerías utilizadas por la aplicación para poder instalarlas dentro del contenedor. La forma estándar de hacerlo es mediante un archivo requirements.txt. Este archivo incluirá todas las librerías necesarias para ejecutar la aplicación.

Al usar este comando, ten en cuenta que exporta todo, incluyendo paquetes del sistema Windows que pueden impedir crear la imagen Docker al tratar de instalar paquetes de Windows en WLS (Subsistema de Linux para Windows). Una vez ejecutado el código revisa el fichero y elimina archivos como pywin32, pywinpty o
winshell.

pip freeze > requirements.txt

Excluyendo archivos innecesarios con .dockerignore

Cuando Docker construye una imagen, copia el contenido del proyecto al contenedor. Sin embargo, muchos archivos no deben incluirse:

  • entornos virtuales
  • cachés
  • configuraciones del editor
  • repositorios Git
  • logs

Para evitarlo se utiliza un archivo /.dockerignore.

__pycache__/
*.pyc

.venv/
venv/

.git/
.vscode/
.idea/

.env
*.log

.ipynb_checkpoints/

Instalar Gunicorn

Instalamos Gunicorn dentro del entorno virtual y lo agregamos a las dependencias:

pip install gunicorn
pip show gunicorn

Configurar Gunicorn creando el archivo: /gunicorn.conf.py. Esta configuración es suficiente para la mayoría de los dashboards analíticos pequeños y medianos.

bind = "0.0.0.0:5000"

workers = 2

threads = 2

timeout = 120

worker_class = "gthread"

Creando el Dockerfile

El archivo más importante del proceso es el /Dockerfile. Aquí se define cómo construir el contenedor.

FROM python:3.13-slim

ENV PYTHONDONTWRITEBYTECODE=1
ENV PYTHONUNBUFFERED=1

WORKDIR /app

COPY requirements.txt .

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

RUN apt-get update && apt-get install -y curl

COPY . .

EXPOSE 5000

HEALTHCHECK CMD curl --fail http://localhost:5000 || exit 1

CMD ["gunicorn", "-c", "gunicorn.conf.py", "run:app"]

Entendiendo cada sección del Dockerfile

  • FROM python:3.13-slim: La aplicación se construirá sobre una imagen ligera de Python. La versión slim reduce considerablemente el tamaño final del contenedor.
  • ENV PYTHONDONTWRITEBYTECODE=1: Evitan generar archivos .pyc, mejoran el comportamiento del contenedor en producción.
  • ENV PYTHONUNBUFFERED=1: fuerzan salida inmediata de logs.
  • WORKDIR /app: Define el directorio interno donde vivirá la aplicación.
  • RUN pip install : instala las librerías listadas en requirements.txt.
  • RUN apt-get ... : instalar curl para healthcheck.
  • COPY ... : Copia el resto del proyecto al contenedor.
  • EXPOSE 5000: Indica que Flask/Gunicorn utilizará el puerto 5000.
  • HEALTHCHECK CMD curl: añadir comprobaciones automáticas de salud de los contenedores.
  • CMD : inicia la aplicación utilizando Gunicorn.

Construyendo la imagen Docker

Una vez preparados todos los archivos, ya podemos construir la imagen. En Powershell y desde la raíz del proyecto ejecutamos:

docker build -t dashforge-spacex .

Docker empezará a:

  1. descargar la imagen base
  2. instalar dependencias
  3. copiar el proyecto
  4. construir la imagen final
  • docker build: Es el comando principal que le ordena a Docker empaquetar tu aplicación, sus dependencias (como Python, Pandas, Scikit-Learn) y el sistema operativo base en una sola imagen aislada.
  • -t dashforge-spacex (Tag): Asigna un nombre y una etiqueta personalizada a la imagen que estás creando. El nombre que elijas aquí (dashforge-spacex) es la referencia exacta que usarás después para arrancar el contenedor con el comando docker run.
  • . (Punto final): Indica el contexto de construcción, diciéndole a Docker que busque el archivo llamado Dockerfile en el directorio actual.

Ejecutar el contenedor

Cuando la imagen termina de construirse, podemos iniciar la aplicación:

docker run -d -p 5010:5000 --name dashforge-spacex dashforge-spacex
  • docker run -d : Esto crea un contenedor en segundo plano -d (Detached).
  • -p 5000:5000 (Publish / Ports): Conecta un puerto de tu computadora real (Anfitrión) con un puerto dentro del contenedor (Contenedor) siguiendo la estructura -p puerto_externo:puerto_interno.
  • Primer 5010 (Externo): El puerto de tu máquina real. Podrás abrir tu navegador web e ingresar a http://localhost:5000 para ver tu app.
  • Segundo 5000 (Interno): El puerto donde tu servidor (como Flask, Dash o FastAPI) está escuchando dentro del entorno cerrado del contenedor.
  • --name dashforge-spacex: Asigna un nombre personalizado e identificable a este contenedor específico.
  • dashforge-spacex (Al final): Es el nombre de la imagen de Docker de origen que vas a utilizar como plantilla para construir este contenedor. Debe coincidir exactamente con el nombre de la imagen que creaste previamente con el comando docker build.

Gestionando contenedores Docker

Docker incluye comandos para administrar los contenedores.

# Ver dontenedores activos
docker ps

# Detener un contendor
docker stop dashforge-spacex

# Eliminar un contenedor
docker rm dashforge-spacex

# Eliminar una imagen de docker
docker rmi dashforge-spacex

Preparando DashForge para despliegues dinámicos

Una de las ventajas más potentes de Docker es que cada dashboard puede ejecutarse como un contenedor independiente. Esto permite construir una arquitectura bajo demanda:

  • El portal principal permanece activo
  • Las aplicaciones solo se inician cuando un usuario las solicita
  • Los contenedores pueden apagarse automáticamente tras un periodo de inactividad

Cada proyecto puede ejecutarse aislado, con sus propias dependencias, sus modelos ML y su configuración independiente. Esta arquitectura escala muchísimo mejor que mantener decenas de aplicaciones Flask activas permanentemente.