Introduzione
Docker è una piattaforma di container open-source. Si tratta di un ambiente standardizzato leggero, virtualizzato, portatile e definito dal software che consente al software di essere eseguito in isolamento rispetto ad altri software in esecuzione sulla macchina host fisica. Docker offre un'alternativa leggera alle macchine virtuali. Allo stesso tempo, offre portabilità, prestazioni, agilità e scalabilità delle applicazioni. Per una panoramica guida completa sull'ecosistema Docker, dai un'occhiata alla nostra panoramica dettagliata sulla containerizzazione con Docker.
Flask è un micro-framework web open-source realizzato con Python. Alcune delle straordinarie caratteristiche di Flask sono la sua leggerezza, flessibilità e l'essere altamente strutturato. Inoltre, non richiede strumenti o plug-in specifici per essere eseguito.
La combinazione di Flask e Docker offre un'applicazione leggera, flessibile e scalabile. È possibile distribuirla su molti server e infrastrutture, grazie alla natura portatile dei container Dockerizzati. L'obiettivo di questo tutorial è mostrarti come distribuire un'applicazione Flask con Docker. Dimostreremo anche come assicurarsi che i futuri aggiornamenti dell'applicazione abbiano effetto.
Prerequisiti
Questo sarà un tutorial pratico, e dovresti creare un ambiente che ti consenta di seguirlo:
- Dovresti avere un' installazione di Ubuntu 20.04 come ambiente operativo iniziale. È inoltre necessario creare un utente non-root con privilegi sudo.
- Inoltre, è necessario installare Docker. Abbiamo un tutorial su come installare e utilizzare Docker su Ubuntu. Segui i passaggi 1, 2, 3 e 4. Questo dovrebbe funzionare per qualsiasi distribuzione Ubuntu.
- Infine, è necessario avere Nginx installato. Segui il nostro tutorial su come installare Nginx su Ubuntu.
Ora iniziamo!
Passo 1: Preparare l'applicazione Flask
Inizieremo creando una directory che conterrà la nostra applicazione Flask. Puoi scegliere un nome di directory a tua scelta. Tuttavia, per questo tutorial, la chiameremo flask_demo. Salveremo i file del progetto all'interno della directory /var/www, che di solito è la directory a cui Ubuntu consente l'accesso a Internet pubblico per impostazione predefinita. Per prima cosa, esegui i seguenti comandi per creare la directory ed entrarci:
|
1 2 3 |
sudo mkdir /var/www/flask_demo cd /var/www/flask_demo |
All'interno di questa directory radice del nostro progetto, creeremo la struttura delle cartelle di base di un'applicazione Flask. Successivamente, esegui il seguente comando per creare la struttura di base, aggiungendo il flag -p per creare tutte le cartelle principali lungo il percorso:
|
1 |
sudo mkdir -p app/static app/templates |
La cartella app contiene tutti i file relativi a un'app Flask, inclusi views e blueprints. Le views contengono il codice scritto per rispondere alle richieste che arrivano all'applicazione. I blueprints aiutano a creare componenti dell'applicazione e supportano pattern comuni nelle applicazioni Flask.
La cartella opportunamente denominata static contiene risorse statiche come immagini, file CSS e JavaScript. La directory templates contiene tutti i template HTML per il progetto.
Ora possiamo iniziare a scrivere i file necessari per inizializzare un'applicazione Flask. Inizia creando un file chiamato __init__.py all'interno della directory app per dire all' Python interprete che la directory app deve essere trattata come un pacchetto. Esegui il seguente comando sul tuo terminale per aprire il file con l'editor nano:
|
1 |
sudo nano app/__init__.py |
In Python utilizziamo i pacchetti per raggruppare i moduli in namespace o gerarchie logiche. La modularizzazione consente di suddividere il codice in blocchi singoli e gestibili che eseguono funzioni definite.
Dopodiché, all'interno del file __init__.py aperto nel tuo editor, aggiungi il seguente frammento di codice per avviare l'istanza di Flask e importare la logica da views.py che creerai nei passaggi successivi:
|
1 2 3 4 5 |
from flask import Flask app = Flask(__name__) from app import views |
Al termine, premi Ctrl + O e ENTER per salvare il file, quindi chiuderlo con Ctrl + X. Successivamente, creiamo il file views.py all'interno della directory app . Il file views.py conterrà la maggior parte della logica dell'applicazione:
|
1 |
sudo nano app/views.py |
All'interno del file, aggiungi il seguente frammento di codice. Questo codice mostrerà una semplice stringa per indicare che l'app è in esecuzione quando gli utenti visitano il tuo sito web:
|
1 2 3 4 5 |
from app import app @app.route('/') def home(): return "La nostra applicazione Flask è in esecuzione!" |
In questo file, iniziamo importando l'istanza dell'app Flask. Successivamente, dobbiamo aggiungere una riga per definire la rotta: @app.route(/). La riga @app.route(/) viene definita decoratore in Flask. Puoi utilizzare i decoratori per inserire funzionalità aggiuntive in una o più funzioni. In questo caso, stiamo passando una chiamata alla rotta / alla funzione home. Quando un utente visita questa rotta, vedrà il testo: "La nostra applicazione Flask è in esecuzione!".
Successivamente, creerai il file uwsgi.ini per contenere le configurazioni uWSGI per l'applicazione. uWSGI è un'opzione di distribuzione per Nginx che funge da protocollo e server applicativo. Esegui il comando seguente per creare il file nella directory principale del progetto con l'editor nano:
|
1 |
sudo nano uwsgi.ini |
All'interno del file aperto, aggiungi il seguente frammento di codice:
|
1 2 3 4 |
[uwsgi] module = main callable = app master = true |
Questo file contiene alcune direttive. Ne definiamo lo scopo di seguito:
- module – definisce il modulo da cui verrà servita l'applicazione Flask. Abbiamo impostato il modulo come main, facendo riferimento al file main.py nella directory principale. Creeremo questo file nel passaggio successivo.
- callable – indica a uWSGI di utilizzare l'istanza app esportata dall'applicazione.
- master – garantisce che l'applicazione continui a funzionare per ridurre al minimo i tempi di inattività durante il ricaricamento dell'intera applicazione.
Salva e chiudi il file quando hai finito.
Ora puoi creare il file main.py per determinare il punto di ingresso della tua applicazione. uWSGI leggerà questo file per sapere come interagire con l'applicazione. Esegui il comando seguente per creare il file main.py con nano all'interno della root directory del tuo progetto:
|
1 |
sudo nano main.py |
All'interno del file, aggiungi la seguente riga che importerà l'istanza Flask creata nel pacchetto dell'applicazione:
|
1 |
from app import app |
L'ultima cosa che farai in questo passaggio è definire le dipendenze necessarie per l'esecuzione dell'applicazione. Definiremo queste dipendenze all'interno di un file chiamato dependencies.txt. Quando Docker compila l'immagine della tua applicazione, eseguirà un comando del pip (package manager) per installare le dipendenze. Apri il file nella directory principale con il seguente comando:
|
1 |
sudo nano dependencies.txt |
Fino a questo punto del nostro progetto, vogliamo solo una dipendenza: Flask. Pertanto, possiamo aggiungere la riga seguente per fare riferimento alla versione corretta di Flask che desideriamo per il nostro progetto:
|
1 |
Flask==2.0.1 |
Scegliamo la Flask version 2.0.1 come dipendenza. È l'ultima versione al momento della stesura di questo tutorial. Puoi trovare maggiori informazioni sulle varie versioni nella pagina Flask Changes . Questo completa la configurazione dell'applicazione Flask. Ora prepariamo le configurazioni di Docker per la distribuzione.
Step 2: Configure Docker
Per configurare una distribuzione Docker, creeremo due file, Dockerfile e start.sh. Il file Dockerfile contiene righe dichiarative che compongono un'immagine Docker. Il file start.sh è uno script di shell di base per compilare l'immagine e avviare il contenitore dal Dockerfile. Trovandoti all'interno della directory principale del progetto, esegui il comando seguente per creare il Dockerfile:
|
1 |
sudo nano Dockerfile |
Questo file contiene le configurazioni necessarie per un'immagine Docker. Successivamente, aggiungi il seguente frammento di codice per specificare le dipendenze e come compilare l'immagine:
|
1 2 3 4 5 6 7 8 9 10 11 |
FROM tiangolo/uwsgi-nginx-flask:python3.6-alpine3.7 RUN apk --update add bash nano git ENV STATIC_URL /static ENV STATIC_PATH /var/www/app/static COPY ./dependencies.txt /var/www/dependencies.txt RUN pip install -r /var/www/dependencies.txt |
La prima riga in un Dockerfile definisce l'immagine di base a partire dalla quale stiamo creando la nostra immagine. In questo caso, la creazione si baserà su tiangolo/uwsgi-nginx-flask, disponibile su DockerHub. Abbiamo scelto questa particolare immagine perché supporta molte versioni di Python.
Specifichiamo anche che vogliamo aggiornare l'immagine. Successivamente, dobbiamo aggiungere il bash comando processo , l' nano testo editor, e il git client per eseguire il pull e il push del codice sorgente da repository di controllo versione come GitHub, Bitbucket, o Gitlab. Le righe con ENV specificano le variabili d'ambiente da utilizzare nel container.
Il comando COPY copia le dipendenze nel container. Il comando RUN richiama il pip gestore di pacchetti per analizzare il file dependencies.txt e installare le dipendenze. Salva e chiudi il file quando hai finito di modificarlo.
Successivamente, creerai lo script start.sh. Questo script includerà i comandi Docker per creare e avviare l'immagine. Sebbene sia possibile eseguire questi comandi progressivamente sul terminale, abbiamo pensato che fosse più pulito aggiungerli a uno script di shell e richiamarlo semplicemente dal terminale con un solo comando.
Prima di poter definire il contenuto di questo file, dobbiamo prima stabilire una porta libera che altri servizi non stiano utilizzando. Utilizzeremo la porta 45644. Tuttavia, puoi scegliere una porta diversa. Esegui la riga seguente per verificare se la porta è libera:
|
1 |
sudo nc localhost 45644 < /dev/null; echo $? |
A seconda della porta scelta, se l'output del comando precedente è 1, allora è libera. In caso contrario, potresti dover scegliere un'altra porta e riprovare il comando:

