Deploy tu Aplicación Flask en Heroku: Tutorial Paso a Paso

👤 Admin 📅 19 de octubre, 2025 ⏱ 17 min 🏷 Desarrollo Web

¿Qué es Heroku?

Heroku es una plataforma como servicio (PaaS) que permite desplegar, ejecutar y gestionar aplicaciones web en la nube. Es ideal para principiantes porque simplifica el proceso de deployment y ofrece un tier gratuito para proyectos pequeños.

Requisitos Previos

  • Aplicación Flask funcionando localmente
  • Git instalado y configurado
  • Cuenta de Heroku (gratis en heroku.com)
  • Heroku CLI instalado

Instalar Heroku CLI

Windows

# Descargar desde: https://devcenter.heroku.com/articles/heroku-cli
# O con Chocolatey:
choco install heroku-cli

macOS

# Con Homebrew
brew tap heroku/brew && brew install heroku

Linux

# Ubuntu/Debian
curl https://cli-assets.heroku.com/install.sh | sh

# Verificar instalación
heroku --version

Preparar tu Aplicación Flask

Estructura del Proyecto

mi-app-flask/
├── app.py              # Aplicación principal
├── requirements.txt    # Dependencias
├── Procfile           # Comando de inicio
├── runtime.txt        # Versión de Python
├── .gitignore         # Archivos a ignorar
├── templates/         # Templates HTML
├── static/            # CSS, JS, imágenes
└── venv/              # Entorno virtual (no subir)

Aplicación Flask Básica (app.py)

from flask import Flask, render_template
import os

app = Flask(__name__)

@app.route('/')
def index():
    return render_template('index.html')

@app.route('/about')
def about():
    return render_template('about.html')

if __name__ == '__main__':
    # Puerto dinámico para Heroku
    port = int(os.environ.get('PORT', 5000))
    app.run(host='0.0.0.0', port=port, debug=False)

Archivos de Configuración

requirements.txt

# Generar con entorno virtual activado
pip freeze > requirements.txt
Flask==2.3.0
gunicorn==21.2.0
Werkzeug==2.3.0

Procfile

web: gunicorn app:app

Importante: El Procfile no tiene extensión. El primer 'app' es el nombre del archivo (app.py), el segundo es la instancia de Flask.

runtime.txt

python-3.11.4

Verifica las versiones soportadas en: https://devcenter.heroku.com/articles/python-support

.gitignore

# Entornos virtuales
venv/
env/
ENV/

# Python
__pycache__/
*.pyc
*.pyo
*.egg-info/

# Flask
instance/
.webassets-cache

# Variables de entorno
.env

# IDEs
.vscode/
.idea/

# Sistema
.DS_Store
Thumbs.db

Configurar Git

# Inicializar repositorio
git init

# Agregar archivos
git add .

# Primer commit
git commit -m "Configuración inicial para Heroku"

# Verificar
git status

Login en Heroku

# Login desde terminal
heroku login

# Se abrirá navegador para autenticación
# O usar:
heroku login -i  # Login interactivo en terminal

Crear Aplicación en Heroku

# Crear app con nombre automático
heroku create

# Crear app con nombre específico
heroku create mi-app-flask-demo

# Verificar remotes
git remote -v
# Deberías ver:
# heroku  https://git.heroku.com/mi-app-flask-demo.git (fetch)
# heroku  https://git.heroku.com/mi-app-flask-demo.git (push)

Deploy a Heroku

# Push a Heroku
git push heroku master
# O si usas 'main':
git push heroku main

# Ver logs durante deploy
heroku logs --tail

# Abrir aplicación en navegador
heroku open

Aplicación Flask Completa para Deploy

app.py

from flask import Flask, render_template, request, jsonify
import os
from datetime import datetime

app = Flask(__name__)
app.config['SECRET_KEY'] = os.environ.get('SECRET_KEY', 'dev-secret-key')

# Lista para almacenar mensajes (en producción usar base de datos)
messages = []

@app.route('/')
def index():
    return render_template('index.html')

@app.route('/api/messages', methods=['GET', 'POST'])
def handle_messages():
    if request.method == 'POST':
        data = request.get_json()
        message = {
            'text': data.get('text'),
            'timestamp': datetime.now().isoformat()
        }
        messages.append(message)
        return jsonify(message), 201
    
    return jsonify(messages)

@app.route('/about')
def about():
    return render_template('about.html')

@app.errorhandler(404)
def not_found(error):
    return render_template('404.html'), 404

if __name__ == '__main__':
    port = int(os.environ.get('PORT', 5000))
    debug = os.environ.get('DEBUG', 'False') == 'True'
    app.run(host='0.0.0.0', port=port, debug=debug)

templates/index.html

<!DOCTYPE html>
<html lang="es">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Mi App Flask en Heroku</title>
    <link rel="stylesheet" href="{{ url_for('static', filename='css/style.css') }}">
</head>
<body>
    <div class="container">
        <h1>¡Bienvenido a mi App Flask!</h1>
        <p>Esta aplicación está desplegada en Heroku.</p>
        
        <div class="message-box">
            <h2>Enviar Mensaje</h2>
            <input type="text" id="messageInput" placeholder="Escribe un mensaje">
            <button onclick="sendMessage()">Enviar</button>
        </div>
        
        <div id="messages"></div>
    </div>
    
    <script src="{{ url_for('static', filename='js/main.js') }}"></script>
