Sviluppo di container con Dockerfile

1. Panoramica

Docker è una piattaforma aperta per lo sviluppo, la distribuzione e l'esecuzione di applicazioni. Con Docker puoi separare le tue applicazioni dalla tua infrastruttura e trattare la tua infrastruttura come un'applicazione gestita. Docker ti aiuta a distribuire, testare ed eseguire il deployment del codice più velocemente e a ridurre il ciclo tra scrittura ed esecuzione del codice.

Per farlo combina le funzionalità di containerizzazione dei kernel con flussi di lavoro e strumenti che ti aiutano a gestire le tue applicazioni e a eseguirne il deployment.

I container Docker possono essere utilizzati direttamente in Kubernetes, il che consente di eseguirli facilmente in Kubernetes Engine. Dopo aver appreso gli elementi essenziali di Docker, avrai le competenze per iniziare a sviluppare applicazioni Kubernetes e containerizzate.

Obiettivi didattici

In questo lab imparerai a:

  • Crea un Dockerfile per un'applicazione di esempio
  • Crea un'immagine
  • Esegui l'immagine come container in locale
  • Modifica il comportamento del contenitore
  • Esegui il push dell'immagine ad Artifact Registry

Prerequisiti

Questo è un lab di livello introduttivo. È adatto a chi ha poca o nessuna esperienza con Docker e i container. Suggeriamo, ma non è obbligatoria, esperienza con la riga di comando e Cloud Shell.

Configurazione dell'ambiente autogestito

  1. Accedi alla console Google Cloud e crea un nuovo progetto o riutilizzane uno esistente. Se non hai ancora un account Gmail o Google Workspace, devi crearne uno.

b35bf95b8bf3d5d8.png

a99b7ace416376c4.png

bd84a6d3004737c5.png

  • Il Nome progetto è il nome visualizzato dei partecipanti del progetto. Si tratta di una stringa di caratteri non utilizzata dalle API di Google e può essere aggiornata in qualsiasi momento.
  • L'ID progetto deve essere univoco in tutti i progetti Google Cloud ed è immutabile (non può essere modificato dopo essere stato impostato). La console Cloud genera automaticamente una stringa univoca; di solito non ti importa cosa sia. Nella maggior parte dei codelab, devi fare riferimento all'ID progetto (che solitamente è identificato come PROJECT_ID), quindi, se non ti piace, generane un altro a caso oppure puoi fare un tentativo personalizzato e controllare se è disponibile. Poi c'è "congelato" dopo la creazione del progetto.
  • C'è un terzo valore, il numero di progetto, utilizzato da alcune API. Scopri di più su tutti e tre questi valori nella documentazione.
  1. Successivamente, dovrai abilitare la fatturazione nella console Cloud per utilizzare le risorse/le API Cloud. Eseguire questo codelab non dovrebbe costare molto. Per arrestare le risorse in modo da non incorrere in fatturazione oltre questo tutorial, segui eventuali "pulizie" istruzioni riportate alla fine del codelab. I nuovi utenti di Google Cloud sono idonei al programma prova senza costi di 300$.

2. Prova l'applicazione

È stata fornita un'applicazione di esempio per facilitare questo lab. In questa sezione recupererai il codice sorgente e creerai l'applicazione nella sua forma nativa prima di passare al processo di containerizzazione.

Codice sorgente

Il codice sorgente di questo lab è disponibile nel repository GoogleCloudPlatform/container-developer-workshop insieme alla documentazione dell'applicazione di esempio.

Configura Git

git config --global user.name ${USER}
git config --global user.email ${USER}@qwiklabs.net

Clona il repository di codice sorgente Cloud dell'applicazione di esempio

gcloud source repos clone sample-app ${HOME}/sample-app &&
cd ${HOME}/sample-app &&
git checkout main

Output

Cloning into '/home/student_03_49720296e995/sample-app'...
remote: Finding sources: 100% (16/16)
remote: Total 16 (delta 0), reused 16 (delta 0)
Receiving objects: 100% (16/16), 47.23 KiB | 681.00 KiB/s, done.
warning: remote HEAD refers to nonexistent ref, unable to checkout.