Poiché abbiamo stabilito una porta libera, ora possiamo creare il file con nano all'interno della directory principale del progetto eseguendo il seguente comando:
|
1 |
sudo nano start.sh |
All'interno di questo file, aggiungi il seguente frammento di codice:
|
1 2 3 4 5 6 7 |
#!/bin/bash app_name="docker-flask-demo" docker build -t ${app_name} . docker run -d -p 45644:80 --name=${app_name} -v $PWD:/app ${app_name} |
La prima riga, denominata shebang, specifica che si tratta di un file bash e che dovrebbe essere eseguito come comandi. La seconda riga dichiara una variabile chiamata app_name. Utilizziamo questa variabile per impostare i nomi dell'immagine e del container. La terza riga indica a Docker di creare l'immagine in base alla definizione del Dockerfile nella directory corrente. L'immagine si chiamerà docker-flask-demo come da variabile.
L'ultima riga crea un container chiamato docker-flask-demo come da variabile che abbiamo definito. Il flag -d mantiene il container in esecuzione in background in uno stato scollegato (detached) al termine dell'esecuzione del comando. Il flag -p associa una porta sul server a una porta specifica sul container. In questo caso, stiamo mappando la porta 45644 sulla macchina host alla porta 80 che Docker esporrà nel container.
Utilizziamo il flag -v per specificare un volume Docker da montare sul container. La variabile $PWD è una variabile Linux predefinita che contiene il percorso della directory corrente in cui ti trovi in un determinato momento:

