Categoría: Tutoriales

  • 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.

  • Configurar un VPS para prácticas

    Tutorial paso a paso para dejar un servidor virtual listo para trabajar con Python, Docker, GitHub, Jupyter, FastAPI y herramientas de MLOps. Un VPS (Virtual Private Server) es un servidor virtual que alquilas en la nube y al que accedes como si fuera una máquina Linux real. Disponer de un VPS propio es una de las mejores formas de practicar:

    • Administración Linux
    • DevOps
    • Docker y Kubernetes
    • CI/CD
    • APIs con FastAPI
    • Aplicaciones de IA agéntica
    • MLOps
    • Despliegue de modelos de Machine Learning

    En esta guía vamos a configurar un VPS desde cero para convertirlo en un entorno profesional de laboratorio.

    Características Recomendadas para un VPS de prácticas

    Antes de contratar un VPS, conviene elegir una configuración equilibrada que permita trabajar con herramientas de desarrollo, contenedores y cargas moderadas de machine learning.

    Configuración mínima recomendada

    Para un laboratorio personal de DevOps, Data Science y MLOps, estas especificaciones son más que suficientes:

    RecursoRecomendación mínimaRecomendación ideal
    CPU2 vCPU4 vCPU
    Memoria RAM4 GB8 GB o más
    Almacenamiento40 GB SSD/NVMe80 GB NVMe
    Transferencia1 TB/mes2 TB/mes o más
    Sistema operativoUbuntu 24.04 LTSUbuntu 24.04 LTS
    Acceso root
    SnapshotsDeseableMuy recomendable
    Backup automáticoOpcionalRecomendable

    Configuración recomendada según el uso

    CaracteristicaLaboratorio básicoLaboratorio profesionalLaboratorio Avanzado
    CPU2 48
    RAM4 GB8 GB16 GB
    NVMe40 GB80 GB160 GBNVMe
    Adecuado para: Linux, SSH, Python, GitHub Actions, Docker BásicoDocker Compose, FastAPI, MLflow, PostgreSQL, DVC, Entrenamiento de modelos moderados.Múltiples contenedores, Airflow, Kubeflow ligero, procesamiento intensivo.

    Proveedores recomendados

    • Hetzner Cloud
    • Contabo
    • DigitalOcean
    • Vultr
    • OVHcloud
    • AWS EC2
    • Google Cloud
    • Microsoft Azure

    Características del VPS elegido

    Cloud VPS 20 de Contabo

    CaracterísticaEspecificación
    vCPU Cores6 núcleos (AMD EPYC)
    RAM12 GB
    Almacenamiento200 GB SSD (o 100 GB NVMe)
    Velocidad de Puerto300 Mbit/s
    TráficoIlimitado (inbound + outbound)
    Snapshots2 snapshots incluidos
    VirtualizaciónKVM
    Sistema OperativoUbuntu Server 24.04 LTS
    IP1 IPv4 dedicada
    DDoS ProtectionSiempre activada (gratis)
    Precio Base€7.00 / mes + IVA, €5.60/año + IVA

    Una vez completada la suscripción del servicio, nos llegan al correo las credenciales y dirección IP en aproximadamente 30 min. En la consola ya podemos realizar la primera conexión con ssh:

    ssh root@IP_DEL_SERVIDOR
    • ssh: El programa que establece la conexión segura y cifrada.
    • root: El nombre de usuario con el que quieres entrar. En este caso, es el superusuario (el que tiene control total sobre el servidor).
    • @203.0.113.10: La dirección IP del servidor remoto al que te quieres conectar.

    Primeras acciones después de activar tu VPS

    Actualizar el sistema

    sudo apt update && sudo apt upgrade -y
    • sudo: te da permisos de administrador para poder realizar cambios en el sistema.
    • apt update: descarga la información más reciente sobre qué programas tienen versiones nuevas disponibles. No instala nada, solo actualiza la lista.
    • &&: Es un conector lógico. Le dice a la terminal: “si el primer comando termina con éxito, ejecuta el siguiente inmediatamente”.
    • apt upgrade: Compara tus programas instalados con la lista nueva y descarga e instala las actualizaciones.
    • -y: Significa “Yes” (Sí). Responde automáticamente que sí a la pregunta de confirmación, así no tienes que presionar ninguna tecla para que la instalación continúe.

    Crear un usuario administrativo

    adduser usuario
    usermod -aG sudo usuario
    • adduser usuario: Crea una cuenta de usuario nueva llamada “usuario”.
      • Te pedirá que establezcas una contraseña.
      • Creará automáticamente su carpeta personal (/home/usuario) y configurará los archivos básicos del entorno.
    • usermod -aG sudo usuario: Le otorga permisos de administrador.
      • -aG sudo: Añade (-a de append) al usuario al grupo (-G) llamado sudo.
      • Esto permite que el nuevo usuario pueda ejecutar comandos con sudo (como el de actualización que vimos antes) usando su propia contraseña.
    • Después de ejecutar estos comandos, el nuevo usuario debe cerrar sesión y volver a entrar para que los permisos de administrador se activen.

    Configurar la autenticación basada en llaves (en lugar de usar contraseñas).

    En tu equipo local:

    ssh-keygen -t ed25519 -C "[email protected]"

    Este comando se usa para crear un nuevo par de llaves SSH, que es una forma mucho más segura (y cómoda) de entrar a tu servidor que usar una contraseña tradicional.

    • ssh-keygen: La herramienta para generar las llaves.
    • -t ed25519: Especifica el tipo de algoritmo. Ed25519 es el estándar moderno más recomendado porque es increíblemente seguro, rápido y genera llaves cortas.
    • -C "[email protected]": Añade una etiqueta o comentario (normalmente tu email) al final de la llave pública para que sepas a quién pertenece cuando la veas en el servidor.

    Cuando se ejecute el comando, te pregunta si guarda la clave en la ubicación por defecto: ~/.ssh/id_ed25519 (presiona Enter para aceptar). Luego te pedirá una “frase de paso” (opcional). Es una contraseña extra para proteger tu llave privada si alguien robara tu ordenador. Como resultado se crearán dos archivos en tu carpeta .ssh:

    • id_ed25519.pub (Llave Pública): Es como el candado. Esta es la que debes copiar al servidor para poder entrar sin contraseña.
    • id_ed25519 (Llave Privada): Es como tu llave física. Nunca la compartas ni la subas a ningún sitio.

    Instalación de la llave pública en el servidor (o SSH Key Deployment).

    Si usas Linux: 
    ssh-copy-id user@IP_DEL_SERVIDOR
    
    Si usas Windows:
    type $env:USERPROFILE\.ssh\id_ed25519.pub | ssh user@IP_DEL_SERVIDOR "mkdir -p ~/.ssh && cat >> ~/.ssh/authorized_keys"
    • Este código se conecta al servidor remoto usando tu contraseña por última vez.
    • Copia el contenido de tu llave pública (~/.ssh/id_ed25519.pub) al servidor.
    • Lo agrega automáticamente en un archivo especial llamado ~/.ssh/authorized_keys dentro de la carpeta del usuario remoto.
    • Configura los permisos correctos de las carpetas para que el servidor acepte la llave.

    A partir de este momento, cuando escribas ssh user@IP_DEL_SERVIDOR, el servidor reconocerá tu “candado” y te dejará entrar sin pedirte contraseña, o si configuras una palabra de paso (passphrase) te la pedirá al loguearte.

    Copiar tu llave privada a un pendrive

    Puedes copiar tu llave privada a un pendrive y luego usarla en otro ordenador desde la consola de Windows (PowerShell). Supongamos que tu pendrive es la unidad D: Ejecuta esto en PowerShell:

    # Crear una carpeta en el pendrive para la llave
    mkdir D:\mykeys
    
    # Copiar la llave privada
    copy $env:USERPROFILE\.ssh\id_ed25519 D:\mykeys\

    Cómo usarla desde otro ordenador

    Cuando estés en el otro ordenador y quieras conectarte a tu servidor usando la llave del pendrive puedes apuntar a ella directamente al conectarte:

    # Windows
    ssh -i D:\mykeys\id_ed25519 user@IP_DEL_SERVIDOR
    
    # Linux
    ssh -i /media/tu_usuario/NOMBRE_USB/mykeys/id_ed25519 user@IP_DEL_SERVIDOR
    

    Fortalecer SSH (SSH Hardening).

    El SSH Hardening es un conjunto de configuraciones de seguridad aplicadas al servicio de acceso remoto para evitar ataques. Por defecto, SSH es como una puerta con una cerradura estándar; el hardening es como poner una puerta blindada, cambiar la cerradura por un lector de huellas y ocultar la ubicación de la casa.

    El objetivo principal es pasar de una autenticación basada en “algo que sabes” (contraseñas, que pueden ser adivinadas o robadas) a “algo que tienes” (una llave criptográfica única).

    Los 3 Pilares del Fortalecimiento

    1. Eliminación de contraseñas: Se desactiva la posibilidad de loguearse con clave, obligando al uso de llaves SSH (Ed25519).
    2. Restricción de privilegios: Se prohíbe el acceso directo al usuario root. Debes entrar con un usuario normal y escalar privilegios solo cuando sea necesario.
    3. Reducción de exposición: Se configuran parámetros para que el servidor ignore intentos de conexión malintencionados.

    Riesgos y Cómo evitarlos:

    RiesgoExplicaciónCómo evitarlo
    Bloqueo Total (Lockout)Si tu ordenador se rompe o pierdes tu llave privada, no podrás entrar al servidor porque las contraseñas están desactivadas.Guarda una copia de tu llave privada en un gestor de contraseñas o en un USB cifrado.
    Robo de Llave PrivadaSi alguien copia tu archivo id_ed25519, puede entrar a tu servidor sin esfuerzo.Ponle una passphrase (contraseña) a tu llave al generarla. Así, aunque la roben, no podrán usarla sin la clave.
    Cambio de IP del ServidorSi el servidor cambia de IP y no tienes acceso físico, la llave SSH no servirá de nada si no sabes dónde conectar.Usa una IP estática o un nombre de dominio (DNS) vinculado a tu servidor.

    Visto lo anterior, si necesitas tener una buena seguridad en tu VPS, realiza las siguientes tareas:

    Ejecuta el siguiente comando en una terminal para editar el fichero sshd_config. (sustituye ? por i).

    sudo nano /etc/ssh/sshd_conf?g

    Si deseas eliminar la entrada por contraseñas, realiza los siguientes cambios:

    PermitRootLogin no
    PasswordAuthentication no
    PubkeyAuthentication yes
    • PermitRootLogin no: Prohíbe que alguien intente entrar directamente como root. Ahora es obligatorio entrar con tu usuario normal (user) y luego usar sudo. Esto frena miles de ataques automatizados que prueban contraseñas contra el usuario root.
    • PasswordAuthentication no: Esta es la medida más importante. Desactiva las contraseñas por completo para SSH. A partir de ahora, si alguien no tiene tu archivo de llave privada, no podrá entrar aunque adivine tu contraseña.
    • PubkeyAuthentication yes: Asegura que el sistema permita el acceso mediante el par de llaves (pública/privada) que configuraste antes.
    • sudo systemctl restart ssh: Aplica los cambios inmediatamente.

    ¡Aviso muy importante! No toques esa ventana de la terminal después de reiniciar el servidor ssh. Úsala como “salvavidas”. Si algo falla, desde ahí puedes volver a abrir el archivo de configuración y arreglarlo.

    Reinicia el servidor ssh.

    sudo systemctl restart ssh

    Abre una ventana de PowerShell (en Windows) o una terminal nueva (en Linux/Mac) totalmente independiente de la primera. Intenta conectar desde la nueva ventana:

    ssh user@IP_DEL_SERVIDOR<br>

    Analiza el resultado:

    • Si entras directamente (o te pide la contraseña de tu llave): ¡Éxito! El hardening funciona. Ahora sí puedes cerrar todas las sesiones.
    • Si te pide la contraseña del usuario “fernan” (la de texto): algo falló. El servidor sigue aceptando contraseñas. Revisa que pusiste PasswordAuthentication no.
    • Si te dice “Permission denied (publickey)”: ¡Cuidado! El servidor ha bloqueado las contraseñas, pero no reconoce tu llave.

    ¿Qué hacer si falla?: Como tienes la primera ventana todavía abierta, vuelve a ella y:

    1. Revisa el archivo: sudo nano /etc/ssh/sshd_con*
    2. Asegúrate de que tu llave pública esté en ~/.ssh/authorized_keys.
    3. Reinicia de nuevo: sudo systemctl restart ssh.
    4. Vuelve a probar en la segunda ventana.

    Configurar Firewall UFW

    Configurar y activar el firewall (cortafuegos) de tu servidor, asegurándote de que no te bloquee el acceso SSH que acabas de configurar.

    sudo ufw allow OpenSSH
    sudo ufw allow 22/tcp
    sudo ufw enable
    sudo ufw status
    • sudo ufw allow OpenSSH: Crea una regla que permite el tráfico para el perfil “OpenSSH”. Es la forma más recomendada porque el sistema ya sabe qué puertos usa SSH por defecto.
    • sudo ufw allow 22/tcp: Hace casi lo mismo que el anterior, pero de forma manual especificando el puerto 22 y el protocolo TCP. Es redundante si ya hiciste el anterior, pero sirve como refuerzo.
    • sudo ufw enable: Activa el firewall.
      • Al ejecutar el comando, te lanzará un aviso: “Command may disrupt existing ssh connections. Proceed with y/n?”. Escribe y y presiona Enter. Como ya permitiste el puerto 22 en los pasos anteriores, no perderás la conexión.
    • sudo ufw status: Te muestra la lista de reglas activas para confirmar que el puerto 22 (SSH) está en modo ALLOW (Permitido).

    Si en el futuro decides cambiar el puerto de SSH (por ejemplo al 2222) para evitar ataques automáticos, primero deberás hacer un sudo ufw allow 2222/tcp antes de cambiar la configuración del servidor, o te quedarás fuera.

    Instalar Fail2Ban

    Fail2Ban es un Framework de Prevención de Intrusiones (IPS) ligero y modular, escrito en Python. Su función técnica no es solo vigilar, sino actuar como una capa de automatización de políticas de red. En lugar de depender de la intervención manual de un administrador para bloquear ataques, Fail2Ban establece un puente entre el análisis de logs (aplicación) y la gestión de paquetes (red).

    Características Técnicas

    • Persistencia: Permite mantener bases de datos de atacantes recurrentes, lo que ayuda a identificar patrones de ataque persistentes y a establecer prohibiciones a largo plazo para IPs con comportamiento malicioso sistemático.
    • Arquitectura Basada en Jails (Jaulas): Permite configurar entornos aislados para cada servicio (SSH, Nginx, MySQL). Cada “jail” combina un filtro (la expresión regular que busca el error) con una acción (la respuesta del firewall).
    • Gestión Dinámica de Reglas Netfilter: A diferencia de las reglas estáticas de un firewall tradicional, Fail2Ban inyecta y remueve reglas en las tablas de iptables o nftables dinámicamente, minimizando el impacto en el rendimiento del sistema.
    • Multiservicio: Aunque su uso más común es SSH, es estándar en la industria para mitigar ataques de denegación de servicio (DDoS) a nivel de aplicación en servidores web, intentos de inyección en bases de datos y ataques de fuerza bruta en servidores de correo.

    Instala el paquete desde los repositorios oficiales:

    sudo apt update
    sudo apt install fail2ban -y

    Configuración (Crear tu “Jail”):

    Para esto lo correcto es crear una copia local llamada jail.local. Nunca edites el archivo jail.conf directamente, ya que se sobrescribe al actualizar.

    sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local
    sudo nano /etc/fail2ban/jail.local

    Busca la sección [sshd] y déjala configurada así (puedes borrar lo que haya o simplemente añadir estas líneas):

    [sshd]
    enabled = true
    port = ssh
    filter = sshd
    logpath = /var/log/auth.log
    maxretry = 3
    findtime = 600
    bantime = 3600

    ¿Qué significan estos valores?

    • maxretry = 3: El bot tiene solo 3 oportunidades antes del bloqueo.
    • findtime = 600: Los 3 fallos deben ocurrir en una ventana de 10 minutos.
    • bantime = 3600: Si falla, se le prohíbe la entrada por 1 hora (3600 segundos).

    Activar y Verificar

    Guarda el archivo y reinicia el servicio para aplicar los cambios:

    sudo systemctl restart fail2ban
    sudo systemctl enable fail2ban

    Verifica que esté funcionando:

    sudo fail2ban-client status sshd

    Importante: No te bloquees a ti mismo

    Si te equivocas de contraseña 3 veces, tú también serás bloqueado. Para evitarlo, busca la línea ignoreip en tu archivo jail.local y añade tu IP local.

    ignoreip = 127.0.0.1/8 ::1 TU_IP_AQUÍ

    Si te quedas fuera por error o bloqueas a un compañero, puedes liberar la IP inmediatamente con este comando:

    sudo fail2ban-client set sshd unbanip TU_IP_AQUÍ

    Si no estás seguro de qué IPs están baneadas en este momento, primero listalas con:

    sudo fail2ban-client status sshd

    Configurar zona horaria

    Comprobar la zona horaria del servidor

    timedatectl

    Establecer tu zona horaria, en mi caso Islas Canarias

     sudo timedatectl set-timezone Atlantic/Canary

    Herramientas útiles para administrar un VPS

    Estas utilidades son ampliamente utilizadas en administración de sistemas, DevOps y operaciones.

    • tmux — Permite mantener sesiones de terminal persistentes y ejecutar procesos largos aunque se cierre la conexión SSH.
    • htop — Monitor interactivo de procesos para visualizar CPU, memoria y procesos en tiempo real.
    • btop — Monitor avanzado del sistema con métricas de CPU, RAM, disco y red.
    • tree — Muestra la estructura de directorios en formato de árbol.
    • jq — Procesa y filtra datos JSON desde la línea de comandos.
    • ncdu — Analiza el uso del disco y muestra qué directorios ocupan más espacio.
    • rsync — Sincroniza archivos y directorios de forma eficiente, ideal para backups y despliegues.
    • lsof — Muestra qué procesos tienen abiertos archivos, sockets y puertos.
    • dnsutils — Incluye herramientas como dig y nslookup para diagnosticar DNS.
    • mtr — Analiza conectividad de red combinando ping y traceroute.
    • sysstat — Proporciona herramientas como iostat, sar y mpstat para análisis de rendimiento.
    • ufw — Firewall simplificado para gestionar reglas de red.
    • fail2ban — Bloquea automáticamente IPs con intentos repetidos de acceso fallido.
    • unattended-upgrades — Instala automáticamente actualizaciones de seguridad del sistema.
    • tcpdump — Captura y analiza tráfico de red a bajo nivel.
    • iotop — Muestra qué procesos están generando actividad de lectura/escritura en disco.
    • bash-completion — Añade autocompletado avanzado para comandos y opciones en Bash.
    • git — Sistema de control de versiones para clonar y gestionar repositorios.
    • curl — Herramienta para realizar peticiones HTTP y descargar contenido.
    • wget — Utilidad para descargar archivos desde Internet.

    Portal de proyectos para el VPS

    Agrega un sitio web alojado en el vps donde tengas los proyectos que vayas realizando. Puedes ver este proyecto aquí.

    https://fernandorioseco.es/proyecto-aplicacion-web-flask-projects-portal/
  • Entorno híbrido (Ollama + DeepSeek) con LangChain.

    Por qué un entorno RAG híbrido (local + API)

    Este entorno se ha diseñado como base de trabajo para realizar prácticas del curso IBM RAG and Agentic AI, pero desvinculando la implementación de la plataforma watsonx de IBM.

    El objetivo no es replicar la herramienta, sino replicar la arquitectura. En el curso, muchos de los ejercicios se apoyan en servicios gestionados en el ecosistema de IBM, lo que facilita el aprendizaje inicial, pero introduce una fuerte dependencia del proveedor. Para un aprendizaje más profundo y aplicable, es necesario trasladar esos mismos conceptos a un entorno abierto y controlado.

    Entorno: Conda + Python

    Se utiliza Anaconda como gestor de entornos por varias razones:

    • aislamiento de dependencias (evita conflictos entre librerías)
    • compatibilidad con librerías de data science (NumPy, Pandas, sklearn)
    • control de versiones reproducible
    • integración natural con notebooks y workflows analíticos

    Framework: LangChain

    Se utiliza LangChain como capa de orquestación:

    • Abstrae el uso del LLM
    • Permite cambiar de modelo sin cambiar el pipeline
    • Integra: loaders, chunking, embeddings, vector stores, chains

    Uso de IA local: Ollama

    Se utiliza Ollama para ejecutar modelos en local.

    VentajasLimitacionesRol en el sistema
    Independencia total de internet
    Coste cero
    Privacidad de datos
    Control completo del entorno
    Rendimiento limitado por hardware
    Modelos más pequeños
    Menor precisión en tareas complejas
    Desarrollo
    Testing
    Validación de arquitectura
    Entornos offline

    Uso de IA en API: DeepSeek

    Se utiliza DeepSeek como modelo en la nube.

    VentajasLimitacionesRol en el sistema
    Mayor calidad de respuesta
    Mejor razonamiento
    Contexto más amplio
    Coste bajo
    Dependencia de red
    Coste (aunque bajo)
    Menor control
    Validación de calidad
    Comparación con modelos locales
    Ejecución en escenarios reales

    Coste aproximado: Para el modelo por defecto que se va a usar (deepseek-chat):

    • Entrada: ~$0.14 – $0.28 por 1 millón de tokens
    • Salida: ~$0.28 – $0.42 por 1 millón de tokens

    Por qué un enfoque híbrido

    El uso combinado de ambos modelos permite:

    1. Separar arquitectura de proveedor. El sistema RAG se diseña una vez y el LLM se cambia según necesidad:
      • mismo pipeline → distinto modelo
    2. Optimizar coste vs rendimiento
      • local → coste 0
      • API → alta calidad cuando es necesario
    3. Comparación y evaluación. Permite evaluar:
      • calidad de respuestas
      • Impacto del modelo en RAG
      • Diferencias entre local y cloud

    Preparación del entorno RAG híbrido

    Creación del entorno (Anaconda)

    Se crea un entorno aislado para evitar conflictos de dependencias. En la consola de conda ejecuta:

    conda create -n rag_env python=3.10 -y
    conda activate rag_env

    Se utiliza Python 3.10 (máxima compatibilidad con LangChain ahora mismo).

    Instalación de dependencias

    En este entorno se combinan Conda y pip para la instalación de dependencias. Aunque mezclar ambos gestores puede generar conflictos si no se hace correctamente, se sigue un patrón controlado que evita problemas.

    Primero se utilizan paquetes instalados con Conda para la base científica (como NumPy, Pandas o Scikit-learn), ya que garantizan compatibilidad a nivel de sistema. A continuación, se emplea pip para instalar librerías más recientes del ecosistema de IA, como LangChain o herramientas de embeddings, que suelen estar más actualizadas fuera de Conda.

    La regla clave es mantener el orden: instalar primero con Conda y después con pip, evitando volver a usar Conda sobre el mismo entorno una vez que pip ha añadido dependencias. De esta forma, se consigue un entorno estable, reproducible y compatible con las necesidades del desarrollo de sistemas RAG.

    Base científica (Conda)

    conda install -c conda-forge numpy pandas scikit-learn -y

    Librerías de IA, Machine Learning, LangChain (pip)

    pip install langchain langchain-community langchain-core
    pip install -U langchain-ollama
    pip install langchain-openai
    pip install faiss-cpu
    pip install sentence-transformers
    pip install pypdf
    pip install python-dotenv
    pip install requests
    pip install ipykernel
    pip install BeautifullSoup4
    pip install chromadb

    Esta combinación evita problemas de compatibilidad.

    Crear proyecto

    1. Crea una carpeta del proyecto.
    2. En el IDE de preferencia crea el proyecto desde la carpeta creada.
    3. Selecciona el entorno creado en Anaconda
    4. Opcional y recomendable iniciar repositorio y conectar con github.
    5. Crear estructura base
    rag-local/
     ├── .env
     ├── main.py
     ├── data/
     └── notebooks/

    Configuración de IA local (Ollama)

    Descargar modelo:

    ollama pull qwen:4b

    Cuando termine la descarga del modelo, ejecuta:

    ollama run qwen:4b

    Si todo fue correcto, te aparece un prompt interactivo y puedes hacer cualquier pregunta para verificar que el modelo está instalado.

    Configuración de IA en API (DeepSeek)

    Visita https://platform.deepseek.com/ inicia sesión y crea una api_key.

    Crear archivo .env

    DEEPSEEK_API_KEY=tu_api_key

    Cargar las variables en main.py

    # Agrega al inicio
    from dotenv import load_dotenv
    import os
    
    # Cargar variables
    load_dotenv()
    api_key = os.getenv("DEEPSEEK_API_KEY")

    Configuración de LangChain

    Conexión a modelo local

    # Agrega al inicio
    from langchain_ollama import OllamaLLM
    
    
    # LLM local
    llm_local = OllamaLLM(model="qwen:4b")

    Conexión a modelo API

    # agregar al inicio
    from langchain_openai import ChatOpenAI
    
    
    # LLM API
    llm_api = ChatOpenAI(
        openai_api_key=api_key,
        openai_api_base="https://api.deepseek.com",
        model="deepseek-chat"
    )

    Selección de modelo

    Se define un selector para poder cambiar de modelo sin modificar el resto del sistema.

    # Selector de modelo
    usar_api = False
    
    # Elegir Modelo
    llm = llm_api if usar_api else llm_local

    Verificación del entorno

    Código mínimo de prueba al final de main.py:

    respuesta = llm.invoke("Explica qué es RAG en 2 líneas")
    print(respuesta)

    El modelo local responde con usar_api = False:

    RAG significa "Remo de Armas" en inglés.

    El modelo con API responde al usar_api = True

    content='RAG (Retrieval-Augmented Generation) es una técnica que combina la recuperación de información relevante desde una base de datos externa con un modelo de lenguaje, permitiendo generar respuestas más precisas y actualizadas sin necesidad de reentrenar el modelo.' additional_kwargs={'refusal': None} response_metadata={'token_usage': {'completion_tokens': 57, 'prompt_tokens': 15, 'total_tokens': 72, 'completion_tokens_details': None, 'prompt_tokens_details': {'audio_tokens': None, 'cached_tokens': 0}, 'prompt_cache_hit_tokens': 0, 'prompt_cache_miss_tokens': 15}, 'model_provider': 'openai', 'model_name': 'deepseek-v4-flash', 'system_fingerprint': 'fp_058df29938_prod0820_fp8_kvcache_20260402', 'id': '27107c79-dc76-40ab-b461-32439139c445', 'finish_reason': 'stop', 'logprobs': None} id='lc_run--019dcfd2-0298-7482-b39b-c069b9f5e30a-0' tool_calls=[] invalid_tool_calls=[] usage_metadata={'input_tokens': 15, 'output_tokens': 57, 'total_tokens': 72, 'input_token_details': {'cache_read': 0}, 'output_token_details': {}}

    Las respuestas de un LLM no solo contienen el texto generado (content), sino también metadatos relevantes como el uso de tokens, el modelo utilizado y el estado de finalización. Esta información es fundamental para analizar costes, rendimiento y comportamiento del sistema, especialmente en arquitecturas RAG.

    Creación de un módulo reutilizable

    El objetivo de este módulo es centralizar la configuración de los modelos LLM, permitiendo utilizar indistintamente un modelo local (Ollama) o un modelo en API (DeepSeek), evitando así la duplicación de código en notebooks o scripts.

    En lugar de definir la configuración del modelo en cada punto del proyecto, se encapsula esta lógica en un único módulo reutilizable. Esto facilita el cambio de modelo en cualquier momento y mejora la organización del código.

    Este enfoque resulta especialmente útil en sistemas RAG, donde el LLM forma parte de múltiples componentes del pipeline. Al desacoplar su configuración, se consigue un entorno más flexible, mantenible y preparado para evolucionar sin necesidad de modificar cada parte del sistema.

    Aquí tienes una sección lista para integrar en tu artículo, con enfoque didáctico y alineada con tu entorno híbrido.

    Parámetros de generación en DeepSeek y Ollama

    Los modelos de lenguaje, son configurables desde la API con parametros de generación que determinan el estilo, longitud y comportamiento de las respuestas. En este entorno híbrido (Ollama + DeepSeek), vamos a unificar conceptos para poder experimentar sin fricciones.

    Visita la documentación de la API de cada LLM

    Parámetros comunes

    Estos parámetros existen en ambos sistemas:

    Temperature (temperatura)

    Controla el nivel de aleatoriedad del modelo.

    • 0.0 → 0.3 → respuestas deterministas (más exactas)
    • 0.5 → 0.7 → equilibrio
    • 0.8+ → creatividad alta (más variabilidad)
    Max tokens / longitud de salida

    Limita el tamaño de la respuesta. Los LLM que estamos trabajando utilizan denominaciones diferentes:

    • DeepSeek → max_tokens
    • Ollama → num_predict
    Top-p (nucleus sampling)

    Controla la diversidad de palabras considerando la probabilidad acumulada.

    • 0.1 → 0.3 → respuestas más conservadoras
    • 0.8 → 1.0 → mayor diversidad
    Top-k (solo en Ollama)

    Limita el número de posibles palabras candidatas. DeepSeek no soporta este parámetro.

    • Bajo → más determinista
    • Alto → más diversidad
    Parámetros de penalización

    Solo DeepSeek (API tipo OpenAI) permite controlar repetición:

    • frequency_penalty → evita repetir palabras
    • presence_penalty → fomenta introducir nuevos temas
    Modos de razonamiento (DeepSeek)

    DeepSeek introduce capacidades avanzadas que permiten separar razonamiento interno de respuesta final

    • deepseek-reasoner
    • modo thinking

    Parámetros claves resumidos

    ParámetroDeepSeekOllamaUso recomendado
    temperature✔️✔️siempre
    max_tokens✔️usar como estándar
    num_predict✔️interno (no usar directamente)
    top_p✔️✔️recomendado
    top_k✔️opcional (solo local)
    penalties✔️avanzado
    reasoning mode✔️avanzado

    Agregar los parámetros al módulo

    Para evitar complejidad innecesaria, usamos una interfaz común y luego traducimos internamente:

    • max_tokens → num_predict (Ollama)
    • top_k solo si usamos Ollama

    Implementacion

    Crea en la raíz del proyecto el fichero llm_config.py

    from dotenv import load_dotenv
    import os
    
    from langchain_ollama import OllamaLLM
    from langchain_openai import ChatOpenAI
    
    # cargar variables de entorno
    load_dotenv()
    
    def get_llm(llm="dsk" , params=None):
        """
        Devuelve un modelo LLM configurado.
        
        Parameters:
        - usar_api (bool): si True usa DeepSeek, si False usa Ollama
        
        Returns:
        - instancia de LLM
        """
        
        default_params = {
            "temperature": 1, # Aleatoriedad del modelo.
            "max_tokens": 50, # Longitud de la respuesta en DeepSeek
            "top_p": 1, # diversidad de palabras considerando la probabilidad acumulada 
            "top_k": 40, # Diversidad de palabras considerando la frecuencia 
            "frequency_penalty": 0, # Penalizacion de frecuencia - DeepSeek
            "presence_penalty": 0, # Penalizacion de presencia - DeepSeek
            "repeat_penalty": 1.1 # Penalizacion de repeticion - Ollama
        }
    
        if params:
            default_params.update(params)
        
        if llm == "dsk":
            # DeepSeek
            return ChatOpenAI(
                model="deepseek-chat", 
                openai_api_key=os.getenv("DEEPSEEK_API_KEY"),
                openai_api_base="https://api.deepseek.com",
                temperature=default_params["temperature"],
                max_tokens=default_params["max_tokens"],
                top_p=default_params["top_p"],
                frequency_penalty=default_params["frequency_penalty"],
                presence_penalty=default_params["presence_penalty"]
            )
    
        elif llm == "oll":
            # Ollama
            return OllamaLLM(
                model="qwen:4b",
                temperature=default_params["temperature"],
                num_predict=default_params["max_tokens"],
                top_p=default_params["top_p"],
                top_k=default_params["top_k"],
                repeat_penalty=default_params["repeat_penalty"]
            )

    Test del módulo en un cuaderno Jupyter

    En la carpeta notebooks crea un cuaderno de Jupyter rag_test.ipynb. Antes de poder trabajar en el entorno rag_env debes registrar el kernel en Jupyter desde la terminal.

    Selecciona el kernel del entorno y añade al cuaderno las rutas para añadir la raíz al path,

    import sys
    import os
    
    sys.path.append(os.path.abspath(".."))

    Carga las variables del entorno

    from dotenv import load_dotenv
    load_dotenv()

    Importa la configuración de LLM

    from llm_config import get_llm

    Elige entre modelos cambiando el valor de llm

    llm = get_llm(llm="dsk")

    Realiza el test

    respuesta = llm.invoke("Explica qué es RAG en IA en 2 líneas")
    print(respuesta)

    Con esta configuración se ha establecido un entorno de trabajo completo para el desarrollo de sistemas RAG híbridos, combinando modelos locales y modelos en API dentro de una misma arquitectura.

    A lo largo de este proceso se ha definido una base técnica que permite trabajar de forma independiente a plataformas cerradas, replicando los conceptos del curso IBM RAG and Agentic AI en un entorno abierto, controlado y extensible. La integración de herramientas como LangChain, junto con el uso de modelos locales mediante Ollama y modelos en la nube como DeepSeek, proporciona la flexibilidad necesaria para experimentar, comparar resultados y optimizar el sistema según las necesidades.

    Este entorno no solo permite realizar las prácticas del curso, sino que sienta las bases para desarrollar soluciones reales, donde es posible equilibrar coste, rendimiento y control de los datos.

    A partir de este punto, el siguiente paso consiste en implementar el pipeline RAG completo, donde todas las piezas configuradas comenzarán a trabajar de forma conjunta y se podrá observar el verdadero valor de esta arquitectura.

    Actualización de entorno: modelo de embeddings

    En el entorno actual ya contamos con modelos de lenguaje (LLM) como Qwen o DeepSeek, que están diseñados para generación de texto. Sin embargo, para trabajar con arquitecturas RAG es imprescindible incorporar un segundo tipo de modelo: los modelos de embeddings.

    Estos modelos no generan texto, sino que transforman fragmentos de información en vectores numéricos que representan su significado semántico. Gracias a esto, es posible realizar búsquedas inteligentes, identificar similitudes entre textos y recuperar información relevante de forma eficiente.

    A diferencia de los LLM, los modelos de embeddings suelen ser más ligeros, pero trabajan de forma intensiva con memoria, especialmente cuando se generan vectores de múltiples documentos. En tu caso, según los recursos disponibles (16 GB de RAM ), es importante elegir un modelo que mantenga un buen equilibrio entre rendimiento y consumo.

    Para este entorno, la opción más recomendable es:

    nomic-embed-text

    Este modelo destaca por:

    • Buen rendimiento semántico para RAG
    • Bajo consumo de recursos
    • Ejecución fluida en entornos locales
    • Integración directa con Ollama

    Como alternativa más potente (pero más exigente en recursos) está: mxbai-embed-large
    (ideal si más adelante amplías RAM o trabajas con menos carga simultánea)

    Instalación del modelo de embeddings en Ollama

    Ejecuta en tu terminal:

    ollama pull nomic-embed-text
    Verificación (opcional pero recomendable)
    ollama list

    Deberías ver algo como:

    NAME                       ID              SIZE      MODIFIED
    nomic-embed-text:latest    0a109f422b47    274 MB    2 minutes ago
    qwen:4b                    d53d04290064    2.3 GB    3 days ago

    Separación de responsabilidades en el código

    Siguiendo buenas prácticas, no es recomendable mezclar la configuración de embeddings con la de los modelos generativos. Por ello, se introduce un nuevo módulo específico dentro del proyecto:

    embeddings_config.py

    De esta forma, cada tipo de modelo queda encapsulado en su propia capa, facilitando mantenimiento, escalabilidad y pruebas.

    Implementación del módulo de embeddings

    Se crea el archivo embeddings_config.py con una función que permite instanciar el modelo de embeddings de forma centralizada:

    from langchain_community.embeddings import OllamaEmbeddings
    
    def get_embeddings(provider="oll", model=None):
        """
        Devuelve un modelo de embeddings configurado.
        """
    
        if provider == "oll":
            return OllamaEmbeddings(
                model=model or "nomic-embed-text"
            )
    
        else:
            raise ValueError(f"Proveedor de embeddings no soportado: {provider}")

    Este enfoque permite desacoplar completamente el sistema y facilita futuros cambios, como probar otros modelos de embeddings sin modificar el resto del código.

    Uso dentro del flujo de trabajo

    Una vez definido el módulo, el uso es directo desde cualquier parte del proyecto:

    from config.embeddings_config import get_embeddings
    
    embeddings = get_embeddings()
    
    vector = embeddings.embed_query("¿Qué es RAG?")

    Con esto, ya es posible generar representaciones vectoriales tanto de consultas como de documentos.

    Resultado en la arquitectura híbrida

    Tras esta actualización, el entorno queda estructurado de forma clara:

    Embeddings → Ollama (local)
    
    LLM → DeepSeek / Ollama

    Esta separación es fundamental y refleja cómo se diseñan los sistemas RAG en entornos reales de producción, donde cada componente cumple una función específica dentro del pipeline.

  • Anaconda: guía práctica para gestionar entornos, paquetes y flujos de trabajo

    Instalar Anaconda te da acceso a conda, Python y miles de otras herramientas populares. Instala automáticamente más de 300 paquetes listos para el trabajo en Data Science.

    Anaconda Navigator proporciona una interfaz gráfica de usuario: Anaconda Desktop para interactuar con conda, sin utilizar la línea de comandos. Si prefiere trabajar desde la línea de comandos, puede interactuar con conda directamente a través de Anaconda Prompt.

    Manejo de entornos

    El entorno (base) NO es para proyectos, úsalo solamente para la gestión de conda y tareas globales. El proceso de instalación de conda crea un entorno llamado base, donde se instala conda. Sin embargo, al comenzar un nuevo proyecto, se recomienda crear un nuevo entorno. Esto facilita el mantenimiento y la reproducibilidad de los entornos, además de mantener su estabilidad.

    Crear un nuevo entorno

    conda create --name <ENV_NAME> <PACKAGE>=<VERSION> <PACKAGE> <PACKAGE>

    Puedes añadir paquetes al entorno especificando o no la versión. Ejemplo:

    conda create --name hello-env python=3.14 pandas beautifulsoup4 

    Activar un entorno

    conda activate <ENV_NAME>

    Cambiar entre entornos y visualizar entornos existentes

    conda info --envs
    conda activate <ENV_NAME>

    Bloquear un entorno

    Bloquear un entorno crea un entorno completamente especificado, con todos los paquetes utilizados en el proyecto y sus dependencias configuradas a una versión específica. Para bloquear tu proyecto, necesitas conda-project instalado el paquete en el entorno que deseas bloquear. Instala el paquete ejecutando los siguientes comandos:

    conda activate <ENV>
    conda install conda-project

    Si tu proyecto no contiene un archivo, environment.yml créalo ejecutando el siguiente comando:

    conda-project init

    A continuación, puedes bloquear el entorno de tu proyecto ejecutando el siguiente comando:

    conda-project lock

    Al bloquear tu proyecto, se genera un archivo conda-lock.default.yml que puedes exportar para compartirlo con otros.

    Compartir un entorno

    Compartir tu entorno con otra persona le permite usar conda para recrear tu entorno en su máquina. Para compartir un entorno y sus paquetes de software, debe exportar las configuraciones de su entorno a un archivo .yml en un entorno que este activado con el comando.

    conda env export > environment.yml

    El archivo se guarda en su directorio de trabajo y se puede compartir.

    Desactivar un entorno

    Lo más recomendable es desactivar el entorno cuando hayas terminado de trabajar en él. Cuando desactivas un entorno, conda vuelve al entorno que estaba activado anteriormente. Para desactivar su entorno activo, ejecute el siguiente comando:

    conda deactivate

    Eliminar un entorno

    Para eliminar un entorno, ejecute el siguiente comando. Si, por cualquier motivo, necesita eliminar manualmente un directorio de entorno, no utilice el explorador de archivos . Si lo hace, eliminará el contenido del entorno y liberará espacio en su equipo, pero la ruta del entorno permanecerá en su archivo environments.txt.

    conda remove --name <ENV_NAME> --all

    Gestión de Canales

    En el ecosistema de Conda, los canales son repositorios remotos donde se alojan los paquetes. Los tipos de canales más comunes:

    1. Defaults: Es el canal oficial gestionado por Anaconda. Contiene paquetes probados y validados para ser estables y compatibles entre sí.
    2. Conda-Forge: Es un canal comunitario (el más grande y popular). Al ser mantenido por la comunidad, suele tener versiones más actualizadas de las librerías y una variedad mucho mayor de paquetes que el canal por defecto.
    3. Canales específicos: Existen repositorios especializados para nichos científicos o técnicos, como bioconda (para bioinformática).

    Conda permite tener varios canales activos a la vez, pero sigue un orden jerárquico. Si un mismo paquete (por ejemplo, pandas) está disponible en dos canales distintos, Conda lo descargará del que tenga mayor prioridad (el que aparezca primero en tu configuración).

    Visualización de los canales disponibles

    Para ver qué canales están configurados actualmente en conda ejecute el siguiente comando:

    conda config --show channels

    Configuración de canales

    Conda lee la configuración de sus canales desde el archivo .condarc. Para añadir, eliminar o reordenar canales, deberá editar este archivo. Para encontrarlo utilice el comando:

    conda config --show-sources

    Puedes añadir o eliminar canales de tu lista channels: usando comandos de conda en o editando manualmente tu el archivo .condarc.

    conda config <FLAG> channels <CHANNEL>
    FlagAcción
    --addAgrega un canal al principio de channels:.
    --prependAgrega un canal al principio de channels:.
    --appendAgrega un canal al final de channels:.
    --removeElimina un canal de channels:.

    Ejemplo:

    conda config --add channels conda-forge

    Configurar valores predeterminados

    La entrada defaults en tu lista de channels: es un alias especial. Cuando conda detecta busca en los canales listados default_channels: en orden descendente. Este  también se puede configurar utilizando comandos de conda o editando manualmente .condarc.

    conda config --add default_channels <CHANNEL>

    Reemplaza <CHANNEL> con la URL del canal que deseas agregar.

    Instalación de paquetes desde un canal específico

    El uso de la sintaxis de dos puntos dobles instala el paquete desde el canal especificado, pero instala las dependencias de ese paquete desde los canales que aparecen en el  .condarc siguiendo el orden de prioridad de los canales.

    conda install <CHANNEL>::<PACKAGE>

    Gestión de paquetes

    Buscando paquetes conda

    La función de búsqueda de Conda le permite buscar a través de canales para comprobar si un paquete específico está disponible, qué versiones existen en diferentes canales o qué ya está instalado en su entorno local.

    conda search <PACKAGE>

    Buscar un canal específico

    conda search <CHANNEL>::<PACKAGE>

    Búsqueda en entornos locales

    Utilice la bandera --envs para buscar un paquete en sus entornos locales:

    conda search --envs <PACKAGE>

    Instalar paquetes

    Para instalar un solo paquete, ejecute el siguiente comando:

    conda install <PACKAGE>

    Para instalar un paquete en un entorno que no sea su entorno activo actual, especifique el nombre del entorno:

    conda install <PACKAGE> --name <ENVIRONMENT>

    Especificar un canal:

    conda install <CHANNEL>::<PACKAGE>

    Especificación de versiones de paquetes

    Por defecto, al instalar paquetes desde la línea de comandos, conda recupera las versiones más recientes de los paquetes solicitados (y sus dependencias) que sean compatibles con el entorno actual.

    conda install <PACKAGE>=<VERSION>

    Actualización de paquetes

    Para actualizar un solo paquete, ejecute el siguiente comando:

    conda update <PACKAGE>

    Cuando actualizas un paquete, conda también puede actualizar otros paquetes del entorno para mantener la compatibilidad, o instalar nuevos paquetes necesarios para las dependencias actualizadas. Esto ayuda a evitar que tu entorno se dañe debido a cambios en las dependencias. Para evitar que conda actualice cualquier paquete que no sea el que especifiques, usa la bandera --no-update-deps

    Actualizar varios paquetes

    conda update <PACKAGE> <PACKAGE> <PACKAGE>

    Especificar un canal para las actualizaciones de paquetes

    conda update <PACKAGE> --override-channels --channel <CHANNEL>

    Actualizar todos los paquetes

    Es posible que la ejecución de este comando no actualice todos los paquetes de un entorno determinado a sus últimas versiones. Si la última versión de un paquete es incompatible con otros paquetes instalados en el entorno, conda solo actualizará ese paquete a la última versión compatible .

    conda update --all

    Usando pip en Conda

    La mayoría de los paquetes populares del repositorio PyPI están disponibles en el repositorio público de Anaconda , Anaconda.org o conda-forge . Sin embargo, es posible que necesite usar pip si un paquete o una versión específica no está disponible a través de conda. Instalar paquetes usando pip modifica tu entorno conda. Sin embargo, conda desconoce estas modificaciones. Como resultado, cuando conda intenta modificar el entorno posteriormente, existe una alta probabilidad de que surjan conflictos de dependencias entre los paquetes controlados por conda y los paquetes de pip no controlados, lo que puede provocar un entorno dañado.

    Comprender conda y pip

    Aunque algunas funcionalidades de conda y pip se solapan (en concreto, la capacidad de instalar paquetes de Python), fueron diseñadas y deben usarse con fines diferentes.

    • Pip es la herramienta recomendada por la Autoridad de Empaquetado de Python para instalar paquetes del Índice de Paquetes de Python (PyPI).
    • Conda, por otro lado, es un gestor de paquetes y entornos multiplataforma que instala y gestiona paquetes tanto del repositorio público de Anaconda como de Anaconda.org.

    Otras diferencias clave entre conda y pip incluyen:

    condapip
    Formato de distribución del paqueteBinariosWheels o fuente
    ¿Requiere compiladores?No
    Tipos de paquetesCualquiera (Python, R, C++, etc.)Solo Python
    ¿Creación de entorno?Sí, incorporadoNo, requiere virtualenv o venv.
    ¿Resolución de dependencias?No
    Fuentes de paquetesRepositorio de Anaconda, Anaconda.orgPyPI

    Crear un entorno conda que incluya paquetes pip

    Para crear un entorno estable que incluya paquetes pip, Anaconda recomienda escribir un archivo environment.yml y luego construir un entorno a partir de ese archivo. Aunque este método requiere más tiempo de configuración, ofrece varias ventajas:

    • Control sobre el orden de compilación, las versiones y los canales de los paquetes.
    • Actualizaciones de entorno sencillas
    • Mayor reproducibilidad y facilidad para compartir mediante un archivo .yml.

    Al escribir el archivo, asegúrese de agregar pip y sus dependencias al final, ya que conda crea los entornos en el orden en que aparecen. Ejemplo:

    name: myenv           # Nombre del entorno
    dependencies:         # Lista de los paquetes que se incluyen
        - python=3.12    
        - bokeh>=2.4.2
        - flask
        - pip             # Install pip en el entorno
        - pip:            # Incluir los paquetes pip al final
            - Flask-Testing

    La documentación oficial de conda incluye más información sobre cómo crear archivos de entorno manualmente , así como especificaciones de coincidencia de paquetes .

    Creación de un entorno a partir de un archivo environment.yml

    Para crear un entorno a partir de un archivo environment.yml, ejecute el siguiente comando desde el directorio que contiene el archivo:

    conda env create --file environment.yml

    Actualizar un entorno con un archivo environment.yml

    Si alguna vez necesita agregar paquetes a su entorno, realizar cambios en las versiones de los paquetes o eliminar paquetes, actualice el archivo environment.yml y luego vuelva a construir el entorno ejecutando el siguiente comando desde el directorio que contiene el archivo:

    conda env update --file environment.yml --prune

    --prune elimina cualquier paquete huérfano del entorno.

    Uso de pip install en un entorno conda

    Debido a que conda no reconoce las actualizaciones de entorno realizadas por pip, el uso de pip en su entorno debe ser la última acción que se realice al construir el entorno.

    conda install <PACKAGE> <PACKAGE> pip

    No ejecute pip install en su entorno base. Cree un entorno conda independiente para aislar los cambios.

    Solucionador de dependencias

    Una de las principales características de conda es su capacidad para gestionar paquetes de software y sus dependencias. La gestión de dependencias puede resultar compleja, sobre todo cuando un paquete tiene muchas dependencias. Conda utiliza un algoritmo llamado 
    solucionador de dependencias , que determina qué versiones de qué paquetes deben instalarse para satisfacer (o resolver) todas las dependencias sin conflictos de versiones.

    Gestión de errores del solucionador

    Aunque el solucionador de conda está diseñado para instalar paquetes y sus dependencias sin generar conflictos de versiones, estos pueden ocurrir. Este tutorial explicará los posibles escenarios de conflicto del solucionador y cómo solucionarlos.

    Gestionar Python en entornos conda

    Por defecto, al instalar o actualizar paquetes en un ambiente, conda recupera las versiones más recientes posibles del/de los paquete(s) solicitado(s) y sus dependencias que sean compatibles con el entorno actual.

    Algunos paquetes (o versiones de paquetes) solo son compatibles con ciertas versiones de Python. Si intentas instalar un paquete que no es compatible con la versión de Python que usas en tu entorno, conda no lo instalará.

    En este caso, suele ser mejor crear un nuevo entorno que use la versión de Python requerida, junto con los demás paquetes que necesitas.Para crear un nuevo entorno con una versión específica de Python y todos los paquetes que necesitas, ejecuta el siguiente comando:

    conda create --name <ENVIRONMENT> python=<VERSION> <PACKAGE> <PACKAGE> <PACKAGE>

    Integraciones de conda

    Consulta esta página para integrar conda con:

    • Docker
    • Authenticated Docker builds
    • Snowflare Snowpark
    • TensorFlow

    Más de Anaconda

    • Herramientas Anaconda: diseñadas para optimizar tus flujos de trabajo de ciencia de datos, aprendizaje automático e inteligencia artificial. 
    • Plataforma Anaconda (Nube): Anaconda Platform proporciona una plataforma segura y repositorio centralizado. Dónde puedes controlar el acceso de tu organización a paquetes software de código abierto y realizar un seguimiento de las vulnerabilidades del software.
    • Data Science & AI Workbench: Workbench es una plataforma de ciencia de datos escalable, segura y preparada para entornos empresariales que permite a los equipos gestionar los activos de ciencia de datos, colaborar e implementar sus proyectos de ciencia de datos.

    Flujo de trabajo

    Crea el nuevo entorno para el proyecto y actívalo

    conda create --name <ENV_NAME>
    conda activate <ENV_NAME>

    Instala los paquetes necesarios para el proyecto

    conda install pandas scipy numpy matplotlib seaborn scikit-learn 

    Trabajar con JupyterLab – conda

    Para que el entorno aparezca en la lista de opciones de tu cuaderno, ejecuta este comando y luego puedes seleccionarlo en la lista de kernels disponibles.

    python -m ipykernel install --user --name=<ENV_NAME> --display-name "NAME_ALIAS"
    

    Trabajar con Visual Studio Code – conda

    Presiona Ctrl+Mayús+P, busca Python: Select Interpreter y elige tu entorno de la lista. Puedes instalar la extensión nb_conda_kernels en tu entorno base (conda install nb_conda_kernels), la cual detectará automáticamente todos tus entornos de Conda que tengan ipykernel instalado.