Introduzione
Docker è una piattaforma di containerizzazione che costituisce un ambiente standardizzato leggero, virtualizzato, portabile e definito dal software. Consente al software di essere eseguito in isolamento rispetto ad altri software in esecuzione sulla macchina host fisica. Docker è un componente fondamentale dell'aspetto di Continuous Development e Integration dello sviluppo software. Offre un'alternativa leggera alle macchine virtuali e consente agli sviluppatori di sfruttare architetture applicative distribuite. Per una panoramica approfondita dell'ecosistema Docker, consulta questo articolo.
Il processo di creazione di un'applicazione con Docker inizia con uno sviluppatore che crea un'immagine per la propria applicazione. Successivamente, l'immagine verrà distribuita all'interno di un container. L'immagine contiene i componenti che definiscono un'applicazione, come il codice dell'applicazione, le librerie, i file di configurazione, le variabili d'ambiente e l'ambiente di runtime. L'immagine standardizza l'ambiente all'interno di un container, conferendo alla containerizzazione le sue caratteristiche di portabilità. Node.js è un ambiente di runtime JavaScript backend open-source e multipiattaforma in grado di eseguire codice JavaScript al di fuori di un browser web. È basato sul motore V8 JavaScript Engine. Express.js è un framework JavaScript backend minimalista che viene eseguito sopra Node.js.
In questo tutorial, creeremo un'immagine per un sito web basato sul framework Express. Utilizzeremo Bootstrap, che è una libreria frontend, per migliorare l'aspetto del frontend. Una volta creata l'immagine, creeremo un container e lo invieremo a Docker Hub. Docker Hub consente agli sviluppatori di ospitare applicazioni containerizzate per una facile distribuzione in qualsiasi ambiente Docker. Una volta che il container sarà ospitato su Docker Hub, lo scaricheremo (pull) e creeremo un'altra immagine che servirà effettivamente il nostro sito web.
Prerequisiti
Questo sarà un tutorial pratico. Dovresti creare un ambiente che ti consenta di seguire i passaggi.
- Dovresti avere un'installazione di Ubuntu 20.04 come ambiente operativo iniziale e creare un utente non root con privilegi sudo. Accedi con l'utente non root e procedi con i passaggi seguenti.
- Devi installare Docker. Segui i passaggi 1, 2, 3 e 4 del nostro tutorial su come installare e utilizzare Docker su Ubuntu. Questo dovrebbe funzionare per qualsiasi distribuzione Ubuntu.
- Crea un account Docker Hub se non ne hai già uno. Puoi seguire questo link per la Guida rapida di Docker Hub.
- Installa Node.js and NPM. NPM è un gestore di pacchetti JavaScript. Puoi seguire queste istruzioni sull'installazione di Node e npm.
Passo 1: Configurare le dipendenze dell'applicazione
Devi creare il codice sorgente della tua applicazione prima di poter creare l'immagine. Il codice sorgente dell'applicazione include codice, contenuti statici e dipendenze che verranno copiati nel container. Inizia creando una directory per il tuo progetto nella home directory dell'utente non root. La chiameremo node_express, ma sei libero di usare il nome di directory che preferisci:
|
1 |
mkdir node_express |
Successivamente, spostati in questa directory:
|
1 |
cd node_express |
Questa sarà la directory radice della tua applicazione. Un'applicazione node.js si aspetta un file package.json nella cartella radice. Npm utilizza questo file per determinare di quali dipendenze ha bisogno la tua applicazione. Inserisci il seguente comando per creare questo file:
|
1 |
nano package.json |
Successivamente, aggiungi il seguente frammento di codice al file. Puoi aggiornare il nome, l'autore, la descrizione e il file del punto di ingresso come desideri:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
{ "name": "node-express-docker-image", "version": "1.0.0", "description": "Esempio di immagine Docker Nodejs Express", "author": "hackins", "main": "index.js", "license": "ISC", "keywords": [ "nodejs", "express", "bootstrap" ], "dependencies": { "express": "^4.17.1" } } |
Come puoi vedere, questo file specifica il nome del progetto, la versione, l'autore e la licenza con cui verrà condiviso il codice dell'applicazione. Si consiglia di utilizzare un nome breve e descrittivo per il progetto per evitare duplicati nel registro npm. Abbiamo specificato la licenza ISC per il progetto, che consente la copia, la modifica o la distribuzione gratuita del codice dell'applicazione.
Ancora più importante, dovresti notare le seguenti direttive nel file:
- “
main”: questa direttiva specifica il punto di ingresso dell'applicazione, che abbiamo impostato come index.js. Creeremo questo file a breve. - “
dependencies”: questa direttiva specifica le dipendenze dell'applicazione che verranno scaricate dal registro npm quando eseguiamo il comandonpm, nel nostro caso, vogliamo Express versione 4.17.1 e successive.
Ora puoi salvare il file premendo Ctrl + O. Quindi, chiudi il file premendo Ctrl + X. Successivamente, installeremo le dipendenze eseguendo il seguente comando:
|
1 |
npm install |
Il comando installa le dipendenze dell'applicazione specificate nel file package.json all'interno delle directory node_modules. Sono state create automaticamente la prima volta che hai eseguito il comando. Con le dipendenze della nostra applicazione installate, ora puoi iniziare ad aggiungere il codice dell'applicazione.
Passo 2: Aggiunta dei file di codice dell'applicazione
Creeremo un sito web di ricette di base, per gentile concessione di allrecipes. Il punto di ingresso principale per l'applicazione è il file index.js. Aggiungeremo una directory views che conterrà le varie pagine e gli asset statici del progetto. Il sito web avrà una landing page che conterrà informazioni introduttive e link ad alcune ricette.
Il codice della nostra landing page sarà inserito nel file home.html. Per prima cosa, crea il file index.js inserendo il seguente comando:
|
1 |
nano index.js |
Aggiungi il seguente codice, che importa e crea un'applicazione Express. Specifica anche l'oggetto Router, la directory di base e la porta su cui verrà servita questa app:
|
1 2 3 4 5 6 |
const express = require('express'); const app = express(); const router = express.Router(); const path = __dirname + '/views/'; const port = 8090; |
require è una funzione JavaScript che carica un modulo. In questo caso, stiamo caricando il modulo express. Successivamente, utilizzeremo il modulo importato per creare gli oggetti express e router. L'oggetto router esegue le funzioni di routing dell'app rispondendo alle chiamate dei metodi HTTP che aggiungeremo a questo oggetto man mano che procediamo con il tutorial.
Abbiamo anche impostato path e port. La costante path definisce la directory di base per il codice. Nel nostro caso è la sottodirectory views all'interno della directory principale del progetto. La costante port specifica la porta su cui l'app express deve rimanere in ascolto, nel nostro esempio l'abbiamo impostata su 8090.
Una volta ottenute le costanti, possiamo specificare alcune rotte per l'applicazione utilizzando l'oggetto router. Aggiungi il seguente codice al file index.js per specificare le rotte:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
router.use(function (req,res,next) { console.log('/' + req.method); next(); }); router.get('/', function(req,res){ res.sendFile(path + 'home.html'); }); router.get('/lasagna', function(req,res){ res.sendFile(path + 'lasagna.html'); }); router.get('/guacamole', function(req,res){ res.sendFile(path + 'guacamole.html'); }); router.get('/banana-bread', function(req,res){ res.sendFile(path + 'banana_bread.html'); }); |
Puoi aggiungere middleware alle rotte utilizzando la funzione router.use. In questo caso, aggiungiamo una funzione che registra le richieste del router prima di passarle alle rotte dell'applicazione. Una richiesta GET alla base dell'applicazione restituirà un file home.html pagina. Successivamente, abbiamo aggiunto le pagine per tre ricette che verranno anch'esse recuperate utilizzando la richiesta GET alla pagina della ricetta specifica.
Infine, aggiungi il seguente codice per montare il router middleware e gli asset statici dell'applicazione. Inoltre, indica all'applicazione express di rimanere in ascolto sulla porta 8090:
|
1 2 3 4 5 6 |
app.use(express.static(path)); app.use('/', router); app.listen(port, function () { console.log('Nodejs Express Example App in ascolto sulla porta ' + port) }) |
Il tuo file index.js completo dovrebbe apparire così:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
const express = require('express'); const app = express(); const router = express.Router(); const path = __dirname + '/views/'; const port = 8090; router.use(function (req,res,next) { console.log('/' + req.method); next(); }); router.get('/', function(req,res){ res.sendFile(path + 'home.html'); }); router.get('/lasagna', function(req,res){ res.sendFile(path + 'lasagna.html'); }); router.get('/guacamole', function(req,res){ res.sendFile(path + 'guacamole.html'); }); router.get('/banana-bread', function(req,res){ res.sendFile(path + 'banana_bread.html'); }); app.use(express.static(path)); app.use('/', router); app.listen(port, function () { console.log('Nodejs Express Example App in ascolto sulla porta ' + port) }) |
Ora puoi salvare e chiudere il file. Il passo successivo consiste nell'aggiungere le pagine web statiche alla directory views. Inizia inserendo il seguente comando per creare la directory:
|
1 |
mkdir views |
Inserisci il seguente comando per aprire il file della pagina di destinazione home.html:
|
1 |
nano views/home.html |
Aggiungi il seguente codice al file. Il codice importa Bootstrap e offre ai visitatori del sito web alcune informazioni sullo scopo del sito:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 |
<!DOCTYPE html> <html lang="it"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <meta name="description" content=""> <meta name="author" content="Mark Otto, Jacob Thornton e i collaboratori di Bootstrap"> <meta name="generator" content="Hugo 0.80.0"> <title>Ricette fantastiche</title> <!-- CSS principale di Bootstrap --> <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta2/dist/css/bootstrap.min.css" rel="stylesheet" crossorigin="anonymous"> <link href="css/custom.css" rel="stylesheet"> </head> <body> <nav class="navbar navbar-dark bg-dark navbar-static-top navbar-expand-md"> <div class="container"> <button type="button" class="navbar-toggler collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1" aria-expanded="false"> <span class="sr-only">Attiva/disattiva navigazione</span> </button> <a class="navbar-brand" href="#">Ricette fantastiche</a> <div class="collapse navbar-collapse justify-content-center" id="bs-example-navbar-collapse-1"> <ul class="nav navbar-nav justify-content-center"> <li class="active nav-item"> <a href="/" class="nav-link">Home</a> </li> <li class="nav-item"> <a href="/lasagna" class="nav-link">Lasagne</a> </li> <li class="nav-item"> <a href="/guacamole" class="nav-link">Guacamole</a> </li> <li class="nav-item"> <a href="/banana-bread" class="nav-link">Banana Bread</a> </li> </ul> </div> </div> </nav> <main> <section class="py-5 text-center container"> <div class="row py-lg-5"> <div class="col-lg-6 col-md-8 mx-auto"> <h1 class="fw-light">Ricetta fantastica</h1> <p class="lead text-muted"> Trova e condividi l'ispirazione culinaria di tutti i giorni da queste fantastiche ricette. Scopri ricette, cuochi, video e guide pratiche basate sul cibo che ami e sugli amici che segui. <br /> <em>(Nulla di serio, questo serve solo per la nostra app demo con immagine node-express-docker)</em> </p> </div> </div> </section> </main> </body> </html> |
Oltre a importare Bootstrap, la pagina aggiunge anche un semplice menu di navigazione per aiutarci a spostarci tra le pagine e tornare alla pagina di destinazione. Abbiamo anche aggiunto una riga per importare il nostro file CSS personalizzato:
|
1 |
<link href="css/custom.css" rel="stylesheet"> |
Useremo questo file per aggiungere uno stile personalizzato all'applicazione in seguito. Ora creiamo le tre pagine per le ricette. Iniziamo creando la pagina della lasagna. Apri il file con l'editor nano usando il seguente comando:
|
1 |
nano views/lasagna.html |
Nel file aperto, aggiungi il seguente codice. Questo file importerà Bootstrap, il file custom.css, specificherà un menu di navigazione e offrirà alcune informazioni sulla ricetta delle lasagne:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 |
<!DOCTYPE html> <html lang="it"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <meta name="description" content=""> <meta name="author" content="Mark Otto, Jacob Thornton e i collaboratori di Bootstrap"> <meta name="generator" content="Hugo 0.80.0"> <title>Ricetta delle lasagne</title> <!-- CSS principale di Bootstrap --> <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta2/dist/css/bootstrap.min.css" rel="stylesheet" crossorigin="anonymous"> <link href="css/custom.css" rel="stylesheet"> </head> <body> <nav class="navbar navbar-dark bg-dark navbar-static-top navbar-expand-md"> <div class="container"> <button type="button" class="navbar-toggler collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1" aria-expanded="false"> <span class="sr-only">Attiva/disattiva navigazione</span> </button> <a class="navbar-brand" href="#">Ricette fantastiche</a> <div class="collapse navbar-collapse justify-content-center" id="bs-example-navbar-collapse-1"> <ul class="nav navbar-nav justify-content-center"> <li class="active nav-item"> <a href="/" class="nav-link">Home</a> </li> <li class="nav-item"> <a href="/lasagna" class="nav-link">Lasagne</a> </li> <li class="nav-item"> <a href="/guacamole" class="nav-link">Guacamole</a> </li> <li class="nav-item"> <a href="/banana-bread" class="nav-link">Banana Bread</a> </li> </ul> </div> </div> </nav> <main> <section class="py-5 text-center container bg-light"> <div class="row py-lg-5"> <div class="col-lg-6 col-md-8 mx-auto"> <h1 class="fw-light">La migliore ricetta delle lasagne</h1> <p class="lead text-muted"> Queste sono le migliori lasagne che preparerai mai. <br /> <em>(Nulla di serio, questo serve solo per la nostra app demo con immagine node-express-docker)</em> </p> <h3>Ingredienti</h3> <ul class="list-group"> <li class="list-group-item">1 libbra di salsiccia italiana dolce</li> <li class="list-group-item">¾ di libbra di carne macinata di manzo magra</li> <li class="list-group-item">½ tazza di cipolla tritata</li> <li class="list-group-item">2 spicchi d'aglio schiacciati</li> <li class="list-group-item">1 lattina (da 28 once) di pomodori pelati schiacciati</li> <li class="list-group-item">2 lattine (da 6 once) di concentrato di pomodoro</li> <li class="list-group-item">2 lattine (da 6,5 once) di salsa di pomodoro in scatola</li> <li class="list-group-item">½ tazza d'acqua</li> <li class="list-group-item">2 cucchiai di zucchero bianco</li> <li class="list-group-item">1 ½ cucchiaini di foglie di basilico essiccate</li> <li class="list-group-item">½ cucchiaino di semi di finocchio</li> <li class="list-group-item">1 cucchiaino di condimento italiano</li> <li class="list-group-item">1 ½ cucchiaini di sale, divisi, o a piacere</li> <li class="list-group-item">¼ di cucchiaino di pepe nero macinato</li> <li class="list-group-item">4 cucchiai di prezzemolo fresco tritato</li> <li class="list-group-item">12 sfoglie per lasagne</li> <li class="list-group-item">16 once di ricotta</li> <li class="list-group-item">1 uovo</li> <li class="list-group-item">¾ di libbra di mozzarella a fette</li> <li class="list-group-item">¾ di tazza di parmigiano grattugiato</li> </ul> </div> </div> </section> </main> </body> </html> |
Seguiamo lo certo processo per creare un file per la pagina della ricetta del guacamole. Apri il file con nano eseguendo il seguente comando:
|
1 |
nano views/guacamole.html |
Quindi aggiungi questo codice al file:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 |
<!DOCTYPE html> <html lang="it"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <meta name="description" content=""> <meta name="author" content="Mark Otto, Jacob Thornton, and Bootstrap contributors"> <meta name="generator" content="Hugo 0.80.0"> <title>Ricetta del Guacamole</title> <!-- CSS principale di Bootstrap --> <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta2/dist/css/bootstrap.min.css" rel="stylesheet" crossorigin="anonymous"> <link href="css/custom.css" rel="stylesheet"> </head> <body> <nav class="navbar navbar-dark bg-dark navbar-static-top navbar-expand-md"> <div class="container"> <button type="button" class="navbar-toggler collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1" aria-expanded="false"> <span class="sr-only">Alterna navigazione</span> </button> <a class="navbar-brand" href="#">Ricette Fantastiche</a> <div class="collapse navbar-collapse justify-content-center" id="bs-example-navbar-collapse-1"> <ul class="nav navbar-nav justify-content-center"> <li class="active nav-item"> <a href="/" class="nav-link">Home</a> </li> <li class="nav-item"> <a href="/lasagna" class="nav-link">Lasagna</a> </li> <li class="nav-item"> <a href="/guacamole" class="nav-link">Guacamole</a> </li> <li class="nav-item"> <a href="/banana-bread" class="nav-link">Banana Bread</a> </li> </ul> </div> </div> </nav> <main> <section class="py-5 text-center container bg-light"> <div class="row py-lg-5"> <div class="col-lg-6 col-md-8 mx-auto"> <h1 class="fw-light">La migliore ricetta del guacamole</h1> <p class="lead text-muted"> Puoi preparare questa insalata di avocado cremosa o a pezzi a seconda dei tuoi gusti. <br /> <em>(Nulla di serio, questo serve solo per la nostra app demo con immagine node-express-docker)</em> </p> <h3>Ingredienti</h3> <ul class="list-group"> <li class="list-group-item">3 avocado - sbucciati, snocciolati e schiacciati</li> <li class="list-group-item">1 lime, spremuto</li> <li class="list-group-item">1 cucchiaino di sale</li> <li class="list-group-item">½ tazza di cipolla a dadini</li> <li class="list-group-item">3 cucchiai di coriandolo fresco tritato</li> <li class="list-group-item">2 pomodori perini (roma), a dadini</li> <li class="list-group-item">1 cucchiaino di aglio tritato</li> <li class="list-group-item">1 pizzico di pepe di Cayenna macinato (Opzionale)</li> </ul> </div> </div> </section> </main> </body> </html> |
Infine, creiamo il banana_bread.html file inserendo il comando:
|
1 |
nano views/banana_bread.html |
Quindi, aggiungi il seguente codice HTML al file:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 |
<!DOCTYPE html> <html lang="it"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <meta name="description" content=""> <meta name="author" content="Mark Otto, Jacob Thornton, and Bootstrap contributors"> <meta name="generator" content="Hugo 0.80.0"> <title>Ricetta del Banana Bread</title> <!-- Bootstrap core CSS --> <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta2/dist/css/bootstrap.min.css" rel="stylesheet" crossorigin="anonymous"> <link href="css/custom.css" rel="stylesheet"> </head> <body> <nav class="navbar navbar-dark bg-dark navbar-static-top navbar-expand-md"> <div class="container"> <button type="button" class="navbar-toggler collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1" aria-expanded="false"> <span class="sr-only">Alterna navigazione</span> </button> <a class="navbar-brand" href="#">Ricette Fantastiche</a> <div class="collapse navbar-collapse justify-content-center" id="bs-example-navbar-collapse-1"> <ul class="nav navbar-nav justify-content-center"> <li class="active nav-item"> <a href="/" class="nav-link">Home</a> </li> <li class="nav-item"> <a href="/lasagna" class="nav-link">Lasagna</a> </li> <li class="nav-item"> <a href="/guacamole" class="nav-link">Guacamole</a> </li> <li class="nav-item"> <a href="/banana-bread" class="nav-link">Banana Bread</a> </li> </ul> </div> </div> </nav> <main> <section class="py-5 text-center container bg-light"> <div class="row py-lg-5"> <div class="col-lg-6 col-md-8 mx-auto"> <h1 class="fw-light">La migliore ricetta del Banana Bread</h1> <p class="lead text-muted"> Perché scendere a compromessi sul sapore di banana? Questo banana bread è soffice e delizioso, con un intenso sapore di banana! Amici e parenti adorano la mia ricetta e dicono che è di gran lunga la migliore! È fantastico tostato!! Buon appetito! <br /> <em>(Nulla di serio, questo serve solo per la nostra app demo con immagine node-express-docker)</em> </p> <h3>Ingredienti</h3> <ul class="list-group"> <li class="list-group-item">2 tazze di farina 00</li> <li class="list-group-item">1 cucchiaino di bicarbonato di sodio</li> <li class="list-group-item">¼ di cucchiaino di sale</li> <li class="list-group-item">½ tazza di burro</li> <li class="list-group-item">¾ di tazza di zucchero di canna</li> <li class="list-group-item">2 uova, sbattute</li> <li class="list-group-item">2⅓ tazze di banane molto mature schiacciate</li> </ul> </div> </div> </section> </main> </body> </html> |
Ora abbiamo creato tutte le pagine. Se ricordi, dobbiamo aggiungere il file css/custom.css. Inserisci il seguente comando per creare la directory:
|
1 |
mkdir views/css |
Quindi crea e apri il file nell'editor nano con il comando:
|
1 |
nano views/css/custom.css |
Puoi aggiungere altri codici CSS per personalizzare lo stile del tuo sito web come desideri. Per brevità, aggiungiamo il seguente frammento di codice al file:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 |
.bd-placeholder-img { font-size: 1.125rem; text-anchor: middle; -webkit-user-select: none; -moz-user-select: none; user-select: none; } @media (min-width: 768px) { .bd-placeholder-img-lg { font-size: 3.5rem; } } |
Salva e chiudi il file quando hai finito.
Puoi avviare l'applicazione poiché ora abbiamo installato il codice sorgente dell'applicazione e le dipendenze del progetto.
We had set the app to listen on a port 8090, esegui il seguente comando per istruire il firewall a consentire il traffico attraverso questa porta. Se hai specificato una porta diversa, sostituisci il numero di porta nel comando:
|
1 |
sudo ufw allow 8090 |
Ora puoi avviare l'applicazione. Ma prima, assicurati di trovarti nella directory principale del progetto eseguendo il seguente comando:
|
1 |
cd ~/node_express |
Avvia l'applicazione con node index.js. Se hai specificato un punto di ingresso diverso, sostituiscilo con il tuo punto di ingresso:
|
1 |
node index.js |
Se navighi con il tuo browser su http://your_public_server_ip:8090, vedrai la pagina di destinazione delle Ricette come definita:
Puoi vedere i collegamenti alle varie ricette nella barra di navigazione. Facciamo clic su alcuni. Di seguito abbiamo la pagina della ricetta delle Lasagne:
E qui abbiamo la pagina della ricetta del Guacamole:
Fino a questo punto, hai creato la tua applicazione e verificato che funzioni come previsto. Puoi uscire dal server premendo Ctrl + C e passare alla creazione del Dockerfile. I Dockerfile aiutano nella scalabilità rendendo possibile ricreare un'istanza dell'applicazione quando necessario.
Passo 3: Creazione del Dockerfile
Docker legge le istruzioni specificate in un Dockerfile durante la compilazione delle immagini. Specifica l'ambiente di runtime di un'applicazione. Di conseguenza, aiuta gli sviluppatori a evitare discrepanze con le dipendenze o modifiche alle versioni di runtime. Inserisci il seguente comando per creare il Dockerfile:
|
1 |
nano Dockerfile |
Un'immagine Docker viene creata utilizzando diversi livelli di immagini che si sovrappongono l'uno all'altro. Si inizia aggiungendo un'immagine di base per formare il punto di partenza dell'app.
Poiché l'applicazione prevede di essere eseguita in un node.js ambiente, inizieremo aggiungendo l' immagine node:10-alpine per node.js. Attualmente, mentre scriviamo questo tutorial, questa è la versione LTS consigliata di Node.js. Abbiamo scelto questa immagine specifica perché deriva dal progetto Alpine Linux. Di conseguenza, aiuterà a mantenere al minimo le dimensioni della nostra immagine. Esistono diverse varianti di immagine nella pagina delle immagini Node di Docker Hub tra cui puoi scegliere in base alle tue esigenze.
Aggiungi il seguente codice per impostare l'immagine di base dell'applicazione utilizzando la direttiva FROM:
|
1 |
FROM node:10-alpine |
Questa immagine include Node.js e npm. Ogni Dockerfile deve iniziare con una direttiva FROM. L'immagine Docker node viene fornita per impostazione predefinita con un utente node non root che puoi utilizzare per eseguire il container dell'applicazione come root. La sicurezza di Docker consiglia di non eseguire i container come root e di limitare i privilegi solo a quelli richiesti per eseguire le sue risorse.
In tal caso, utilizzeremo la directory home dell'utente node come directory di lavoro per l'applicazione e come utente all'interno del container. Puoi consultare questa guida alle migliori pratiche per l'immagine Docker Node per ulteriori informazioni.
Creeremo la sottodirectory node_modules all'interno di /home/node insieme alla directory dell'app per aiutare a ottimizzare i permessi per il codice dell'applicazione. La creazione di queste directory garantisce che abbiano i permessi corretti quando eseguiamo il comando npm install localmente all'interno dei container. Una volta create le directory, devi impostarne la proprietà sull'utente node . Lo faremo all'interno del Dockerfile aggiungendo la seguente riga:
|
1 |
mkdir -p /home/node/app/node_modules && chown -R node:node /home/node/app |
Quindi imposterai la directory di lavoro aggiungendo la seguente riga:
|
1 |
WORKDIR /home/node/app |
È una buona idea impostare sempre WORKDIR in modo che Docker non debba crearne una per impostazione predefinita.
Aggiungi la seguente riga per copiare i file package.json e package-lock.json :
|
1 |
COPY package*.json ./ |
Si consiglia di aggiungere l'istruzione COPY prima di eseguire npm install o di copiare il codice sorgente dell'applicazione. Ciò consente di sfruttare il meccanismo di caching di Docker. Durante il processo di compilazione, Docker verifica se ha un livello memorizzato nella cache per ogni istruzione. Ciò significa che se non hai modificato il file package.json , Docker utilizzerà il livello dell'immagine esistente ed eviterà di reinstallare i moduli node , garantendo così processi di compilazione più rapidi.
Prima di eseguire npm install , aggiungi la seguente riga per passare all'utente node per garantire che tutti i file dell'applicazione e la directory node_modules siano di proprietà dell'utente node non root:
|
1 |
USER node |
Il nostro container è ora pronto per eseguire il comando npm install. Aggiungi la seguente riga al Dockerfile:
|
1 |
RUN npm install |
Una volta installati i node_modules , aggiungi la seguente riga che dirà a Docker di copiare il codice dell'applicazione nella directory dell'applicazione sul container con i permessi e la proprietà corretti, ovvero l'utente node non root:
|
1 |
COPY --chown=node:node . . |
L'ultimo passaggio consiste nell'esporre la porta 8090 sul container, come avevamo definito nel nostro file di ingresso index.js :
|
1 2 |
EXPOSE 8090 CMD [ "node", "index.js" ] |
EXPOSE imposta quali porte sul container saranno aperte a runtime. CMD esegue il comando per avviare l'applicazione, in questo caso, node index.js.
Dovresti avere solo un comando CMD nel Dockerfile, poiché solo l'ultimo ha effetto. Dai un'occhiata alla documentazione di riferimento del Dockerfile per un elenco di cose che puoi fare con il Dockerfile.
Il tuo Dockerfile completo dovrebbe apparire così:
|
1 2 3 4 5 6 7 8 9 |
FROM node:10-alpine RUN mkdir -p /home/node/app/node_modules && chown -R node:node /home/node/app WORKDIR /home/node/app COPY package*.json ./ USER node RUN npm install COPY --chown=node:node . . EXPOSE 8090 CMD [ "node", "index.js" ] |
Ora puoi salvare e chiudere il file.
La prossima cosa da fare è aggiungere il file .dockerignore. Proprio come il file .gitignore, il file .dockerignore specifica quali file e directory all'interno della directory del progetto non devono essere copiati nel container.
Apri il file con l'editor nano:
|
1 |
nano .dockerignore |
Aggiungi le seguenti righe all'interno del file:
|
1 2 3 4 |
node_modules npm-debug.log Dockerfile .dockerignore |
Se stai lavorando con un repository git, dovresti anche aggiungere la directory .git e il file .gitignore. Salva e chiudi il file.
Se tutto è andato a buon fine, è il momento di compilare l'immagine dell'applicazione utilizzando il comando docker build. Puoi aggiungere il flag –t al comando docker build per taggare l'immagine con un nome facile da ricordare, anziché la stringa casuale impostata da Docker per impostazione predefinita. Invieremo anche l'immagine a Docker Hub, quindi è consigliabile includere il tuo nome utente Docker Hub nel tag.
Useremo nodejs-express-image come nome del tag. Sei libero di scegliere il nome del tag che preferisci. Ecco il comando per compilare l'immagine:
|
1 |
sudo docker build -t your_dockerhub_username/nodejs-express-image . |
Ricorda di sostituire your_dockerhub_username con il tuo vero nome utente Docker Hub. Il . (punto) alla fine specifica che il contesto di compilazione è la directory corrente.
Il processo di compilazione richiede un minuto o due. Una volta terminato, inserisci il comando per verificare le tue immagini:
|
1 |
sudo docker images |
Dovresti vedere qualcosa di simile a questo:
Ricorda che abbiamo sostituito your_dockerhub_username con un nome utente reale.
Dopo aver confermato che la tua immagine è stata compilata, ora puoi creare un container con l'immagine utilizzando docker run. Saranno inclusi i seguenti flag:
-p: pubblica la porta sul container e la mappa su una porta del sistema host. Utilizzeremo la porta 80 sul sistema host a scopo dimostrativo. Tuttavia, se hai un altro processo in esecuzione su quella porta, sentiti libero di modificarla come necessario. Scopri di più sul port binding nella documentazione di Docker.-d: per la modalità detached. Consente al container di continuare a essere eseguito in background.--name: puoi usarlo per impostare un nome facile da ricordare invece di lasciare che Docker assegni una stringa casuale.
Il comando per compilare il container è il seguente. Sostituisci opportunamente il tuo nome utente Docker Hub:
|
1 |
sudo docker run --name nodejs-express-image -p 80:8090 -d your_dockerhub_username/nodejs-express-image |
Attendi che il container venga compilato e avviato. Puoi utilizzare questo comando per ispezionare tutti i container in esecuzione:
|
1 |
sudo docker ps |
Dovresti vedere un output simile al seguente:
Come si vede nell'output, il container è ora in esecuzione. Puoi visualizzarlo nel browser visitando l'indirizzo IP pubblico del tuo server senza specificare la porta. La tua home page verrà caricata:
Hai distribuito con successo un sito web statico Node Express con Docker. Vediamo come possiamo inviare questa immagine a Docker Hub per usi futuri e scopi di scalabilità.
Passo 4: Lavorare con i repository di immagini Docker
Puoi inviare le tue immagini a registri di immagini come Docker Hub e salvarle per un uso futuro, condividerle con altri sviluppatori o consentire la scalabilità dei tuoi container. Possiamo inviare l'immagine che abbiamo creato a Docker Hub e usarla per ricreare un container.
Usa il seguente comando per accedere al tuo account Docker Hub. Sostituisci con il tuo nome utente Docker Hub effettivo:
|
1 |
sudo docker login -u your_dockerhub_username |
Inserisci la tua password quando richiesto. Una volta effettuato l'accesso, un file ~/.docker/config.json viene creato nella directory home del tuo utente, contenente le tue credenziali di Docker Hub.
Fatto questo, inserisci il seguente comando per inviare l'immagine a Docker Hub, specificando il tag impostato in precedenza durante la creazione dell'immagine:
|
1 |
sudo docker push your_dockerhub_username/nodejs-express-image |
Questo comando invia l'immagine docker al tuo account Docker Hub. Se visiti il tuo account, puoi vedere l'immagine caricata di recente:
Possiamo testare l'utilità del repository di immagini eliminando il container dell'applicazione corrente e ricostruendolo utilizzando l'immagine nel repository.
Elenca i tuoi container correnti inserendo il comando:
|
1 |
sudo docker ps |
Dovresti vedere un output simile a questo:
Prendi nota del CONTAINER ID elencato nel tuo output, copialo e usalo per arrestare il tuo container con il comando, sostituendo l'ID con il tuo:
|
1 |
sudo docker stop 1bb2d65279bb |
Inserisci il seguente comando per elencare tutte le immagini docker disponibili nel tuo sistema:
|
1 |
sudo docker images –a |
L'output mostrerà il nome della tua immagine, l'immagine node.js e altre immagini del processo di compilazione.
Inserisci il seguente comando per rimuovere le immagini, comprese quelle inutilizzate o orfane:
|
1 |
sudo docker system prune |
Digita y per confermare. Questo rimuove i container e le immagini arrestati. Se li elenchi, vedrai un elenco vuoto nell'output:
Ora hai rimosso sia il container che esegue l'applicazione, sia l'immagine stessa. Scopri di più su come rimuovere container, immagini e volumi Docker seguendo il nostro tutorial.
Ora possiamo ricreare l'intero processo scaricando prima l'immagine da Docker Hub con il seguente comando. Sostituisci il tuo nome utente Docker Hub in modo appropriato:
|
1 |
sudo docker pull your_dockerhub_username/nodejs-express-image |
Elenca nuovamente le tue immagini Docker con il comando:
|
1 |
sudo docker images |
Dovresti vedere l'immagine nell'output:
Ora puoi ricostruire il tuo container usando il comando del Passo 3. Naturalmente, sostituisci il tuo nome utente Docker Hub dove opportuno:
|
1 |
sudo docker run --name nodejs-express-image -p 80:8090 -d your_dockerhub_username/nodejs-express-image |
Elenca i tuoi container per confermare che sia stato ricostruito:
|
1 |
sudo docker ps |
Dovresti vedere un output simile:
Nel tuo browser, naviga verso l'indirizzo IP pubblico del tuo server e dovresti vedere la tua app in esecuzione.
Conclusione
Se hai seguito il tutorial fino a questo punto, ora hai un sito web statico realizzato con Express e Bootstrap, e distribuito con Docker. Hai utilizzato i file del sito web statico per creare un'immagine Docker e hai utilizzato l'immagine per creare un container. Hai quindi inviato l'immagine a un registro di immagini Docker, Docker Hub, rendendola disponibile per un uso futuro o per la scalabilità. Per testare l'uso del registro delle immagini, hai eliminato le immagini e i container, hai scaricato le immagini dal registro e hai ricostruito i container.
Questo tutorial ha spiegato come distribuire un'app Node.js. Se desideri imparare a utilizzare uno stack di sviluppo web diverso, abbiamo un tutorial su Come distribuire un'app Laravel con Docker Compose su Nginx.
Per ulteriori risorse sull'utilizzo di Docker, consulta i seguenti tutorial:
- Come installare e configurare Docker Compose su Ubuntu 20.04
- Come condividere dati tra un container Docker e un host
- Installazione e configurazione di Docker su CentOS 7
Buon computing!











Commenti
Ancora nessun commento. Scrivi il primo.