Nel nostro caso, stiamo montando l'intera directory del progetto nella directory /var/www del container. La configurazione di Docker è ora pronta. Puoi creare l'immagine e avviare il container in base all'immagine creata eseguendo il seguente comando:
|
1 |
sudo bash start.sh |
Attendi che lo script termini l'esecuzione, quindi esegui il seguente comando Docker per elencare tutti i container in esecuzione:
|
1 |
sudo docker ps |
L'output mostrerà i container in esecuzione:

Dovresti vedere il nostro container con il nome docker-flask-demo nell'elenco dei container in esecuzione. Trova l'IP pubblico IP del tuo server e accedi ad esso nel tuo browser alla porta specificata: http://your-server-public-ip:45644.
Dovresti vedere un output simile:

Se vedi quanto sopra nel tuo browser, significa che hai distribuito con successo un'applicazione Flask. Successivamente, modificheremo i file e forniremo contenuti agli utenti tramite i template.
Passo 3: Fornire contenuti tramite file di template
In Flask, i template vengono utilizzati per mostrare contenuti statici e dinamici ai visitatori del sito web. Ti mostreremo come creare un template HTML e fornirlo ai tuoi utenti quando visitano una determinata rotta. Ad esempio, questa può essere una pagina Home o una pagina Informazioni.
Esegui il seguente comando sul tuo terminale per creare un file index.html nella directory app/templates :
|
1 |
sudo nano app/templates/index.html |
Quindi, aggiungi il seguente frammento di codice al file:
|
1 2 3 4 5 6 7 8 9 10 11 12 |
<!DOCTYPE html> <html lang="it"> <head> <meta charset="UTF-8"> <title>Demo Flask</title> </head> <body> <h2>Sei nella Home</h2> <p>Benvenuto sulla pagina demo di Flask con Docker</p> </body> </html> |
Salva e chiudi il file quando hai finito. Inoltre, crea un'altra pagina, chiamiamola pagina Informazioni, con il seguente comando:
|
1 |
sudo nano app/templates/about.html |
Aggiungi il seguente frammento di codice al file:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 |
<!DOCTYPE html> <html lang="it"> <head> <meta charset="UTF-8"> <title>Informazioni su Demo Flask</title> </head> <body> <h2>Pagina Informazioni</h2> <p>Questo era un progetto demo. . Mostra come costruire un' app Flask con Docker e Docker and Nginx.</p> <p>Puoi aggiungere tutte le pagine e i file che desiderilike</p> </body> </html> |
Salva e chiudi il file quando hai finito. Successivamente, modifica il file app/views.py per fare riferimento ai template e alle rotte per le pagine effettive:
|
1 |
sudo nano app/views.py |
Modifica il file in modo che si presenti così:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
from flask import render_template from app import app @app.route('/') def home(): return "La nostra applicazione Flask è in esecuzione!" @app.route('/index') def index(): return render_template('index.html') @app.route('/about') def about(): return render_template('about.html') |
Salva e chiudi il file quando hai finito. Le modifiche apportate non avranno effetto finché non arresti e riavvii il container. Esegui i seguenti comandi Docker per arrestare e avviare il container. Prendi nota del nome del container come definito in precedenza:
|
1 |
sudo docker stop docker-flask-demo && sudo docker start docker-flask-demo |
Una volta che il container è attivo e funzionante, visita la pagina Home e la pagina About per vedere alcuni dei nuovi contenuti:
|
1 |
Home page: http://your-server-public-ip:45644/index |

