🚀 Modulo 8: Deployment e Produzione
Metti online la tua applicazione Flask e condividila con il mondo!
8 di 8
60 minuti
Master
🎯 Benvenuto nell’Ultimo Modulo!
Congratulazioni! Hai imparato tutto ciò che serve per costruire applicazioni Flask professionali. Ora è il momento di condividere il tuo lavoro con il mondo.
Accessibile Ovunque
La tua app sarà online 24/7
Multi-utente
Chiunque può usare la tua app
Mobile Ready
Accessibile da qualsiasi dispositivo
Portfolio
Mostra il tuo lavoro a potenziali clienti/datori
💡 Cosa Significa “Deployment”?
Il deployment è il processo di pubblicazione della tua applicazione su un server accessibile da Internet. Pensa a quando pubblichi una foto su Instagram: dalla tua galleria (locale) ai server di Instagram (produzione).
🔧 Preparazione per la Produzione
Prima di pubblicare, dobbiamo preparare l’applicazione per l’ambiente di produzione.
Lista di tutte le dipendenze del progetto:
# Genera automaticamente requirements.txt pip freeze > requirements.txt
Flask==2.3.2 Flask-SQLAlchemy==3.0.5 Flask-Login==0.6.2 Flask-WTF==1.1.1 Flask-Bcrypt==1.0.1 SQLAlchemy==2.0.19 Werkzeug==2.3.6 python-dotenv==1.0.0 gunicorn==20.1.0 psycopg2-binary==2.9.7
# Ambiente FLASK_ENV=production FLASK_DEBUG=False # Database DATABASE_URL=postgresql://user:password@localhost/dbname # O per SQLite # DATABASE_URL=sqlite:///app.db # Segreti SECRET_KEY=la_tua_chiave_segreta_molto_lunga_e_complessa JWT_SECRET_KEY=altra_chiave_segreta_per_jwt # Email (se usi email) MAIL_SERVER=smtp.gmail.com MAIL_PORT=587 MAIL_USE_TLS=True MAIL_USERNAME=tuamail@gmail.com MAIL_PASSWORD=tua_password_app_specifica
import os
from flask import Flask
from dotenv import load_dotenv
# Carica variabili d'ambiente da .env
load_dotenv()
app = Flask(__name__)
# Configurazione da variabili d'ambiente
app.config['SECRET_KEY'] = os.getenv('SECRET_KEY', 'fallback-secret-key')
app.config['SQLALCHEMY_DATABASE_URI'] = os.getenv('DATABASE_URL')
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
# Debug mode solo in sviluppo
app.config['DEBUG'] = os.getenv('FLASK_DEBUG', 'False').lower() == 'true'
# Configurazione produzione
if not app.debug:
app.config.update(
SESSION_COOKIE_SECURE=True,
SESSION_COOKIE_HTTPONLY=True,
SESSION_COOKIE_SAMESITE='Lax',
PERMANENT_SESSION_LIFETIME=3600
)
⚙️ WSGI: Il Server per la Produzione
❌ Server di Sviluppo Flask
app.run(debug=True)
- Solo per sviluppo
- Single-threaded
- Nessun load balancing
- Debug mode attivo (pericoloso in produzione!)
- Crasha con errori
- Performance limitate
✅ WSGI Server (Gunicorn)
gunicorn app:app
- Per produzione
- Multi-worker/process
- Load balancing automatico
- Gestione errori robusta
- Performance ottimizzate
- Riavvi automatici
pip install gunicorn
from app import app
if __name__ == "__main__":
app.run()
# Semplice gunicorn app:app # Con 4 worker (processi) gunicorn --workers 4 app:app # Su porta specifica gunicorn --bind 0.0.0.0:8000 app:app # Con logging gunicorn --access-logfile - --error-logfile - app:app # Per applicazioni più complesse gunicorn --workers 4 --bind unix:app.sock -m 007 wsgi:app
☁️ Opzioni di Hosting per Flask
PythonAnywhere
Perfetto per iniziare
- Piano gratuito disponibile
- Setup in 5 minuti
- Console Python nel browser
- Database MySQL incluso
- SSL gratuito
- Limite: 512MB RAM
- Supporto base
Railway / Render
Moderno e semplice
- Deploy da Git con un click
- Auto-deploy su push
- Database automatico
- SSL automatico
- Piano gratuito generoso
- CI/CD integrato
- Monitoraggio base
AWS / Google Cloud
Professionale & Scalabile
- Altamente scalabile
- Completamente personalizzabile
- Database managed
- CDN integrato
- Backup automatici
- Monitoraggio avanzato
- Supporto 24/7
🚀 Deployment su Railway (Facile & Gratis)
Prepara App
Crea Procfile
Push su GitHub
Connetti Railway
Configura Variabili
Railway usa questo file per sapere come avviare la tua app.
web: gunicorn app:app
Alternative:
# Se il file principale si chiama wsgi.py web: gunicorn wsgi:app # Con worker multipli web: gunicorn --workers 4 app:app # Se usi un'app factory web: gunicorn "app:create_app()"
python-3.11.0
flask-app/ ├── app.py ← File principale ├── wsgi.py ← Entry point WSGI ├── requirements.txt ← Dipendenze ├── Procfile ← Comando di avvio ├── runtime.txt ← Versione Python (opzionale) ├── .env ← Variabili locali (NON commitare!) ├── .gitignore ← Esclude .env, __pycache__, etc. ├── static/ ├── templates/ ├── models.py ├── forms.py └── README.md
- Crea account su railway.app
- Click “New Project” → “Deploy from GitHub repo”
- Connetti il tuo account GitHub
- Scegli il repository con la tua app Flask
- Railway deployerà automaticamente
- Vai su Settings → Variables e aggiungi:
SECRET_KEY=tua_chiave_segreta_lunga DATABASE_URL=postgresql://... # Railway crea DB automaticamente FLASK_ENV=production
- La tua app è online! 🎉
🎨 Deployment su Render (Alternative)
services:
- type: web
name: flask-app
env: python
buildCommand: pip install -r requirements.txt
startCommand: gunicorn app:app
envVars:
- key: SECRET_KEY
generateValue: true
- key: DATABASE_URL
fromDatabase:
name: flask-db
property: connectionString
- key: FLASK_ENV
value: production
databases:
- name: flask-db
databaseName: flaskdb
user: flaskuser
- Vai su render.com
- Crea account (con GitHub)
- Click “New +” → “Web Service”
- Connetti repository GitHub
- Render rileverà automaticamente render.yaml
- Click “Create Web Service”
- Il deploy inizia automaticamente
🗄️ Database in Produzione
⚠️ IMPORTANTE: SQLite NON per Produzione!
SQLite è perfetto per sviluppo, ma in produzione usa un database vero:
- PostgreSQL: Raccomandato – robusto, funzionalità complete
- MySQL: Buona alternativa – ampiamente supportato
- SQLite: ❌ Solo sviluppo/testing
import os
from flask_sqlalchemy import SQLAlchemy
from urllib.parse import urlparse
app = Flask(__name__)
# Prendi URL database da variabile d'ambiente
database_url = os.getenv('DATABASE_URL')
# Railway/Render forniscono DATABASE_URL già formattata
if database_url:
# Gestisci caso di Railway che usa postgres:// invece di postgresql://
if database_url.startswith('postgres://'):
database_url = database_url.replace('postgres://', 'postgresql://', 1)
app.config['SQLALCHEMY_DATABASE_URI'] = database_url
else:
# Fallback a SQLite per sviluppo
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///app.db'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
db = SQLAlchemy(app)
# In produzione, prima del deploy flask db upgrade # O in Railway/Render, aggiungi build command # buildCommand: "pip install -r requirements.txt && flask db upgrade" # Se qualcosa va storto flask db downgrade # Torna indietro di una migrazione flask db current # Vedi migrazione corrente
🔗 Dominio Personalizzato e SSL
Railway/Render forniscono URL tipo tuoapp.railway.app, ma puoi usare il tuo dominio.
1. Vai su Settings del tuo progetto 2. Click "Domains" 3. Aggiungi il tuo dominio (es: app.tuonome.com) 4. Railway mostrerà record DNS da aggiungere 5. Vai dal tuo registrar di dominio (es: GoDaddy, Namecheap) 6. Aggiungi i record CNAME/A forniti 7. Attendi propagazione DNS (fino a 48h)
Railway/Render forniscono SSL automatico con Let’s Encrypt.
🔐 Perché SSL è Obbligatorio?
- Sicurezza: Crittografa dati tra browser e server
- SEO: Google penalizza siti senza HTTPS
- Credibilità: Mostra il lucchetto verde nel browser
- Modernità: Browser segnalano siti HTTP come “non sicuri”
📊 Monitoring e Logs in Produzione
import logging
from logging.handlers import RotatingFileHandler
import os
def setup_logging(app):
if not app.debug:
# Crea directory logs se non esiste
if not os.path.exists('logs'):
os.mkdir('logs')
# File handler con rotazione
file_handler = RotatingFileHandler(
'logs/flask_app.log',
maxBytes=10240,
backupCount=10
)
file_handler.setFormatter(logging.Formatter(
'%(asctime)s %(levelname)s: %(message)s [in %(pathname)s:%(lineno)d]'
))
file_handler.setLevel(logging.INFO)
app.logger.addHandler(file_handler)
app.logger.setLevel(logging.INFO)
app.logger.info('Flask app startup')
# Nel create_app()
setup_logging(app)
| Strumento | Scopo | Costo |
|---|---|---|
| UptimeRobot | Monitora se il sito è online | Gratis |
| Google Analytics | Traffico e utenti | Gratis |
| Railway/Render Dashboard | Logs, performance, errori | Incluso |
| Sentry | Error tracking in tempo reale | Piano gratuito |
| New Relic | Performance monitoring | Piano gratuito |
✅ Checklist Pre-Deployment
🔍 Controlla Ogni Punto Prima di Deployare!
📦 Configurazione
-
requirements.txtaggiornato -
Procfilepresente -
.envNON commitato (in .gitignore) -
DEBUG = Falsein produzione - Database configurato (PostgreSQL)
🛡️ Sicurezza
-
SECRET_KEYcomplessa - Password hashate con bcrypt
- CSRF protection attiva
- HTTPS/SSL configurato
- Input validation attiva
🚀 Performance
- Gunicorn configurato
- Static files serviti correttamente
- Database indicizzato
- Cache configurata (se necessaria)
- CDN per static files (opzionale)
🔧 Manutenzione
- Backup database configurato
- Logging attivo
- Error pages personalizzate
- Monitoraggio configurato
- README.md aggiornato
🔧 Troubleshooting Comuni
# Controlla logs su Railway/Render Error: No module named 'flask' → requirements.txt mancante o incompleto Error: Address already in use → Porta già occupata, cambia PORT in variabili Error: ImportError → Controlla i percorsi degli import Application error → Controlla logs per dettagli specifici
OperationalError: could not connect to server → DATABASE_URL non configurata o errata ProgrammingError: relation does not exist → Migrazioni non applicate: flask db upgrade InterfaceError: connection already closed → Timeout connessione, controlla pool size psycopg2.OperationalError → Database non esiste o credenziali errate
# In produzione, Flask non serve static files # Configura web server o usa CDN # Soluzione 1: Usa whitenoise pip install whitenoise # In app.py from whitenoise import WhiteNoise app.wsgi_app = WhiteNoise(app.wsgi_app, root='static/') # Soluzione 2: Configura nginx/apache # Soluzione 3: Usa CDN (Cloudflare, AWS CloudFront)
🏆 Progetto Finale: Blog Completo
Metti insieme tutto ciò che hai imparato e deploya un blog completo!
- Frontend: Templates con Bootstrap 5
- Autenticazione: Registrazione, Login, Logout
- CRUD Articoli: Create, Read, Update, Delete
- Commenti: Sistema commenti per articoli
- Admin Panel: Gestione contenuti
- Search: Ricerca articoli
- API REST: Endpoint per app mobile
# Modelli principali User (id, username, email, password_hash, is_admin) Post (id, title, content, created_at, user_id) Comment (id, content, created_at, user_id, post_id) Category (id, name) Tag (id, name) # Relazioni User 1→N Post User 1→N Comment Post 1→N Comment Post N→N Category Post N→N Tag
- Sviluppa localmente il blog
- Testa tutto localmente
- Crea repository GitHub
- Prepara requirements.txt, Procfile, .env
- Deploy su Railway o Render
- Configura dominio e SSL
- Testa in produzione
- Condividi il link con amici/colleghi!
Complimenti! 🎉
Hai completato con successo il corso completo di Flask! Ora possiedi tutte le competenze per costruire e pubblicare applicazioni web professionali.
📚 Riassunto del Percorso
Fondamenti
Route & URL
Templates
File Statici
Form & Input
Database
Sicurezza
Deployment
🎯 Prossimi Passi
💼 Portfolio
Crea 2-3 progetti completi e pubblicali online
🤝 Contribuisci
Partecipa a progetti open source su GitHub
📈 Avanzato
Impara Docker, CI/CD, Testing, APIs RESTful
“Il viaggio di mille miglia comincia con un singolo passo.”
Ora il tuo viaggio come sviluppatore Flask è iniziato! 🚀
Hai domande o bisogno di aiuto? Cerca su Stack Overflow o unisciti a comunità Flask su Discord/Reddit!
© 2024 Corso Completo Flask – Tutti i diritti riservati