Project [qwiklabs-gcp-02-4327c4e03d82] repository [sample-app] was cloned to [/home/student_03_49720296e995/sample-app].
Branch 'main' set up to track remote branch 'main' from 'origin'.
Switched to a new branch 'main'

Crea l'applicazione di esempio

cd ${HOME}/sample-app
./mvnw compile

Output

[INFO] Scanning for projects...
...
[INFO] Compiling 1 source file to /home/student_03_49720296e995/sample-app/target/classes
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  10.080 s
[INFO] Finished at: 2022-02-23T17:14:30Z
[INFO] ------------------------------------------------------------------------

Esegui l'applicazione di esempio

cd ${HOME}/sample-app
./mvnw exec:java

Output

[INFO] Scanning for projects...
...
Listening at http://localhost:8080

Visualizza l'anteprima dell'applicazione in esecuzione

  • Fai clic sul pulsante Anteprima web di Cloud Shell
  • Fai clic su Anteprima sulla porta 8080

Al termine

  • Premi CTRL + c in Cloud Shell per arrestare l'applicazione in esecuzione

3. Dockerfile

Containerizzazione dell'applicazione con un Dockerfile

Un metodo per pacchettizzare un'applicazione in un container è l'utilizzo di un Dockerfile. Il Dockerfile è simile a uno script che indica al daemon come assemblare l'immagine container. Per saperne di più, consulta la documentazione di riferimento di Dockerfile.

Crea un Dockerfile vuoto nel repository dell'applicazione di esempio.

touch ${HOME}/sample-app/Dockerfile

Apri il Dockerfile nell'editor che preferisci.

vi ${HOME}/sample-app/Dockerfile

Scegli un'immagine iniziale

L'utilizzo del metodo Dockerfile per creare un container richiede la conoscenza diretta dell'applicazione per assemblare il container. Il primo passaggio per creare un Dockerfile consiste nel selezionare un'immagine che verrà utilizzata come base della tua immagine.Questa immagine deve essere un'immagine padre o di base gestita e pubblicata da una fonte attendibile, di solito la tua azienda.

L'istruzione FROM inizializza una nuova fase di creazione e imposta l'immagine di base per i comandi sequenziali successivi. Di conseguenza, l'istruzione FROM è in genere la prima istruzione in un Dockerfile e può essere preceduta solo da un'istruzione ARG facoltativa per supportare le variabili.

Sintassi: FROM <image>[:<tag> | @<digest>] [AS <name>]

Il formato di un'immagine è <image>:<tag> o <image>@<digest>. Se un tag o un digest non vengono specificati, per impostazione predefinita viene usato il tag :latest. Il formato di <image> varia in base al registro utilizzato per archiviare l'immagine. Per Artifact Registry, il formato <image> è <region>-docker.pkg.dev/<project ID>/<repository name>/<image name>:<image tag>.

Per questo lab utilizziamo l'immagine openjdk:11.0-jdk pubblica, aggiungi la seguente riga al tuo Dockerfile

FROM openjdk:11.0-jdk

Impostare la directory di lavoro

L'istruzione WORKDIR imposta la directory di lavoro per eventuali istruzioni sequenziali che seguono nel Dockerfile. Per ulteriori informazioni, consulta la sezione WORKDIR della documentazione di riferimento di Dockerfile.

Sintassi: WORKDIR <path>

Per questo lab utilizziamo la directory /app come WORKDIR, aggiungi la seguente riga in fondo al tuo Dockerfile

WORKDIR /app

Copia i file dell'applicazione

L'istruzione COPY copia le directory o i file dalla posizione <source> al percorso <destination> del file system dell'immagine. È possibile specificare più risorse <source> e tutte relative al contesto della build. Il contesto della build verrà approfondito nella sezione Creazione. Per ulteriori informazioni, consulta la sezione COPIA della documentazione di riferimento di Dockerfile.

Sintassi: COPY <source>... <destination>

Per questo lab copieremo tutti i file del repository nel file system dell'immagine. Aggiungiamo la seguente riga in fondo al Dockerfile

COPY . /app

Compila l'applicazione

