Esercitazione: Rendere persistenti i dati in un'app contenitore usando volumi in VS Code
In questa esercitazione si apprenderà come rendere persistenti i dati in un'applicazione contenitore. Quando vengono eseguiti o aggiornati, i dati sono ancora disponibili. Esistono due tipi principali di volumi usati per rendere persistenti i dati. Questa esercitazione è incentrata sui volumi denominati.
Verranno inoltre fornite informazioni sui montaggi di associazione, che controllano il punto di montaggio esatto nell'host. È possibile usare i montaggi di associazione per rendere persistenti i dati, ma può anche aggiungere altri dati ai contenitori. Quando si lavora su un'applicazione, è possibile usare un montaggio bind per montare il codice sorgente nel contenitore per visualizzare le modifiche al codice, rispondere e visualizzare immediatamente le modifiche.
Questa esercitazione presenta anche la suddivisione in livelli delle immagini, la memorizzazione nella cache dei livelli e le compilazioni a più fasi.
In questa esercitazione apprenderai a:
- Informazioni sui dati tra contenitori.
- Rendere persistenti i dati usando volumi denominati.
- Usare i montaggi di associazione.
- Visualizzare il livello immagine.
- Dipendenze della cache.
- Informazioni sulle compilazioni in più fasi.
Prerequisiti
Questa esercitazione continua l'esercitazione precedente, Creare e condividere un'app Docker con Visual Studio Code. Iniziare con quello, che include i prerequisiti.
Informazioni sui dati tra contenitori
In questa sezione si inizieranno due contenitori e si creerà un file in ognuno. I file creati in un contenitore non sono disponibili in un altro contenitore.
Avviare un
ubuntu
contenitore usando questo comando:docker run -d ubuntu bash -c "shuf -i 1-10000 -n 1 -o /data.txt && tail -f /dev/null"
Questo comando avvia il richiamo di due comandi tramite
&&
. La prima parte seleziona un singolo numero casuale e la scrive in/data.txt
. Il secondo comando sta controllando un file per mantenere il contenitore in esecuzione.In VS Code, nell'area Docker fare clic con il pulsante destro del mouse sul contenitore ubuntu e scegliere Collega shell.
Viene aperto un terminale che esegue una shell nel contenitore Ubuntu.
Eseguire il comando seguente per visualizzare il contenuto del
/data.txt
file.cat /data.txt
Il terminale mostra un numero compreso tra 1 e 10000.
Per usare la riga di comando per visualizzare questo risultato, ottenere l'ID contenitore usando il
docker ps
comando ed eseguire il comando seguente.docker exec <container-id> cat /data.txt
Avviare un altro
ubuntu
contenitore.docker run -d ubuntu bash -c "shuf -i 1-10000 -n 1 -o /data.txt && tail -f /dev/null"
Usare questo comando per esaminare il contenuto della cartella.
docker run -it ubuntu ls /
Non dovrebbe essere presente alcun
data.txt
file perché è stato scritto nello spazio scratch solo per il primo contenitore.Selezionare questi due contenitori Ubuntu. Fare clic con il pulsante destro del mouse e scegliere Rimuovi. Dalla riga di comando è possibile rimuoverli usando il
docker rm -f
comando .
Rendere persistenti i dati todo usando volumi denominati
Per impostazione predefinita, l'app todo archivia i dati in un database SQLite all'indirizzo /etc/todos/todo.db
.
Il database SQLite è un database relazionale che archivia i dati di un singolo file.
Questo approccio funziona per progetti di piccole dimensioni.
È possibile rendere persistente il singolo file nell'host. Quando lo si rende disponibile per il contenitore successivo, l'applicazione può selezionare la posizione in cui è stata interrotta. Creando un volume e collegandoli o montandoli nella cartella in cui sono archiviati i dati, è possibile rendere persistenti i dati. Il contenitore scrive nel file todo.db e i dati vengono mantenuti nell'host nel volume.
Per questa sezione, usare un volume denominato. Docker mantiene la posizione fisica del volume sul disco. Fare riferimento al nome del volume e Docker fornisce i dati corretti.
Creare un volume usando il
docker volume create
comando .docker volume create todo-db
In CONTENITORI selezionare Attività iniziali e fare clic con il pulsante destro del mouse. Selezionare Arresta per arrestare il contenitore dell'app.
Per arrestare il contenitore dalla riga di comando, usare il
docker stop
comando .Avviare il contenitore introduttivo usando il comando seguente.
docker run -dp 3000:3000 -v todo-db:/etc/todos getting-started
Il parametro volume specifica il volume da montare e la posizione ,
/etc/todos
.Aggiornare il browser per ricaricare l'app. Se la finestra del browser è stata chiusa, passare a
http://localhost:3000/
. Aggiungere alcuni elementi all'elenco todo.Rimuovere il contenitore introduttivo per l'app todo. Fare clic con il pulsante destro del mouse sul contenitore nell'area Docker e scegliere Rimuovi o usare i
docker stop
comandi edocker rm
.Avviare un nuovo contenitore usando lo stesso comando:
docker run -dp 3000:3000 -v todo-db:/etc/todos getting-started
Questo comando monta la stessa unità di prima. Aggiorna il browser. Gli elementi aggiunti sono ancora presenti nell'elenco.
Rimuovere di nuovo il contenitore introduttivo .
I volumi denominati e i montaggi di associazione, descritti di seguito, sono i tipi principali di volumi supportati da un'installazione predefinita del motore Docker.
Proprietà | Volumi denominati | Associa montaggi |
---|---|---|
Posizione host | Docker sceglie | Si controlla |
Esempio di montaggio (con -v ) |
my-volume:/usr/local/data | /path/to/data:/usr/local/data |
Popola il nuovo volume con il contenuto del contenitore | Sì | No |
Supporta i driver di volume | Sì | No |
Sono disponibili molti plug-in driver di volume per supportare NFS, SFTP, NetApp e altro ancora. Questi plug-in sono particolarmente importanti per eseguire contenitori in più host in un ambiente cluster, ad esempio Swarm o Kubernetes.
Se ci si chiede dove Docker archivia effettivamente i dati, eseguire il comando seguente.
docker volume inspect todo-db
Esaminare l'output, simile a questo risultato.
[
{
"CreatedAt": "2019-09-26T02:18:36Z",
"Driver": "local",
"Labels": {},
"Mountpoint": "/var/lib/docker/volumes/todo-db/_data",
"Name": "todo-db",
"Options": {},
"Scope": "local"
}
]
Mountpoint
è la posizione effettiva in cui vengono archiviati i dati.
Nella maggior parte dei computer è necessario l'accesso radice per accedere a questa directory dall'host.
Usare i montaggi di binding
Con i montaggi di associazione, è possibile controllare il punto di montaggio esatto nell'host. Questo approccio rende persistenti i dati, ma viene spesso usato per fornire più dati nei contenitori. È possibile usare un montaggio di associazione per montare il codice sorgente nel contenitore per visualizzare le modifiche al codice, rispondere e visualizzare immediatamente le modifiche.
Per eseguire il contenitore per supportare un flusso di lavoro di sviluppo, seguire questa procedura:
Rimuovere tutti i
getting-started
contenitori.app
Nella cartella eseguire il comando seguente.docker run -dp 3000:3000 -w /app -v ${PWD}:/app node:20-alpine sh -c "yarn install && yarn run dev"
Questo comando contiene i parametri seguenti.
-dp 3000:3000
Uguale a prima. Eseguire in modalità scollegata e creare un mapping delle porte.-w /app
Directory di lavoro all'interno del contenitore.-v ${PWD}:/app"
Eseguire il montaggio della directory corrente dall'host nel contenitore nella/app
directory .node:20-alpine
Immagine da usare. Questa immagine è l'immagine di base per l'app dal Dockerfile.sh -c "yarn install && yarn run dev"
Comando . Avvia una shell usandosh
ed esegueyarn install
per installare tutte le dipendenze. Esegue quindiyarn run dev
. Se si cerca inpackage.json
, lodev
script sta avviandonodemon
.
È possibile controllare i log usando
docker logs
.docker logs -f <container-id>
$ nodemon src/index.js [nodemon] 2.0.20 [nodemon] to restart at any time, enter `rs` [nodemon] watching path(s): *.* [nodemon] watching extensions: js,mjs,json [nodemon] starting `node src/index.js` Using sqlite database at /etc/todos/todo.db Listening on port 3000
Quando viene visualizzata la voce finale in questo elenco, l'app è in esecuzione.
Al termine dell'osservazione dei log, selezionare qualsiasi tasto nella finestra del terminale o premere CTRL+C in una finestra esterna.
In VS Code aprire src/static/js/app.js. Modificare il testo del pulsante Aggiungi elemento alla riga 109.
- {submitting ? 'Adding...' : 'Add Item'} + {submitting ? 'Adding...' : 'Add'}
Salvare la modifica.
Aggiorna il browser. Verrà visualizzata la modifica.
Visualizzare i livelli immagine
È possibile esaminare i livelli che costituiscono un'immagine.
Eseguire il docker image history
comando per visualizzare il comando usato per creare ogni livello all'interno di un'immagine.
Usare
docker image history
per visualizzare i livelli nell'immagine introduttiva creata in precedenza nell'esercitazione.docker image history getting-started
Il risultato dovrebbe essere simile a questo output.
IMAGE CREATED CREATED BY SIZE COMMENT a78a40cbf866 18 seconds ago /bin/sh -c #(nop) CMD ["node" "/app/src/ind… 0B f1d1808565d6 19 seconds ago /bin/sh -c yarn install --production 85.4MB a2c054d14948 36 seconds ago /bin/sh -c #(nop) COPY dir:5dc710ad87c789593… 198kB 9577ae713121 37 seconds ago /bin/sh -c #(nop) WORKDIR /app 0B b95baba1cfdb 13 days ago /bin/sh -c #(nop) CMD ["node"] 0B <missing> 13 days ago /bin/sh -c #(nop) ENTRYPOINT ["docker-entry… 0B <missing> 13 days ago /bin/sh -c #(nop) COPY file:238737301d473041… 116B <missing> 13 days ago /bin/sh -c apk add --no-cache --virtual .bui… 5.35MB <missing> 13 days ago /bin/sh -c #(nop) ENV YARN_VERSION=1.21.1 0B <missing> 13 days ago /bin/sh -c addgroup -g 1000 node && addu… 74.3MB <missing> 13 days ago /bin/sh -c #(nop) ENV NODE_VERSION=12.14.1 0B <missing> 13 days ago /bin/sh -c #(nop) CMD ["/bin/sh"] 0B <missing> 13 days ago /bin/sh -c #(nop) ADD file:e69d441d729412d24… 5.59MB
Ognuna delle linee rappresenta un livello nell'immagine. L'output mostra la base nella parte inferiore con il livello più recente nella parte superiore. Usando queste informazioni, è possibile visualizzare le dimensioni di ogni livello, consentendo di diagnosticare immagini di grandi dimensioni.
Diverse righe vengono troncate. Se si aggiunge il
--no-trunc
parametro , si otterrà l'output completo.docker image history --no-trunc getting-started
Dipendenze della cache
Una volta modificato un livello, è necessario ricreare anche tutti i livelli downstream. Ecco di nuovo il Dockerfile :
FROM node:20-alpine
WORKDIR /app
COPY . .
RUN yarn install --production
CMD ["node", "/app/src/index.js"]
Ogni comando nel Dockerfile diventa un nuovo livello nell'immagine.
Per ridurre al minimo il numero di livelli, è possibile ristrutturare il Dockerfile per supportare la memorizzazione nella cache delle dipendenze.
Per le applicazioni basate su Node, tali dipendenze vengono definite nel package.json
file .
L'approccio consiste nel copiare solo il file in primo luogo, installare le dipendenze e quindi copiare tutto il resto.
Il processo ricrea le dipendenze yarn solo se è stata apportata una modifica a package.json
.
Aggiornare il Dockerfile per copiare le dipendenze nel
package.json
primo, installare le dipendenze e quindi copiare tutto il resto. Ecco il nuovo file:FROM node:20-alpine WORKDIR /app COPY package.json yarn.lock ./ RUN yarn install --production COPY . . CMD ["node", "/app/src/index.js"]
Compilare una nuova immagine usando
docker build
.docker build -t getting-started .
Verrà visualizzato un output simile ai risultati seguenti:
Sending build context to Docker daemon 219.1kB Step 1/6 : FROM node:12-alpine ---> b0dc3a5e5e9e Step 2/6 : WORKDIR /app ---> Using cache ---> 9577ae713121 Step 3/6 : COPY package* yarn.lock ./ ---> bd5306f49fc8 Step 4/6 : RUN yarn install --production ---> Running in d53a06c9e4c2 yarn install v1.17.3 [1/4] Resolving packages... [2/4] Fetching packages... info fsevents@1.2.9: The platform "linux" is incompatible with this module. info "fsevents@1.2.9" is an optional dependency and failed compatibility check. Excluding it from installation. [3/4] Linking dependencies... [4/4] Building fresh packages... Done in 10.89s. Removing intermediate container d53a06c9e4c2 ---> 4e68fbc2d704 Step 5/6 : COPY . . ---> a239a11f68d8 Step 6/6 : CMD ["node", "/app/src/index.js"] ---> Running in 49999f68df8f Removing intermediate container 49999f68df8f ---> e709c03bc597 Successfully built e709c03bc597 Successfully tagged getting-started:latest
Tutti i livelli sono stati ricostruiti. Questo risultato è previsto perché è stato modificato il Dockerfile.
Apportare una modifica al src/static/index.html. Ad esempio, modificare il titolo in modo da indicare "The Awesome Todo App".
Compilare ora l'immagine Docker usando
docker build
di nuovo. Questa volta, l'output dovrebbe avere un aspetto leggermente diverso.Sending build context to Docker daemon 219.1kB Step 1/6 : FROM node:12-alpine ---> b0dc3a5e5e9e Step 2/6 : WORKDIR /app ---> Using cache ---> 9577ae713121 Step 3/6 : COPY package* yarn.lock ./ ---> Using cache ---> bd5306f49fc8 Step 4/6 : RUN yarn install --production ---> Using cache ---> 4e68fbc2d704 Step 5/6 : COPY . . ---> cccde25a3d9a Step 6/6 : CMD ["node", "/app/src/index.js"] ---> Running in 2be75662c150 Removing intermediate container 2be75662c150 ---> 458e5c6f080c Successfully built 458e5c6f080c Successfully tagged getting-started:latest
Poiché si usa la cache di compilazione, dovrebbe essere molto più veloce.
Compilazioni in più fasi
Le compilazioni a più fasi sono uno strumento incredibilmente potente che consente di usare più fasi per creare un'immagine. Esistono diversi vantaggi:
- Separare le dipendenze in fase di compilazione dalle dipendenze di runtime
- Ridurre le dimensioni complessive dell'immagine in base alla spedizione solo di ciò che l'app deve eseguire
In questa sezione vengono forniti brevi esempi.
Esempio di Maven/Tomcat
Quando si compilano applicazioni basate su Java, è necessario un JDK per compilare il codice sorgente in bytecode Java. JDK non è necessario nell'ambiente di produzione. È possibile usare strumenti come Maven o Gradle per facilitare la compilazione dell'app. Questi strumenti non sono necessari anche nell'immagine finale.
FROM maven AS build
WORKDIR /app
COPY . .
RUN mvn package
FROM tomcat
COPY --from=build /app/target/file.war /usr/local/tomcat/webapps
Questo esempio usa una fase, build
, per eseguire la compilazione Java effettiva usando Maven.
La seconda fase, a partire da "FROM tomcat", copia nei file dalla build
fase.
L'immagine finale è solo l'ultima fase da creare, che può essere sottoposta a override usando il --target
parametro .
Esempio di React
Quando si compilano applicazioni React, è necessario un ambiente Node per compilare il codice JavaScript, i fogli di stile SASS e altro ancora in HTML statico, JavaScript e CSS. Se non si esegue il rendering sul lato server, non è necessario nemmeno un ambiente Node per la compilazione di produzione.
FROM node:20-alpine AS build
WORKDIR /app
COPY package* yarn.lock ./
RUN yarn install
COPY public ./public
COPY src ./src
RUN yarn run build
FROM nginx:alpine
COPY --from=build /app/build /usr/share/nginx/html
In questo esempio viene usata un'immagine node:20
per eseguire la compilazione, che ottimizza la memorizzazione nella cache dei livelli e quindi copia l'output in un contenitore nginx .
Pulire le risorse
Mantenere tutto ciò che è stato fatto finora per continuare questa serie di esercitazioni.
Passaggi successivi
Sono state illustrate le opzioni per rendere persistenti i dati per le app contenitore.
Cosa vuoi fare?
Usare più contenitori usando Docker Compose:
Distribuire in App Azure Container:
Distribuire nel Servizio app di Azure
Commenti e suggerimenti
https://aka.ms/ContentUserFeedback.
Presto disponibile: Nel corso del 2024 verranno gradualmente disattivati i problemi di GitHub come meccanismo di feedback per il contenuto e ciò verrà sostituito con un nuovo sistema di feedback. Per altre informazioni, vedereInvia e visualizza il feedback per