Se hai mai avuto bisogno di eseguire uno o due comandi nel tuo contenitore Docker all'avvio, questo tutorial è per te. Usando il Dockerfile ENTRYPOINT
e CMD
istruzioni, puoi eseguire tutti i comandi di avvio che desideri.
In questo tutorial imparerai come utilizzare il ENTRYPOINT
e CMD
istruzioni per eseguire i comandi di avvio in un Dockerfile e comprenderne le differenze.
Prerequisiti
Poiché questo tutorial sarà una dimostrazione pratica, assicurati di avere in atto quanto segue:
- In questo tutorial è stato utilizzato un PC Windows 10:Windows 10 v10.0.19042.
- Docker Desktop:questo tutorial utilizza Docker Desktop v3.3.1.
Creazione di un Dockerfile
Prima di poter eseguire i comandi di avvio del contenitore Docker, devi prima creare un Dockerfile. Un Dockerfile è un documento di testo che contiene un elenco di comandi per creare contenitori, immagini Docker e determina come viene creata un'immagine Docker.
1. Innanzitutto, apri PowerShell come amministratore.
2. Crea una nuova cartella per archiviare il Dockerfile e tutti i file associati che questo tutorial utilizzerà e cambierà in quella directory. Questo tutorial utilizza ~/docker .
mkdir ~/docker
cd docker
3. Ora crea un file di testo vuoto chiamato Dockerfile con il seguente comando.
cd > Dockerfile
In alternativa, puoi creare un Dockerfile con il seguente comando se sei su Linux o Mac OS.
touch Dockerfile
4. Infine, aggiungi il seguente contenuto nel Dockerfile
FROM ubuntu:20.04
Ora hai creato un Dockerfile che sarà presto disponibile!
Creazione di un'immagine Docker
Ora che hai creato il tuo Dockerfile, devi creare un'immagine Docker per eseguire i comandi scritti nelle tue istruzioni Dockerfile ENTRYPOINT e CMD. Un modo per creare un'immagine è usare build
comando.
Nella ~/docker directory, eseguire il comando seguente. Il comando seguente crea un'immagine Docker chiamata demo (-t demo
) dal Dockerfile in ~/docker specificando la directory di lavoro corrente (.
).
docker build -t demo .
Esecuzione di un container Docker
Dopo aver creato l'immagine Docker, avrai bisogno di un contenitore per eseguire l'immagine Docker che eseguirà i comandi dalle istruzioni Dockerfile ENTRYPOINT e CMD.
Per eseguire un container Docker, richiama run
comando per creare un livello contenitore scrivibile sull'immagine Docker (demo
). L'esempio seguente utilizza -it
parametro per connettersi in modo interattivo al contenitore in modo da poter vedere l'output di esempio.
docker run -it demo
Exec vs. Shell Form
Quando inizi a lavorare con un Dockerfile e capisci come eseguire i comandi di avvio, potresti imbatterti in due diversi metodi per definire questi comandi. Ciascun metodo invocherà i comandi ma lo fa in modo leggermente diverso.
Quando Docker esegue i comandi, può farlo direttamente chiamato exec
oppure passa attraverso la shell del contenitore (/bin/sh -c
su Linux o cmd /S /C
su Windows) chiamato shell
.
Noterai i comandi eseguiti tramite exec
avere un'istruzione seguita dagli eseguibili da invocare seguiti da uno o più argomenti della riga di comando, come mostrato di seguito.
ENTRYPOINT ["executables", "parameter1", "parameter2", ...]
CMD ["executables", "parameter1", "parameter2:, ...]
Scrivere comandi in shell
form, d'altra parte, non richiede il wrapping dei comandi tra parentesi quadre, come mostrato di seguito.
ENTRYPOINT <command> "parameter1"
CMD <command> "parameter1"
Se non specifichi un argomento per
CMD
, Docker eseguirà sempre il comando in formato exec, ad es.CMD <command>
.
Se hai appena iniziato, la differenziazione tra queste due invocazioni di comando non avrà molta importanza, ma man mano che diventerai più avanzato, vedrai presto vantaggi e svantaggi in ciascuna.
Esecuzione dei comandi di avvio
Entriamo ora nel vivo di questo tutorial e sporchiamoci le mani esaminando alcuni esempi di esecuzione di comandi di avvio all'interno di un Dockerfile ENTRYPOINT
e istruzioni CMD.
1. Apri il Dockerfile che hai creato in precedenza nel tuo editor di testo preferito.
2. Copia e incolla il contenuto del Dockerfile di esempio nel tuo Dockerfile, come mostrato di seguito, e salvalo.
Questo Dockerfile crea un livello usando ubuntu:20.04
come immagine di base. Quindi dice a Docker di invocare echo
comando passandogli il Hello world
argomento per entrambi i Dockerfile CMD
e ENTRYPOINT
istruzioni usando exec
e shell
modulo.
FROM ubuntu:20.04
# CMD Instruction
CMD ["echo", "Hello world"] # Exec Form
CMD echo "Hello world" # Shell Form
# ENTRYPOINT Instruction
ENTRYPOINT ["echo", "Hello world"] # Exec Form
ENTRYPOINT echo "Hello world" # Shell Form
3. Nella ~/docker directory, crea la nuova immagine eseguendo docker build
e chiamalo demo
. Il comando sotto tag l'immagine come demo
e cerca un Dockerfile nella directory di lavoro corrente (.
).
docker build -t demo .
4. Ora, esegui un contenitore utilizzando l'immagine, quindi esegui un contenitore Docker basato sull'immagine Docker creata in precedenza. Ora vedrai che il contenitore restituisce Hello world
che proveniva dal CMD
istruzioni fornite nel Dockerfile.
docker run -it demo
Utilizzo di variabili in un Dockerfile
A volte potresti non conoscere gli argomenti esatti della riga di comando da passare al comando in anticipo. Gli argomenti che devi passare a un comando vengono esposti solo in fase di esecuzione. Invece di assegnare staticamente argomenti di comando, puoi acquisire e passare tali argomenti a comandi con variabili.
Puoi usare solo le variabili Dockerfile in
shell
modulo. Docker non supporta le variabili nel comando invocato tramiteexec
modulo.
Apri nuovamente il Dockerfile nel tuo editor di testo preferito, sostituisci tutto all'interno con la seguente serie di comandi e salvalo.
Noterai che questa volta Dockerfile utilizza variabili di ambiente e viene mostrato utilizzando ENV
. Nell'esempio seguente, Dockerfile sta definendo una variabile di ambiente chiamata name
con un valore di friend
. Una volta creata, questa variabile di ambiente viene quindi referenziata tramite $name
.
Quando Docker esegue un container basato su questo Dockerfile, invocherà echo
comando e passa l'argomento di Welcome, friend
.
FROM ubuntu:20.04
ENV name friend
CMD echo "Welcome, $name"
# or
## ENTRYPOINT echo "Welcome, $name"
Ora crea l'immagine Docker ed esegui di nuovo il contenitore fornendo opzionalmente un nome tag di shellform
. Noterai che Docker ha invocato echo
comando e restituito l'output previsto.
Combinazione delle istruzioni Dockerfile ENTRYPOINT e CMD
Per la maggior parte del tempo, invocherai i comandi di avvio nelle istruzioni CMD o ENTRYPOINT. Dopotutto, puoi invocare tutti i comandi che desideri utilizzando ciascun metodo. Ma puoi anche invocare un singolo comando e "integrarlo" usando entrambe le istruzioni.
Basandosi sugli esempi precedenti, forse hai un Dockerfile che assomiglia all'esempio seguente. Così com'è, se crei un'immagine ed esegui un contenitore da quell'immagine, Docker invocherà l'echo
comando e restituisci Hello
.
FROM ubuntu:20.04
ENTRYPOINT ["echo", "Hello"]
Forse hai un altro argomento che vorresti passare a echo
comando ma non subito. Forse ti piacerebbe farlo più in basso nel Dockerfile. Chiamando il CMD
istruzioni senza un comando, puoi farlo.
Quando specifichi un comando da eseguire tramite il
ENTRYPOINT
istruzione seguita dalCMD
istruzione, Docker assume automaticamente il valore passato aCMD
è un argomento; non un comando.
Ora aggiungi un CMD
riferimento all'istruzione senza un comando, solo un argomento chiamato world
, come mostrato di seguito.
FROM ubuntu:20.04
ENTRYPOINT ["echo", "Hello"]
CMD ["world"]
Le istruzioni Combining devono sempre essere scritte in formato exec a causa del suo comportamento "array like" di specificare valori separati singolarmente da virgole rispetto a tutti in una stringa.
Dopo aver creato l'immagine ed eseguito il contenitore dall'immagine, puoi vederlo invece di due righe di output (Hello
e world
), Docker ne restituisce solo uno che significa solo un singolo echo
invocazione del comando.
Conclusione
Ora dovresti avere una buona conoscenza dell'esecuzione dei comandi di avvio del contenitore Docker tramite il CMD
e ENTRYPOINT
Istruzioni per il file Docker. Ogni istruzione è leggermente diversa ma svolge lo stesso compito e può anche essere utilizzata insieme.
Riesci a pensare a uno scenario in cui preferiresti usare CMD
su ENTRYPOINT
eseguire un comando di avvio?