</body>
</html>

Variables de Entorno en Heroku

# Establecer variable de entorno
heroku config:set SECRET_KEY="tu-clave-secreta-aqui"

# Ver variables configuradas
heroku config

# Eliminar variable
heroku config:unset VARIABLE_NAME

# Establecer múltiples
heroku config:set VAR1=value1 VAR2=value2

Usar Base de Datos PostgreSQL

Agregar PostgreSQL

# Agregar addon de PostgreSQL (gratis)
heroku addons:create heroku-postgresql:mini

# Ver URL de la base de datos
heroku config:get DATABASE_URL

Actualizar requirements.txt

Flask==2.3.0
gunicorn==21.2.0
psycopg2-binary==2.9.6
Flask-SQLAlchemy==3.0.5

Configurar en app.py

import os
from flask import Flask
from flask_sqlalchemy import SQLAlchemy

app = Flask(__name__)

# Configuración de base de datos
app.config['SQLALCHEMY_DATABASE_URI'] = os.environ.get('DATABASE_URL').replace('postgres://', 'postgresql://', 1)
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False

db = SQLAlchemy(app)

# Modelo
class Message(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    text = db.Column(db.String(500), nullable=False)
    created_at = db.Column(db.DateTime, default=datetime.utcnow)

# Crear tablas
with app.app_context():
    db.create_all()

Comandos Útiles de Heroku

# Ver logs en tiempo real
heroku logs --tail

# Ver logs recientes
heroku logs --num 100

# Reiniciar aplicación
heroku restart

# Ver estado de la app
heroku ps

# Escalar dynos
heroku ps:scale web=1

# Abrir consola Python en Heroku
heroku run python

# Ejecutar comandos
heroku run python -c "from app import db; db.create_all()"

# Abrir dashboard
heroku open

# Ver información de la app
heroku info

Actualizar la Aplicación

# 1. Hacer cambios en el código

# 2. Commit
git add .
git commit -m "Descripción de cambios"

# 3. Push a Heroku
git push heroku main

# 4. Ver logs
heroku logs --tail

Dominio Personalizado

# Agregar dominio personalizado
heroku domains:add www.tudominio.com

# Ver dominios configurados
heroku domains

# Configurar DNS
# En tu proveedor de DNS, crear registro CNAME:
# www.tudominio.com -> tu-app.herokuapp.com

SSL/HTTPS

Heroku proporciona SSL automático para dominios .herokuapp.com y dominios personalizados.

# Verificar SSL
heroku certs:auto

# Forzar HTTPS en Flask
from flask_sslify import SSLify

if 'DYNO' in os.environ:  # Solo en producción
    sslify = SSLify(app)

Monitoreo y Debugging

Ver Métricas

# Dashboard web
heroku addons:open papertrail  # Logs
heroku addons:open librato     # Métricas

Debugging

# Agregar logging
import logging

logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)

@app.route('/')
def index():
    logger.info('Acceso a página principal')
    return render_template('index.html')

Troubleshooting Común

Error: Application Error

# Ver logs
heroku logs --tail

# Verificar Procfile
cat Procfile

# Verificar que gunicorn esté instalado
pip list | grep gunicorn

Error: No web processes running

# Escalar web dyno
heroku ps:scale web=1

Error: Requirements.txt

# Regenerar requirements.txt
pip freeze > requirements.txt
git add requirements.txt
git commit -m "Update requirements"
git push heroku main

Mejores Prácticas

  • ✅ Usa variables de entorno para configuraciones
  • ✅ Nunca subas claves secretas a Git
  • ✅ Usa PostgreSQL para producción
  • ✅ Implementa logging adecuado
  • ✅ Configura manejo de errores
  • ✅ Usa gunicorn en producción
  • ✅ Mantén requirements.txt actualizado
  • ✅ Implementa SSL/HTTPS

Alternativas a Heroku

  • Railway: Similar a Heroku, fácil de usar
  • Render: Free tier generoso
  • PythonAnywhere: Especializado en Python
  • Google Cloud Run: Contenedores serverless
  • AWS Elastic Beanstalk: Más complejo pero potente
  • DigitalOcean App Platform: Buena relación precio/valor

Checklist de Deploy

  • ☐ Aplicación funciona localmente
  • ☐ requirements.txt actualizado
  • ☐ Procfile creado correctamente
  • ☐ runtime.txt con versión Python
  • ☐ .gitignore configurado
  • ☐ Variables de entorno configuradas
  • ☐ Puerto dinámico implementado
  • ☐ Debug=False en producción
  • ☐ Git commit de todos los cambios
  • ☐ Push a Heroku exitoso

Conclusión

Desplegar tu aplicación Flask en Heroku es un proceso directo que te permite tener tu proyecto en producción rápidamente. Heroku maneja la infraestructura, permitiéndote enfocarte en desarrollar tu aplicación. Sigue esta guía paso a paso y tendrás tu app online en minutos. Recuerda monitorear los logs y optimizar tu aplicación según el uso real.