L'istruzione RUN esegue i comandi in un nuovo livello immagine sopra l'immagine corrente ed esegue il commit dei risultati. L'immagine di cui viene eseguito il commit risultante verrà utilizzata per i passaggi sequenziali nel Dockerfile. Per ulteriori informazioni, consulta la sezione ESEGUI della documentazione di riferimento di Dockerfile.

Sintassi: RUN <command>

Per questo lab utilizzeremo Maven per compilare l'applicazione in un file JAR. Aggiungere la riga seguente in fondo al Dockerfile

RUN ./mvnw compile assembly:single

Avvia l'applicazione

L'istruzione CMD fornisce il comando predefinito per un container in esecuzione. In un Dockerfile può esistere una sola istruzione CMD. Se viene specificata più di una CMD, viene applicata solo l'ultima istruzione CMD. Sono disponibili funzionalità più avanzate mediante le istruzioni CMD e ENTRYPOINT, ma non sono descritte in questo lab. Per saperne di più, consulta la sezione CMD" della documentazione di riferimento di Dockerfile

Sintassi: CMD ["executable","param1","param2"]

Per questo lab eseguiamo il file JAR che abbiamo compilato, aggiungi la seguente riga in fondo al tuo Dockerfile

CMD ["java","-jar","/app/target/sample-app-1.0.0-jar-with-dependencies.jar"]

Dockerfile finale

Il Dockerfile finale sarà

FROM openjdk:11.0-jdk
WORKDIR /app
COPY . /app
RUN ./mvnw compile assembly:single
CMD ["java","-jar","/app/target/sample-app-1.0.0-jar-with-dependencies.jar"]

Esegui il commit del Dockerfile in locale

cd ${HOME}/sample-app
git add Dockerfile
git commit -m "Added Dockerfile"

4. Build

Ora creeremo l'immagine dal Dockerfile utilizzando il comando docker build. Questo comando indica al daemon Docker di creare l'immagine utilizzando le istruzioni del nostro Dockerfile. Per saperne di più, consulta la documentazione di riferimento per Docker Build.

Crea l'immagine

cd ${HOME}/sample-app
export IMAGE_TAG=$(git rev-parse --short HEAD)
docker build --tag sample-app:${IMAGE_TAG} .

Output

Sending build context to Docker daemon  221.2kB
Step 1/4 : FROM openjdk:11.0-jdk
11.0-jdk: Pulling from library/openjdk
0c6b8ff8c37e: Pull complete
412caad352a3: Pull complete
e6d3e61f7a50: Pull complete
461bb1d8c517: Pull complete
e442ee9d8dd9: Pull complete
542c9fe4a7ba: Pull complete
41de18d1833d: Pull complete
Digest: sha256:d72b1b9e94e07278649d91c635e34737ae8f181c191b771bde6816f9bb4bd08a
Status: Downloaded newer image for openjdk:11.0-jdk
---> 2924126f1829
Step 2/4 : WORKDIR /app
---> Running in ea037abb273d
Removing intermediate container ea037abb273d
---> bd9b6d078082
Step 3/4 : COPY . /app
---> b9aec2b5de51
Step 4/4 : RUN ./mvnw compile jar:jar
---> Running in 3f5ff737b7fd
[INFO] Scanning for projects...
...
[INFO] Building jar: /app/target/sample-app-1.0.0.jar
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  22.952 s
[INFO] Finished at: 2022-02-23T18:09:08Z
[INFO] ------------------------------------------------------------------------
Removing intermediate container 331443caebd3
---> 152f65cc441e
Step 5/5 : CMD ["java", "-jar", "/app/target/sample-app-1.0.0.jar"]
---> Running in 3d595a72231c
Removing intermediate container 3d595a72231c
---> 0e40d7548cab
Successfully built 0e40d7548cab
Successfully tagged sample-app:aaa8895

5. Esegui

Una volta creata correttamente l'immagine container, siamo in grado di eseguire l'applicazione e di assicurarci che si comporti come previsto utilizzando il comando docker run. Questo comando avvierà il container in primo piano nel prompt dei comandi per eseguire test o eseguire il debug. Per saperne di più, consulta la documentazione di riferimento di docker run.

Esegui un container utilizzando l'immagine

cd ${HOME}/sample-app
export IMAGE_TAG=$(git rev-parse --short HEAD)
docker run \
  --rm \
  -p 8080:8080 \
  sample-app:${IMAGE_TAG}