|
1 |
Informazioni page: http://your-server-public-ip:45644/about |

Finora hai creato un'applicazione Flask in grado di fornire contenuti ai visitatori del tuo sito web. Ecco la struttura dei file del progetto:

Probabilmente avrai notato che abbiamo dovuto riavviare il container Docker per fargli recepire le nuove modifiche. Nel prossimo passaggio, automatizzeremo questo processo per garantire tempi di inattività ridotti.
Passaggio 4: Configurare gli aggiornamenti dei file dell'applicazione per il ricaricamento automatico
Spesso apportiamo modifiche a un'applicazione, per migliorarne la logica, le interfacce utente o aggiungere alcune dipendenze. Affinché tali modifiche abbiano effetto, potrebbe essere necessario riavviare il container Docker. Fortunatamente, uWSGI ha una funzionalità chiamata touch-reload per ricaricare uno script Python senza riavviare il container.
Pronto all'uso, Python ha una funzionalità di auto--ricaricamento che monitora l'intero file system alla ricerca di modifiche e aggiorna l'applicazione quando si verifica una modifica. Sebbene il ricaricamento automatico sia utile per ridurre al minimo i tempi di inattività, può richiedere molte risorse. Pertanto, non è consigliato per gli ambienti di produzione.
Vediamo come puoi utilizzare touch-reload per monitorare le modifiche a un file specifico e ricaricare l'applicazione quando ci sono modifiche. Modifica il file uwsgi.ini con l'editor nano:
|
1 |
sudo nano uwsgi.ini |
Aggiungi la riga evidenziata in modo che appaia così:
|
1 2 3 4 5 |
[uwsgi] module = main callable = app master = true touch-reload = /app/uwsgi.ini |
Salva e chiudi il file quando hai finito. La riga aggiunta ha specificato un file che verrà modificato per attivare il ricaricamento dell'applicazione. Tuttavia, affinché questa condizione venga attivata per le modifiche future, devi prima riavviare il container:
|
1 |
sudo docker stop docker-flask-demo && sudo docker start docker-flask-demo |
Ora puoi modificare il file app/views.py per dimostrare come funziona il ricaricamento automatico:
|
1 |
sudo nano app/views.py |
Modifica la stringa restituita dalla funzione home come evidenziato:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
from flask import render_template from app import app @app.route('/') def home(): return "<h3>Alcune modifiche alla nostra applicazione Flask per il ricaricamento automatico!</h3>" @app.route('/index') def index(): return render_template('index.html') @app.route('/about') def about(): return render_template('about.html') |
Salva e chiudi il file una volta terminato.
Apri la home page della tua applicazione nel browser: http://your-server-public-ip:45644.
Non vedrai ancora alcuna modifica. Questo perché la condizione touch-reload rileva una modifica al file uwsgi.ini . Puoi usare touch per attivare la condizione, ricaricando così l'intera applicazione con il seguente comando:
|
1 |
sudo touch uwsgi.ini |
Ora, se ricarichi la home page, troverai visualizzate le nuove modifiche:

In futuro, se apporterai ulteriori modifiche, dovrai solo eseguire il comando sudo touch uwsgi.ini e l'intera applicazione si ricaricherà con tempi di inattività ridotti. Questo ci porta alla fine di questo tutorial.
Conclusione
In questo tutorial, hai implementato e distribuito un'applicazione Flask con immagini e container Docker. Per ridurre al minimo i tempi di inattività evitando la necessità di riavviare il container, hai configurato touch-reload per ascoltare le modifiche a un file particolare e ricaricare automaticamente l'intera applicazione. Infine, hai testato tutto questo nel browser per assicurarti che funzioni.
Docker garantisce distribuzioni più rapide e consente una facile scalabilità delle applicazioni. Se desideri saperne di più sui vari comandi Docker, dai un'occhiata a questo tutorial su come installare e utilizzare Docker su Ubuntu.
Per ulteriori risorse su Docker sul nostro blog, puoi consultare i seguenti:
- Tecnologia di containerizzazione: tipi e utilizzi di diversi container sulla piattaforma PaaS di CloudSigma
- Come condividere dati tra un container Docker e un host
- Installazione e configurazione di Docker su CentOS 7
- Distribuzione di Laravel, Nginx e MySQL con Docker Compose
- Pulizia delle risorse Docker – Immagini, container e volumi
Buona programmazione!
Commenti
Ancora nessun commento. Scrivi il primo.