¿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-climacOS
# Con Homebrew
brew tap heroku/brew && brew install herokuLinux
# Ubuntu/Debian
curl https://cli-assets.heroku.com/install.sh | sh
# Verificar instalación
heroku --versionPreparar 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.txtFlask==2.3.0
gunicorn==21.2.0
Werkzeug==2.3.0Procfile
web: gunicorn app:appImportante: 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.4Verifica 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.dbConfigurar Git
# Inicializar repositorio
git init
# Agregar archivos
git add .
# Primer commit
git commit -m "Configuración inicial para Heroku"
# Verificar
git statusLogin en Heroku
# Login desde terminal
heroku login
# Se abrirá navegador para autenticación
# O usar:
heroku login -i # Login interactivo en terminalCrear 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 openAplicació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=value2Usar 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_URLActualizar requirements.txt
Flask==2.3.0
gunicorn==21.2.0
psycopg2-binary==2.9.6
Flask-SQLAlchemy==3.0.5Configurar 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 infoActualizar 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 --tailDominio 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.comSSL/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étricasDebugging
# 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 gunicornError: No web processes running
# Escalar web dyno
heroku ps:scale web=1Error: Requirements.txt
# Regenerar requirements.txt
pip freeze > requirements.txt
git add requirements.txt
git commit -m "Update requirements"
git push heroku mainMejores 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.