Output

Listening at http://localhost:8080

Visualizza l'anteprima dell'applicazione in esecuzione in un container

  • Fai clic sul pulsante Anteprima web di Cloud Shell
  • Fai clic su Anteprima sulla porta 8080
  • Premi CTRL + C in Cloud Shell per arrestare i container

Modifica del comportamento del contenitore

L'esecuzione di Docker Run utilizza la configurazione predefinita nel Dockerfile. Per modificare questo comportamento, è possibile aggiungere ulteriori istruzioni e parametri.

Attiva la registrazione TRACE

cd ${HOME}/sample-app
export IMAGE_TAG=$(git rev-parse --short HEAD)
docker run \
  --rm \
  -p 8080:8080 \
  sample-app:${IMAGE_TAG} \
  java -Dorg.slf4j.simpleLogger.defaultLogLevel=trace -jar /app/target/sample-app-1.0.0-jar-with-dependencies.jar

Visualizza l'anteprima dell'applicazione in esecuzione in un container

  • Fai clic sul pulsante Anteprima web di Cloud Shell
  • Fai clic su Anteprima sulla porta 8080
  • Passa alla scheda Cloud Shell per visualizzare il logging aggiuntivo
  • Premi CTRL + C in Cloud Shell per arrestare il container

Cambia porta

cd ${HOME}/sample-app
export IMAGE_TAG=$(git rev-parse --short HEAD)
docker run \
--rm \
-e PORT=8081 \
-p 8081:8081 \
sample-app:${IMAGE_TAG}

Visualizza l'anteprima dell'applicazione in esecuzione in un container

  • Fai clic sul pulsante Anteprima web di Cloud Shell
  • Fai clic su Cambia porta
  • Inserisci 8081
  • Fai clic su Cambia e visualizza l'anteprima
  • Premi CTRL + C in Cloud Shell per arrestare il container

6. Push

Una volta stabilito che l'immagine container funziona correttamente e vogliamo rendere il container disponibile per l'esecuzione in altri ambienti e/o da altri utenti, dobbiamo eseguire il push dell'immagine in un repository condiviso. Questo dovrebbe avvenire come parte di una pipeline di build automatizzata, ma nel nostro ambiente di test abbiamo già un repository configurato e possiamo eseguire manualmente il push dell'immagine.

Esegui il push del commit Dockerfile nel repository dell'app di esempio

cd ${HOME}/sample-app
export IMAGE_TAG=$(git rev-parse --short HEAD)
git push

Tagga l'immagine per Artifact Registry

docker tag sample-app:${IMAGE_TAG} \
    us-central1-docker.pkg.dev/${GOOGLE_CLOUD_PROJECT}/apps/sample-app:${IMAGE_TAG}

Configura le tue credenziali per Artifact Registry

gcloud auth configure-docker us-central1-docker.pkg.dev

Quando richiesto, Do you want to continue (Y/n)? rispondi y e premi Enter

Esegui il push dell'immagine ad Artifact Registry

docker push us-central1-docker.pkg.dev/${GOOGLE_CLOUD_PROJECT}/apps/sample-app:${IMAGE_TAG}

Output

 The push refers to repository [us-central1-docker.pkg.dev/qwiklabs-gcp-04-b47ced695a3c/apps/sample-app]
  453b97f86449: Pushed
  e86791aa0382: Pushed
  d404c7ee0850: Pushed
  fe4f44af763d: Pushed
  7c072cee6a29: Pushed
  1e5fdc3d671c: Pushed
  613ab28cf833: Pushed
  bed676ceab7a: Pushed
  6398d5cccd2c: Pushed
  0b0f2f2f5279: Pushed
  aaa8895: digest: sha256:459de00f86f159cc63f98687f7c9563fd65a2eb9bcc71c23dda3351baf13607a size: 2424

7. Complimenti!

Complimenti, hai completato il codelab.

Argomenti trattati

  • Creazione di un Dockerfile per un'applicazione di esempio
  • Immagine creata
  • Ha eseguito l'immagine come container in locale
  • Comportamento del contenitore modificato
  • Eseguito il push dell'immagine in Artifact Registry