Uno dei comandi essenziali di Docker è l'ispezione della finestra mobile. Ti consente di estrarre informazioni su vari oggetti docker, sapere come usarlo è qualcosa di TUTTI dovrebbe sapere.
Nel caso te lo stavi chiedendo, gli oggetti o le risorse Docker sono semplicemente cose come contenitori, volumi, reti ecc.
Il principale punto di forza di inspect
deriva dalle sue capacità di formattazione.
Ad esempio, puoi estrarre l'indirizzo IP di un container in esecuzione ispezionandolo e formattando in modo specifico.
➟ docker container inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' nginx
172.17.0.2
Docker utilizza i modelli go per formattare l'output.
In questo articolo, prima esaminerò le basi del comando Docker inspect, quindi mi concentrerò su come formattare l'output in base alle tue esigenze specifiche.
Cosa fa Docker inspect?
Inspect ti fornisce una serie di metadati su tutti i diversi oggetti gestiti dalla finestra mobile. Il tipo di informazioni varia da oggetto a oggetto.
Ad esempio, se ispezioni un volume, otterrai informazioni relative a quando è stato creato, al driver del volume in uso, alla posizione nel filesystem host, alle etichette, ecc.
Se stai ispezionando una rete, otterrai elementi come la subnet, il gateway, i container connessi e i relativi indirizzi IP, etichette e altre informazioni.
Per capire meglio cosa prevede inspect per un determinato oggetto, ti consiglio di eseguire i comandi e vedere di persona.
Quali sono gli oggetti che possono essere ispezionati?
Nella finestra mobile, un oggetto o un tipo di oggetto sono tutti i costrutti controllati dalla finestra mobile. Ciò include quanto segue:-
- Contenitori.
- Immagini.
- Reti.
- Volumi.
- Contesti.
- Plugin.
- Nodi (oggetto sciame).
- Servizi (oggetto sciame).
- Segreti (oggetto sciame).
- Configurazioni (oggetto sciame).
Utilizzo del comando di ispezione Docker
Ci sono due modi in cui puoi usare inspect
sottocomando.
docker inspect [object] [options]
docker [object_type] inspect [object] [options]
Il secondo metodo è quello che dovresti usare sempre . Il inspect
il sottocomando fornisce un output JSON, ne parlerò tra un momento.
Crea un volume denominato unique
.
docker volume create unique
Ora crea una rete con lo stesso nome, unique
.
docker network create unique
Ora proviamo a ispezionare l'oggetto denominato unique
utilizzando la prima sintassi.
docker inspect unique
Il mio risultato:-
➟ docker inspect unique
[
{
"Name": "unique",
"Id": "09a7e2163ee058b1057d95599f764d571ec6a42a5792803dc125e706caa525b0",
"Created": "2021-05-07T15:47:20.341493099+05:30",
"Scope": "local",
"Driver": "bridge",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": {},
"Config": [
{
"Subnet": "172.21.0.0/16",
"Gateway": "172.21.0.1"
}
]
},
"Internal": false,
"Attachable": false,
"Ingress": false,
"ConfigFrom": {
"Network": ""
},
"ConfigOnly": false,
"Containers": {},
"Options": {},
"Labels": {}
}
]
Nel mio sistema, come puoi vedere inspect
ho ispezionato la rete, ma se avessi intenzione di ispezionare il volume?
Questo è il problema con docker inspect
, quando hai due oggetti diversi con lo stesso nome, non puoi semplicemente usare docker inspect [object_name]
. Per ispezionare esattamente ciò che desideri, dovrai utilizzare l'ID dell'oggetto o utilizzare il --type=[object_type]
opzione. Puoi scrivere il comando precedente con --type
opzione in questo modo:-
docker inspect --type=volume unique
Sebbene funzioni, credo che ciò non sia necessario poiché abbiamo già l'altra sintassi. Puoi semplicemente usare il sottocomando specifico dell'oggetto come sto facendo qui:-
docker volume inspect unique
È meno da scrivere e molto più facile da leggere.
Alcuni utili esempi di comandi di ispezione Docker
In questa sezione, registrerò un elenco di query comuni e l'aspetto del comando di ispezione pertinente per ottenere tali informazioni.
Query sui contenitori
Per gli esempi, avrò un contenitore nginx di esempio in esecuzione e tutti i comandi verranno eseguiti su questo contenitore in esecuzione. Il comando che ho usato per eseguire questo contenitore:-
docker container run \
--rm --name nginx \
-p target=80,published=127.0.0.1:8081,protocol=tcp \
-p target=80,published=[::1]:8081,protocol=tcp \
-e ENV_VAR=somevalue \
-e ENV_VAR2=linux \
-v $PWD:/mnt:ro \
-v /tmp:/tmp:ro \
-d nginx
Puoi ottenere l'ID del contenitore usando il seguente comando:-
docker container inspect -f '{{.Id}}' [container_name]
Esempio:-
➟ docker container inspect -f '{{.Id}}' nginx
0409779fc2d976387170d664a6aed5ee80a460f8a8dd02c44a02af97df0bb956
Il processo principale del contenitore è fondamentalmente ENTRYPOINT
+ CMD
.
docker container inspect -f '{{printf "%s " .Path}}{{range .Args}}{{printf "%s " .}}{{end}}' [container_name|id]
Esempio:-
➟ docker container inspect -f '{{printf "%s " .Path}}{{range .Args}}{{printf "%s " .}}{{end}}' nginx
/docker-entrypoint.sh nginx -g daemon off;
Il comando seguente elenca tutte le associazioni di porta da contenitore a host.
docker container inspect -f '{{range $target, $published := .NetworkSettings.Ports}}{{range $published}}{{printf "%s -> %s:%s\n" $target .HostIp .HostPort}}{{end}}{{end}}' [container_name|id]
Esempio:-
➟ docker container inspect -f '{{range $target, $published := .NetworkSettings.Ports}}{{range $published}}{{printf "%s -> %s:%s\n" $target .HostIp .HostPort}}{{end}}{{end}}' nginx
80/tcp -> ::1:8081
80/tcp -> 127.0.0.1:8081
Puoi ottenere lo stesso risultato con docker container port
comando.
Un container può essere connesso a più reti, invece di stampare uno di quei tanti indirizzi IP, puoi stampare tutti quegli indirizzi IP con questo comando.
docker container inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' [container_name|id]
Esempio:-
➟ docker container inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' nginx
172.17.0.2
Puoi anche elencare la variabile di ambiente di un container.
docker container inspect -f '{{range .Config.Env}}{{printf "%s\n" .}}{{end}}' [container_name|id]
Esempio:-
➟ docker container inspect -f '{{range .Config.Env}}{{printf "%s\n" .}}{{end}}' nginx
ENV_VAR=somevalue
ENV_VAR2=linux
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
NGINX_VERSION=1.19.10
NJS_VERSION=0.5.3
PKG_RELEASE=1~buster
Il comando seguente stampa i mount di collegamento in questo formato, "[sorgente] -> [destinazione], modalità:[modalità]".
docker container inspect -f '{{range .Mounts}}{{printf "%s -> %s, mode: %s\n" .Source .Destination .Mode}}{{end}}' [container_name|id]
Esempio:-
➟ docker container inspect -f '{{range .Mounts}}{{printf "%s -> %s, mode: %s\n" .Source .Destination .Mode}}{{end}}' nginx
/home/debdut -> /mnt, mode: ro
/tmp -> /tmp, mode: ro
Query sul volume
Non c'è molto da ispezionare un volume se non per conoscere la posizione dell'host, che è in data-dir/volumes
. Puoi ottenere queste informazioni con il seguente comando:-
docker volume inspect -f '{{.Mountpoint}}' [volume_name|id]
Esempio:-
➟ docker volume create unique
unique
~
➟ docker volume inspect -f '{{.Mountpoint}}' unique
/var/lib/docker/volumes/unique/_data
Query di rete
Ci sono due domande che personalmente mi ritrovo a fare frequentemente, una è conoscere una sottorete di rete e tutti i container che sono connessi a quella rete e gli IP ad essi associati.
Per questo ho creato una semplice rete con la docker network create unique
comando.
Per ottenere la sottorete, utilizzare il seguente comando:-
docker network inspect -f '{{range .IPAM.Config}}{{.Subnet}}{{end}}' [network_name|id]
Esempio:-
➟ docker network inspect -f '{{range .IPAM.Config}}{{.Subnet}}{{end}}' unique
172.21.0.0/16
Il comando è simile a questo,
docker network inspect -f '{{range .Containers}}{{printf "%s -> %s\n" .Name .IPv4Address}}{{end}}' [network_name|id]
Esempio:-
➟ docker network inspect -f '{{range .Containers}}{{printf "%s -> %s\n" .Name .IPv4Address}}{{end}}' unique
cranky_wescoff -> 172.21.0.5/16
nginx -> 172.21.0.2/16
upbeat_carson -> 172.21.0.3/16
objective_jones -> 172.21.0.4/16
Formattazione dell'output del comando Docker inspect
inspect
ci fornisce un array JSON per l'output, che puoi filtrare usando qualcosa come jq
. Quindi, se hai esperienza con jq
, potresti semplicemente usarlo. Il problema con jq
è che non viene preinstallato nella maggior parte delle distribuzioni Linux, mentre il meccanismo di formattazione predefinito di docker .. inspect
è già lì ed è molto potente.
Docker usa i modelli go per formattare il suo output. Questo articolo non riguarderà i go-template, ma se vuoi saperne di più, puoi leggerlo qui.
Internamente i JSON sono rappresentati utilizzando varie strutture di dati Go. Ecco perché i modelli go funzionano effettivamente con i tipi di dati go. Dal momento che non voglio spiegare quali sono queste strutture di dati, invece di usare quei termini, userò termini JSON per renderlo più comprensibile.
Estrazione di campi semplici
Considera un oggetto JSON come il seguente:-
{
"mary": 43,
"john": 44
}
Supponiamo di voler estrarre le informazioni associate alla chiave mary
. Per fare ciò, ciò che usi è la notazione punto [.], in cui anteponi alla chiave un punto e aggiungi le chiavi in modo ricorsivo per qualsiasi chiave nidificata. È lo stesso di jq
. Quindi .mary
qui sarebbero 43.
Considera ora il seguente JSON.
{
"mary": {
"jane": 43,
"soyas": 56
},
"john": 65
}
In questo caso .mary.jane
sarebbe 43, e allo stesso modo .mary.soyas
sarebbero 56.
Una sintassi simile può essere utilizzata con i modelli go. Per formattare l'output, devi passare il modello a -f
o --format
opzione del inspect
sottocomando. Rivediamo l'output dell'ispezione del volume.
[
{
"CreatedAt": "2021-05-07T15:53:10+05:30",
"Driver": "local",
"Labels": {},
"Mountpoint": "/var/lib/docker/volumes/unique/_data",
"Name": "unique",
"Options": {},
"Scope": "local"
}
]
Se vuoi conoscere il Mountpoint
, useresti il seguente comando:-
docker volume inspect -f '{{.Mountpoint}}' unique
➟ docker volume inspect -f '{{.Mountpoint}}' unique
/var/lib/docker/volumes/unique/_data
Probabilmente stai notando le parentesi graffe proprio lì, sono come blocchi, le espressioni sono incapsulate all'interno di questi blocchi.
Proviamo ora qualcosa annidato. Ispeziona la rete e cerca il IPAM
sezione.
➟ docker network inspect unique
<snipped>
"IPAM": {
"Driver": "default",
"Options": {},
"Config": [
<snipped>
Guardando questo puoi facilmente capire qual è il driver di questa rete. Ma invece di cercarlo in questo modo, puoi formattarlo dall'intero output JSON.
Nota il Driver
la chiave è nidificata all'interno di IPAM
. Quindi l'espressione punto per estrarre il driver sarebbe .IPAM.Driver
. Guardalo in azione:-
➟ docker network inspect -f '{{.IPAM.Driver}}' unique
default
Ciclo su oggetti o elenchi (intervallo)
Gli oggetti JSON sono come array associativi in Bash, o Hash, dove le chiavi sono stringhe e i valori possono essere di qualsiasi tipo di dati.
Per farti capire questo un po' più facilmente, inizierò con un esempio pratico. Considera il .NetworkSettings.Networks
sezione in un risultato di ispezione di un contenitore. Elenca le reti a cui è connesso il container e, per ciascuna rete, alcuni dettagli più associati come l'indirizzo IP.
Pensa se qualcuno ti chiede di comunicargli l'indirizzo IP di un container. Scegliere una sola rete e l'IP associato non ha molto senso, sarebbe meglio elencare tutti gli indirizzi IP associati a tutte le reti.
Puoi ottenere questo risultato con un semplice ciclo bash for se conosci già i nomi di rete. Come nel mio caso, posso fare qualcosa del genere:-
for network in bridge unique; do
docker container inspect -f \
"{{.NetworkSettings.Networks.$network.IPAddress}}" nginx
done
Ma ovviamente questo è limitante su larga scala poiché non possiamo ricordare sempre tutti i nomi di rete.
Puoi mitigare questo problema utilizzando l'azione del modello range
. range
va su una mappa (un array associativo o un oggetto JSON) e ci fornisce non la chiave, ma i valori per ogni iterazione (questo comportamento è modificabile).
Quindi, in questo caso, puoi scrivere un blocco come {{range .NetworkSettings.Networks}}
per scorrere i valori di ciascuna rete o i dati associati a ciascuna rete, e da questo puoi estrarre l'indirizzo IP come faresti da una normale struttura simile a JSON, ovvero {{.IPAddress}}}
. Una cosa da ricordare è di terminare sempre l'intero modello che inizia con range
, con {{end}}
.
Mettendo tutto insieme, puoi riscrivere il precedente ciclo for proprio in questo modo:-
docker container inspect -f \
'{{range .NetworkSettings.Networks}}
{{.IPAddress}}{{end}}' nginx
Esempio di output:-
➟ docker container inspect -f \
> '{{range .NetworkSettings.Networks}}
> {{.IPAddress}}{{end}}' nginx
172.17.0.2
172.21.0.2
Utilizzo dell'index
funzione su array e oggetti
Puoi usare l'index
funzione per estrarre parti dall'oggetto o dall'array JSON. Se la struttura è un oggetto JSON, dovresti utilizzare {{index .Field "key"}}
, se la struttura è un array JSON, dovresti utilizzare {{index .Field index}}
.
Nell'esempio precedente hai stampato tutti gli indirizzi IP di un container. Supponiamo che tu conosca una delle reti a cui è connesso (bridge) e desideri stampare l'indirizzo IP associato a quella rete. Puoi farlo con index
funziona in questo modo:-
docker container inspect -f '{{(index .NetworkSettings.Networks "bridge").IPAddress}}' nginx
Uscita:-
➟ docker container inspect -f '{{(index .NetworkSettings.Networks "bridge").IPAddress}}' nginx
172.17.0.2
Utilizzo di json
funzione
I dati esportati dopo la formattazione non in JSON, è in una struttura di dati go. Ma puoi convertirlo in JSON usando json
funzione.
Il livello superiore dell'oggetto JSON è .
. Quindi per stamparlo faresti qualcosa del genere:-
docker network inspect -f '{{.}}' unique
➟ docker network inspect -f '{{.}}' unique
{unique 09a7e2163ee058b1057d95599f764d571ec6a42a5792803dc125e706caa525b0 2021-05-07 15:47:20.341493099 +0530 IST local bridge false {default map[] [{172.21.0.0/16 172.21.0.1 map[]}]} false false false {} false map[2646cbbde5efc218bb6f3a5c882f8eb9e3e4331d090ad46ccc0a2eec9c2eea1b:{nginx c0291394a48f7e8e8aa98fd31631eb00e68daacbee9cf24bac530f16359d051d 02:42:ac:15:00:02 172.21.0.2/16 }] map[] map[] [] map[]}
Quello che stai vedendo qui è una grande struttura composta da altri tipi di dati e mappe di base di strutture. Questi non sono molto leggibili, né utilizzabili al di fuori di go. Ma puoi convertirli in JSON usando json
funzione. Basta anteporre un campo con json
come sto facendo qui:-
➟ docker network inspect -f '{{json .}}' unique
➟ docker network inspect -f '{{json .}}' unique
{"Name":"unique","Id":"09a7e2163ee058b1057d95599f764d571ec6a42a5792803dc125e706caa525b0","Created":"2021-05-07T15:47:20.341493099+05:30","Scope":"local","Driver":"bridge","EnableIPv6":false,"IPAM":{"Driver":"default","Options":{},"Config":[{"Subnet":"172.21.0.0/16","Gateway":"172.21.0.1"}]},"Internal":false,"Attachable":false,"Ingress":false,"ConfigFrom":{"Network":""},"ConfigOnly":false,"Containers":{"2646cbbde5efc218bb6f3a5c882f8eb9e3e4331d090ad46ccc0a2eec9c2eea1b":{"Name":"nginx","EndpointID":"c0291394a48f7e8e8aa98fd31631eb00e68daacbee9cf24bac530f16359d051d","MacAddress":"02:42:ac:15:00:02","IPv4Address":"172.21.0.2/16","IPv6Address":""}},"Options":{},"Labels":{}}
Per farlo sembrare un po' migliore invialo a jq
.
➟ docker network inspect -f '{{json .}}' unique | jq
{
"Name": "unique",
"Id": "09a7e2163ee058b1057d95599f764d571ec6a42a5792803dc125e706caa525b0",
"Created": "2021-05-07T15:47:20.341493099+05:30",
"Scope": "local",
"Driver": "bridge",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": {},
"Config": [
{
"Subnet": "172.21.0.0/16",
"Gateway": "172.21.0.1"
}
]
},
"Internal": false,
"Attachable": false,
"Ingress": false,
"ConfigFrom": {
"Network": ""
},
"ConfigOnly": false,
"Containers": {
"2646cbbde5efc218bb6f3a5c882f8eb9e3e4331d090ad46ccc0a2eec9c2eea1b": {
"Name": "nginx",
"EndpointID": "c0291394a48f7e8e8aa98fd31631eb00e68daacbee9cf24bac530f16359d051d",
"MacAddress": "02:42:ac:15:00:02",
"IPv4Address": "172.21.0.2/16",
"IPv6Address": ""
}
},
"Options": {},
"Labels": {}
}
È così? Assolutamente no. Consiglio vivamente di leggere come utilizzare i modelli go.
Qui ho provato a iniziare a usarlo senza dover sapere molto sui modelli go. Spero di esserci riuscito.
Per qualsiasi chiarimento non esitare ad utilizzare la sezione commenti.