<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	
	xmlns:georss="http://www.georss.org/georss"
	xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#"
	>

<channel>
	<title>Immagini Archivi - Docker Tutorial</title>
	<atom:link href="https://www.dockertutorial.it/category/tutorial/immagini/feed/" rel="self" type="application/rss+xml" />
	<link>https://www.dockertutorial.it</link>
	<description></description>
	<lastBuildDate>Wed, 22 Dec 2021 16:58:55 +0000</lastBuildDate>
	<language>it-IT</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	

<image>
	<url>https://www.dockertutorial.it/wp-content/uploads/2020/04/cropped-New-Project-2-32x32.png</url>
	<title>Immagini Archivi - Docker Tutorial</title>
	<link>https://www.dockertutorial.it</link>
	<width>32</width>
	<height>32</height>
</image> 
<site xmlns="com-wordpress:feed-additions:1">186986242</site>	<item>
		<title>Cos&#8217;è un&#8217;immagine?</title>
		<link>https://www.dockertutorial.it/cose-unimmagine/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=cose-unimmagine</link>
		
		<dc:creator><![CDATA[Fabio Ros]]></dc:creator>
		<pubDate>Sun, 10 May 2020 13:17:53 +0000</pubDate>
				<category><![CDATA[Immagini]]></category>
		<category><![CDATA[Tutorial]]></category>
		<guid isPermaLink="false">http://dockertutorial.it/?p=283</guid>

					<description><![CDATA[<p>Questo capitolo è dedicato ad uno degli argomenti più importanti di questo corso. Le immagini. Iniziamo con la definizione tratta dal sito ufficiale: “An Image...</p>
<p>L'articolo <a rel="nofollow" href="https://www.dockertutorial.it/cose-unimmagine/">Cos&#8217;è un&#8217;immagine?</a> proviene da <a rel="nofollow" href="https://www.dockertutorial.it">Docker Tutorial</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>Questo capitolo è dedicato ad uno degli argomenti più importanti di questo corso. Le immagini. <br>Iniziamo con la definizione tratta dal sito ufficiale:</p>



<blockquote class="wp-block-quote"><p><br>“An Image is an ordered collection of root filesystem changes and the corresponding execution parameters for use within a container runtime.”</p><cite><a href="https://github.com/moby/moby/blob/master/image/spec/v1.2.md" class="aioseop-link">Moby Image readme.md v1.2</a></cite></blockquote>



<p><br>Tradotto: “Un’immagine è una <strong>raccolta ordinata di modifiche al filesystem di root e dei corrispondenti parametri di esecuzione da utilizzare all’interno di un container runtime</strong>.”</p>



<p>Mi rendo conto che da questa definizione si possa capire ben poco, cerco di rendere questa definizione più comprensibile.</p>



<p>Un immagine è fondamentalmente un <strong>pacchetto</strong> che contiene: <strong>Codice binario di un’App</strong>, <strong>dipendenze</strong> necessarie, <strong>Metadati</strong> e <strong>Istruzioni</strong> su come eseguire l’App.<br>Fondamentalmente è tutto qui.</p>



<p>L’applicazione verrà eseguita in un container, come <strong>processo dell’host</strong>. Questo significa che il kernel su cui gira il container creato a partire da questa immagine, è quello dell’host. </p>



<p class="wp-block-coblocks-highlight"><mark class="wp-block-coblocks-highlight__content">Le immagini e l’host condividono il kernel.</mark></p>



<p>Un immagine può tuttavia utilizzare un Sistema Operativo diverso dall’host <strong>purché condividano il kernel</strong>, ad esempio potrei avere un host RedHat ed un container Ubuntu che condividono il kernel linux.</p>



<p><br>Spesso le immagini contengono <strong>svariate utility</strong> dei sistemi operativi di cui fanno parte, fornendo un ambiente il più completo o specializzato possibile. Questo determina inesorabilmente un aumento della loro dimensione. Un esempio è l’immagine di <strong>Ubuntu</strong>.<br>Di contro, possono essere anche molto <strong>scarne</strong>, privilegiando la leggerezza e lasciando agli utilizzatori l’onere di aggiungere i pacchetti necessari. Un esempio di questa categoria è <strong>Alpine</strong>.</p>



<p>—<br><strong>Prosegui su:</strong> <a href="http://dockertutorial.it/come-fatta-unimmagine/" class="aioseop-link">Com&#8217;è fatta un&#8217;immagine</a></p>



<p>Immagine: <a href="https://it.freepik.com/eberhard9" class="aioseop-link">eberhard9 &#8211; it.freepik.com</a></p>



<p></p>
<p>L'articolo <a rel="nofollow" href="https://www.dockertutorial.it/cose-unimmagine/">Cos&#8217;è un&#8217;immagine?</a> proviene da <a rel="nofollow" href="https://www.dockertutorial.it">Docker Tutorial</a>.</p>
]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">283</post-id>	</item>
		<item>
		<title>Com&#8217;è fatta un&#8217;immagine?</title>
		<link>https://www.dockertutorial.it/come-fatta-unimmagine/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=come-fatta-unimmagine</link>
		
		<dc:creator><![CDATA[Fabio Ros]]></dc:creator>
		<pubDate>Sun, 10 May 2020 13:33:30 +0000</pubDate>
				<category><![CDATA[Immagini]]></category>
		<category><![CDATA[Tutorial]]></category>
		<guid isPermaLink="false">http://dockertutorial.it/?p=291</guid>

					<description><![CDATA[<p>Un immagine non è da intendere come un blocco unico, ma come una pila di livelli incrementali detti &#8220;layer&#8220;. L’insieme ordinato dei layer, costituisce il...</p>
<p>L'articolo <a rel="nofollow" href="https://www.dockertutorial.it/come-fatta-unimmagine/">Com&#8217;è fatta un&#8217;immagine?</a> proviene da <a rel="nofollow" href="https://www.dockertutorial.it">Docker Tutorial</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>Un immagine non è da intendere come un blocco unico, ma come una<strong> pila di livelli incrementali</strong> detti &#8220;<strong>layer</strong>&#8220;.</p>



<p>L’<strong>insieme ordinato dei layer</strong>, costituisce il singolo oggetto immagine.&nbsp;</p>



<p>Questa struttura ha numerosi vantaggi; Il principale è che i layer sono <strong>riusabili</strong>.&nbsp;</p>



<p>Ad esempio, se più immagini sono costruite a partire da un’immagine della stessa versione di Ubuntu, Docker non scaricherà ogni volta una nuova copia di tale immagine ma userà la stessa per costruire tutte le immagini coinvolte.</p>



<h2>Come funziona la condivisione dei layer?</h2>



<p>Alla prima richiesta l’immagine di partenza verrà scaricata, alle successive sarà recuperata dal repository locale dell’host. Per &#8220;repository locale dell&#8217;host&#8221; intendo il sistema che colleziona e organizza le immagini presenti sul device che sta scaricando le immagini.</p>



<p>A seconda delle dipendenze la dimensione di un’immagine può variare di molto. Si può variare da pochi KiloByte a svariati GigaByte.</p>



<p>E’ anche possibile creare un’immagine a partire da un container, facendone una sorta di fotografia. Per fare ciò si usa il comando <a href="https://docs.docker.com/engine/reference/commandline/commit/" class="aioseop-link">docker container commit</a>. <br>Va detto però che è un caso che trova applicazione solo in contesti particolari.</p>



<p>Per chi come me si occupa di sviluppare software, penso possa essere utile fare un parallelo (per cercare di dare un’idea, non una definizione). Pensate alle immagini come a delle classi e i container come degli oggetti, ovvero delle immagini istanziate.</p>



<p><br>In realtà anche le<strong> immagini vengono costruite</strong>, producendo un binario, ma questo avviene <strong>build-time</strong>. I container invece vengono costruiti run-time.</p>



<p>—<br><strong>Prosegui su:</strong> <a href="http://dockertutorial.it/cosa-succede-quando-scarichiamo-unimmagine/" class="aioseop-link">Cosa succede quando scarichiamo un&#8217;immagine</a></p>



<p>Immagine: <a href="https://it.freepik.com/foto-vettori-gratuito/legno">Legno foto creata da wirestock &#8211; it.freepik.com</a></p>
<p>L'articolo <a rel="nofollow" href="https://www.dockertutorial.it/come-fatta-unimmagine/">Com&#8217;è fatta un&#8217;immagine?</a> proviene da <a rel="nofollow" href="https://www.dockertutorial.it">Docker Tutorial</a>.</p>
]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">291</post-id>	</item>
		<item>
		<title>Cosa succede quando scarichiamo un&#8217;immagine</title>
		<link>https://www.dockertutorial.it/cosa-succede-quando-scarichiamo-unimmagine/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=cosa-succede-quando-scarichiamo-unimmagine</link>
		
		<dc:creator><![CDATA[Fabio Ros]]></dc:creator>
		<pubDate>Sun, 10 May 2020 14:04:34 +0000</pubDate>
				<category><![CDATA[Immagini]]></category>
		<category><![CDATA[Tutorial]]></category>
		<guid isPermaLink="false">http://dockertutorial.it/?p=310</guid>

					<description><![CDATA[<p>In questa sezione, andremo più in dettaglio su alcuni aspetti, prevalentemente a basso livello, riguardanti le immagini. Quando scarichiamo un’immagine, ne specifichiamo solo il nome...</p>
<p>L'articolo <a rel="nofollow" href="https://www.dockertutorial.it/cosa-succede-quando-scarichiamo-unimmagine/">Cosa succede quando scarichiamo un&#8217;immagine</a> proviene da <a rel="nofollow" href="https://www.dockertutorial.it">Docker Tutorial</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>In questa sezione, andremo più in dettaglio su alcuni aspetti, prevalentemente a basso livello, riguardanti le immagini.</p>



<p>Quando scarichiamo un’immagine, ne specifichiamo solo il <strong>nome</strong> ed in alcuni casi il <strong>tag</strong> identificativo. Questo può far pensare di aver a che fare con un oggetto unico.</p>



<p>Nella sezione &#8220;<a href="http://dockertutorial.it/come-fatta-unimmagine/" class="aioseop-link">Com&#8217;è fatta un&#8217;immagine</a>&#8221; abbiamo visto che non è così, siamo a conoscenza del fatto che esiste un meccanismo che compone le immagini per layer successivi.</p>



<p>Tuttavia vale la pene vederlo con i nostri occhi scaricando due release consecutive della stessa immagine. Facciamo un esempio con <a href="https://redis.io/" class="aioseop-link">redis</a> basato su Alpine:</p>



<pre class="wp-block-preformatted">docker image pull redis:5-alpine</pre>



<p>ottenendo questo output:</p>



<pre class="wp-block-preformatted">5-alpine: Pulling from library/redis
cbdbe7a5bc2a: Already exists 
dc0373118a0d: Pull complete 
cfd369fe6256: Pull complete 
3e45770272d9: Pull complete 
558de8ea3153: Pull complete 
a2c652551612: Pull complete 
Digest: sha256:83a3af36d5e57f2901b4783c313720e5fa3ecf0424ba86ad9775e06a9a5e35d0
Status: Downloaded newer image for redis:5-alpine
docker.io/library/redis:5-alpine</pre>



<p>Già da qui notiamo che vengono scaricati più frammenti e non un blocco unico. Qualcosa dovrebbe già farci sospettare che l’ipotesi dell’immagine a blocco unico comincia a scricchiolare.<br>Possiamo inoltre vedere già il primo esempio di riuso (dalla riga &#8220;cbdbe7a5bc2a: Already exists&#8221;). Dato che stiamo utilizzando le versioni Alpine, probabilmente stiamo riutilizzando il layer del kernel Alpine da un&#8217;immagine scaricata in precedenza (<a href="http://dockertutorial.it/container-le-basi/" class="aioseop-link">qui</a>).<br>Scarichiamo ora la versione 6-alpine con:</p>



<pre class="wp-block-preformatted">docker image pull redis:6-alpine</pre>



<p>ottenendo questo output:</p>



<pre class="wp-block-preformatted">6-alpine: Pulling from library/redis
cbdbe7a5bc2a: Already exists 
dc0373118a0d: Already exists 
cfd369fe6256: Already exists 
e5396613619b: Pull complete 
6809b5ad2cd4: Pull complete 
386ecfe54d06: Pull complete 
Digest: sha256:2586f31f74ac1d7dc6f6c7eabca42f09bba5ec9911fc519d55fbd7508a9c4f01
Status: Downloaded newer image for redis:6-alpine
docker.io/library/redis:6-alpine</pre>



<p>Qui il riuso diventa evidente. Alcuni &#8220;<strong>frammenti</strong>&#8221; della seconda immagine sono stati <strong>recuperati dalla cache del repository locale</strong>.</p>



<p>C&#8217;è da dire che un utilizzatore di Docker alle prime armi, avrebbe potuto lanciare diversi container senza essere consapevole di tale aspetto. Docker rende tale aspetto assolutamente trasparente, ma è indispensabile conoscerlo per evitare situazioni spiacevoli.</p>



<h2>Come vengono aggregati i layer?</h2>



<p>L&#8217;aggregazione dei livelli (layer) avviene mediante il concetto di <strong>Union File System</strong>.</p>



<p>Mi piacerebbe andare più a fondo sulla questione (parlando di aufs, overlay2, ecc), ma non vorrei andare troppo fuori tema.</p>



<p>Quello che dobbiamo portarci a casa è che <strong>ogni layer può aggiungere file, cartelle o metadati al prodotto dei layer precedenti</strong>. </p>



<p>I layer vengono applicati uno alla volta, in ordine. Al termine dell’applicazione di un layer X, la struttura file risultante sarà la fusione di tutte le modifiche apportate da tutti i layer precedenti e dal layer X. </p>



<p><strong>Per il container</strong>, la struttura file su cui si poggia può essere intesa come un’<strong>entità singola</strong>.</p>



<p>—<br><strong>Prosegui su:</strong> <a href="http://dockertutorial.it/analizzare-la-struttura-di-unimmagine/" class="aioseop-link">Analizzare la struttura di un&#8217;immagine</a></p>



<p>Immagine: <a href="https://it.freepik.com/foto-vettori-gratuito/viaggio">Viaggio foto creata da freepik &#8211; it.freepik.com</a></p>
<p>L'articolo <a rel="nofollow" href="https://www.dockertutorial.it/cosa-succede-quando-scarichiamo-unimmagine/">Cosa succede quando scarichiamo un&#8217;immagine</a> proviene da <a rel="nofollow" href="https://www.dockertutorial.it">Docker Tutorial</a>.</p>
]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">310</post-id>	</item>
		<item>
		<title>Analizzare la struttura di un&#8217;immagine</title>
		<link>https://www.dockertutorial.it/analizzare-la-struttura-di-unimmagine/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=analizzare-la-struttura-di-unimmagine</link>
		
		<dc:creator><![CDATA[Fabio Ros]]></dc:creator>
		<pubDate>Sun, 10 May 2020 14:53:57 +0000</pubDate>
				<category><![CDATA[Immagini]]></category>
		<category><![CDATA[Tutorial]]></category>
		<guid isPermaLink="false">http://dockertutorial.it/?p=325</guid>

					<description><![CDATA[<p>La CLI di Docker mette a disposizione un comando per analizzare tutti i layer che compongono un’immagine. docker image history Attraverso questo comando è possibile...</p>
<p>L'articolo <a rel="nofollow" href="https://www.dockertutorial.it/analizzare-la-struttura-di-unimmagine/">Analizzare la struttura di un&#8217;immagine</a> proviene da <a rel="nofollow" href="https://www.dockertutorial.it">Docker Tutorial</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>La CLI di Docker mette a disposizione un comando per analizzare tutti i layer che compongono un’immagine.</p>



<pre class="wp-block-preformatted">docker image history</pre>



<p>Attraverso questo comando è possibile<strong> visualizzare tutte le modifiche che un’immagine ha subito</strong>. Per essere precisi, va detto che non è una lista precisa di tutti i layer, alcune istruzioni (ad esempio ENV) non saranno tracciate, ma in linea di massima pensare questa lista come l’elenco dei layer è una buona approssimazione.</p>



<p>Credo che il miglior modo di vedere questo aspetto sia con un esempio. Prendiamo l’immagine di ubuntu.</p>



<p>Per scaricarla eseguiamo il comando docker image pull specificando il nome dell’immagine, in questo caso ubuntu.</p>



<pre class="wp-block-preformatted">docker image pull ubuntu</pre>



<p>Nel mio caso, l&#8217;output è:</p>



<pre class="wp-block-preformatted">Using default tag: latest
latest: Pulling from library/ubuntu
d51af753c3d3: Pull complete 
fc878cd0a91c: Pull complete 
6154df8ff988: Pull complete 
fee5db0ff82f: Pull complete 
Digest: sha256:747d2dbbaaee995098c9792d99bd333c6783ce56150d1b11e333bbceed5c54d7
Status: Downloaded newer image for ubuntu:latest
docker.io/library/ubuntu:latest</pre>



<p>Non abbiamo specificato il tag, quindi è stata scaricata la versione taggata come latest. Eseguiamo quindi il comando</p>



<pre class="wp-block-preformatted">docker image history ubuntu:latest</pre>



<p>Ottenendo questo output:</p>



<pre class="wp-block-preformatted">IMAGE               CREATED             CREATED BY                                      SIZE                COMMENT
1d622ef86b13        4 weeks ago         /bin/sh -c #(nop)  CMD ["/bin/bash"]            0B                  
&lt;missing>           4 weeks ago         /bin/sh -c mkdir -p /run/systemd &amp;&amp; echo 'do…   7B                  
&lt;missing>           4 weeks ago         /bin/sh -c set -xe   &amp;&amp; echo '#!/bin/sh' > /…   811B                
&lt;missing>           4 weeks ago         /bin/sh -c [ -z "$(apt-get indextargets)" ]     1.01MB              
&lt;missing>           4 weeks ago         /bin/sh -c #(nop) ADD file:a58c8b447951f9e30…   72.8MB  </pre>



<p>Osservando l&#8217;output, è possibile notare che alcuni layer lasciano la dimensione dell&#8217;immagine pressoché invariata. Il motivo è che questi ultimi aggiungono solo metadati, senza apportare modifiche ai File.</p>



<p>I layer di questo tipo sono facilmente identificabili poché nell’output del comando docker image history, compaiono con la colonna “SIZE” valorizzata con la stringa “0B”, che sta per zero Byte. </p>



<p>Nella colonna &#8220;CREATED&#8221; si può osservare la data di creazione. In questo caso sono tutte uguali, ma potrebbe non essere sempre così.</p>



<p>I layer sono parte di un’immagine e vengono <strong>caricati su una sorta di repository</strong> detto <strong>registry</strong>. Quello di default per docker si chiama Docker Hub ed è raggiungibile all’indirizzo <a href="https://hub.docker.com/" class="aioseop-link">hub.docker.com</a>. Non mi dilungo oltre sui registry, avremo modo di parlarne più in dettaglio nella lezione dedicata.</p>



<p>Se i layer hanno valorizzazioni diverse nella colonna CREATED, significa che hanno subito variazioni in momenti diversi.</p>



<p>Perché risulti più chiaro, immaginate un repository git. Ogni volta che aggiornate un file esso aggiornerà anche la propria data di ultima modifica. Tuttavia i file che non hanno subito variazioni in quel commit manterranno la data di ultima modifica originaria.</p>



<p>Ora dovrebbe sorgere spontanea una domanda: se parliamo di &#8220;ultima modifica&#8221;, <strong>perché la colonna si chiama &#8220;CREATED&#8221; e non &#8220;UPDATED&#8221;</strong>?</p>



<p>Teniamo a mente che stiamo guardando la struttura che compone l&#8217;immagine e non l&#8217;immagine come pacchetto unico. <br>Fatta questa premessa, la risposta è che un layer costruisce un<strong> nuovo ‘strato’</strong> a <strong>partire dalla fusione degli &#8216;strati&#8217; creati negli step precedenti</strong>. Ricordate lo Union File System?</p>



<p>Il codice binario deve essere <strong>ricostruito</strong>, non solo aggiornato. Da qui l’indicazione di creazione e non solo di aggiornamento. </p>



<p>L’hash che vediamo in testa alla colonna IMAGE è l’hash dell’immagine di ubuntu, tant’è che se eseguiamo docker image ls, vedremo che l’IMAGE ID di ubuntu è lo stesso, ovvero 1d622ef86b13.</p>



<pre class="wp-block-preformatted">docker image ls | grep ubuntu</pre>



<p>Ottenendo questo output:</p>



<pre class="wp-block-preformatted">ubuntu                                  latest              1d622ef86b13        4 weeks ago         73.9MB</pre>



<p>In questo caso ho usato un grep per filtrare solo le righe dell&#8217;output che contengono la stringa ubuntu, per evitare rumore nell&#8217;output.</p>



<p>Per ora non mi spingerei oltre. Credo che in questa fase sia opportuno tralasciare la colonna ‘CREATED BY’, diventerà tutto più chiaro quando affronteremo il Dockerfile.</p>



<h2>Ogni layer modifica i precedenti, ma il primo cosa modifica?</h2>



<p>Abbiamo visto che un’immagine viene costruita a pezzi, mediante dei layer che provocano variazioni successive e gestite mediante Union File System.<br>Ma qual è il layer da cui tutto inizia?<br>Il layer in questione si chiama “<strong>scratch</strong>”. In inglese ‘from scratch’ significa da zero.<br>Infatti, se proviamo ad eseguire:</p>



<pre class="wp-block-preformatted">docker image pull scratch</pre>



<p>vedremo che il demone restituisce un errore indicandoci che il nome ‘scratch’ è riservato.</p>



<pre class="wp-block-preformatted">Error response from daemon: 'scratch' is a reserved name</pre>



<p>A dire il vero un immagine può partire anche da un’altra immagine, che può partire da un’altra immagine e così via. Ma la prima di esse partirà sempre &#8220;from-scratch&#8221;.</p>



<p>Ogni modifica all’immagine a partire da scratch genera un nuovo layer.<br>Quando parleremo di Dockerfile, costruiremo i layer di un’immagine e capiremo nel dettaglio come lavorare al meglio con essi.</p>



<p>Ogni layer è identificato da un hash (SHA256) <strong>univoco</strong>. Questo hash è la chiave utilizzata dalle immagini per verificare la presenza o meno dei layer di cui necessitano nella cache locale dell’host.</p>



<p>Questo meccanismo di cache dei layer, snellisce notevolmente le operazioni di upload e download dai registry perché coinvolgono solo i layer nuovi e non ripetono tali operazioni sui layer già presenti. <br>Questo meccanismo resta valido sia quando carichiamo una nuova versione di un’immagine nell’hub, sia quando la scarichiamo.</p>



<p></p>



<p>—<br><strong>Prosegui su:</strong> <a href="http://dockertutorial.it/copy-on-write-cow/" class="aioseop-link">Copy-on-Write (CoW)</a></p>



<p>Immagine: <a href="https://it.freepik.com/foto-vettori-gratuito/viaggio" class="aioseop-link">Viaggio foto creata da freepik &#8211; it.freepik.com</a></p>
<p>L'articolo <a rel="nofollow" href="https://www.dockertutorial.it/analizzare-la-struttura-di-unimmagine/">Analizzare la struttura di un&#8217;immagine</a> proviene da <a rel="nofollow" href="https://www.dockertutorial.it">Docker Tutorial</a>.</p>
]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">325</post-id>	</item>
		<item>
		<title>Copy-on-Write (CoW)</title>
		<link>https://www.dockertutorial.it/copy-on-write-cow/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=copy-on-write-cow</link>
		
		<dc:creator><![CDATA[Fabio Ros]]></dc:creator>
		<pubDate>Sat, 23 May 2020 09:27:05 +0000</pubDate>
				<category><![CDATA[Immagini]]></category>
		<category><![CDATA[Tutorial]]></category>
		<guid isPermaLink="false">http://dockertutorial.it/?p=343</guid>

					<description><![CDATA[<p>Abbiamo capito che le immagini condividono i layer. Ma cosa avviene nei container istanziati a partire da tali immagini? Se più container condividono pezzi della...</p>
<p>L'articolo <a rel="nofollow" href="https://www.dockertutorial.it/copy-on-write-cow/">Copy-on-Write (CoW)</a> proviene da <a rel="nofollow" href="https://www.dockertutorial.it">Docker Tutorial</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>Abbiamo capito che le immagini condividono i layer. Ma cosa avviene nei container istanziati a partire da tali immagini? </p>



<p>Se più container condividono pezzi della stessa immagine, o addirittura tutta la stessa immagine, le modifiche operate da un container interferiscono con gli altri?</p>



<p>La risposta è no. Almeno non per i file relativi l’immagine.</p>



<blockquote class="wp-block-quote"><p>Quando viene eseguito un container, <strong>viene creato per esso un nuovo layer accessibile in lettura e scrittura</strong>. Il container potrà <strong>accedere solo in lettura ai file dell’immagine</strong> evitando ogni tipo di conflitto.</p></blockquote>



<p>Spesso però i container avranno bisogno di modificare alcuni file dell’immagine. Come possono farlo se ci accedono in sola lettura?</p>



<p>In realtà<strong> un container può sempre modificare i file dell’immagine da cui viene istanziato</strong>, ma non lo fa direttamente. Le modifiche riguardanti la sua istanza vengono persistite nel layer in lettura e scrittura creato nel momento in cui viene istanziato. </p>



<p>Il modo il cui lo fa è <strong>Detto Copy-on-Write (CoW)</strong> ovvero copia quando devi scrivere.</p>



<p class="wp-block-coblocks-highlight"><mark class="wp-block-coblocks-highlight__content">Fino alla prima modifica di un file dell’immagine da parte del container, gli accessi avvenivano in sola lettura.</mark></p>



<p>Per risparmiare risorse, in presenza di queste situazioni, Docker non copia i file nel layer in lettura e scrittura ma<strong> il container leggerà tali file direttamente dall’immagine</strong>.</p>



<p>Alla <strong>prima modifica</strong> di un file operata dal container, la nuova versione di <strong>tale file diverge</strong> rispetto a quella dell’immagine.</p>



<p>Solo <strong>a questo punto il file viene copiato dall’immagine al layer abilitato al read/write</strong>.</p>



<p></p>



<p>—<br><strong>Prosegui su:</strong> <a href="http://dockertutorial.it/docker-cli-prima-e-dopo/" class="aioseop-link">Docker CLI &#8211; prima e dopo</a></p>



<p>Immagine: <a href="https://it.freepik.com/foto-vettori-gratuito/viaggio">Viaggio foto creata da cookie_studio &#8211; it.freepik.com</a></p>
<p>L'articolo <a rel="nofollow" href="https://www.dockertutorial.it/copy-on-write-cow/">Copy-on-Write (CoW)</a> proviene da <a rel="nofollow" href="https://www.dockertutorial.it">Docker Tutorial</a>.</p>
]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">343</post-id>	</item>
		<item>
		<title>Docker CLI &#8211; prima e dopo</title>
		<link>https://www.dockertutorial.it/docker-cli-prima-e-dopo/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=docker-cli-prima-e-dopo</link>
		
		<dc:creator><![CDATA[Fabio Ros]]></dc:creator>
		<pubDate>Sat, 23 May 2020 09:47:26 +0000</pubDate>
				<category><![CDATA[Immagini]]></category>
		<category><![CDATA[Tutorial]]></category>
		<guid isPermaLink="false">http://dockertutorial.it/?p=352</guid>

					<description><![CDATA[<p>Ne approfitto per fare un breve cenno a come si è evoluta la CLI (Command Line Interface) negli ultimi tempi, in modo da chiarire perché...</p>
<p>L'articolo <a rel="nofollow" href="https://www.dockertutorial.it/docker-cli-prima-e-dopo/">Docker CLI &#8211; prima e dopo</a> proviene da <a rel="nofollow" href="https://www.dockertutorial.it">Docker Tutorial</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>Ne approfitto per fare un breve cenno a come si è evoluta la CLI (Command Line Interface) negli ultimi tempi, in modo da chiarire perché a volte sia possibile trovare alcuni comandi con una sintassi differente.</p>



<p>Avrei potuto prendere un comando già visto ma dato che ci siamo, impariamo qualcosa di nuovo. Prendiamo quindi:</p>



<pre class="wp-block-preformatted">docker image inspect</pre>



<p>Questo comando <strong>restituisce un oggetto in formato json con i metadati dell’immagine</strong> specificata per parametro.</p>



<p>Eseguendo:</p>



<pre class="wp-block-preformatted">docker image inspect alpine</pre>



<p>Ottenendo il seguente risultato:</p>



<pre class="wp-block-preformatted">[
&nbsp; &nbsp; {
&nbsp; &nbsp; &nbsp; &nbsp; "Id": "sha256:f70734b6a266dcb5f44c383274821207885b549b75c8e119404917a61335981a",
&nbsp; &nbsp; &nbsp; &nbsp; "RepoTags": [
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; "alpine:latest"
&nbsp; &nbsp; &nbsp; &nbsp; ],
&nbsp; &nbsp; &nbsp; &nbsp; "RepoDigests": [
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; "alpine@sha256:9a839e63dad54c3a6d1834e29692c8492d93f90c59c978c1ed79109ea4fb9a54"
&nbsp; &nbsp; &nbsp; &nbsp; ],
&nbsp; &nbsp; &nbsp; &nbsp; "Parent": "",
&nbsp; &nbsp; &nbsp; &nbsp; "Comment": "",
&nbsp; &nbsp; &nbsp; &nbsp; "Created": "2020-04-24T01:05:03.92860976Z",
&nbsp; &nbsp; &nbsp; &nbsp; "Container": "d3de5454dd4538da6ccb451b8fe1574b2efc482f958b04e6d109f123198d3d30",
&nbsp; &nbsp; &nbsp; &nbsp; "ContainerConfig": {
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; "Hostname": "d3de5454dd45",
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; "Domainname": "",
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; "User": "",
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; "AttachStdin": false,
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; "AttachStdout": false,
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; "AttachStderr": false,
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; "Tty": false,
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; "OpenStdin": false,
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; "StdinOnce": false,
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; "Env": [
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ],
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; "Cmd": [
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; "/bin/sh",
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; "-c",
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; "#(nop) ",
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; "CMD [\"/bin/sh\"]"
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ],
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; "ArgsEscaped": true,
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; "Image": "sha256:fce4411719cb54972247bbe799cf1dd74ecffda05bad4909df5224000dfd070e",
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; "Volumes": null,
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; "WorkingDir": "",
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; "Entrypoint": null,
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; "OnBuild": null,
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; "Labels": {}
&nbsp; &nbsp; &nbsp; &nbsp; },
&nbsp; &nbsp; &nbsp; &nbsp; "DockerVersion": "18.09.7",
&nbsp; &nbsp; &nbsp; &nbsp; "Author": "",
&nbsp; &nbsp; &nbsp; &nbsp; "Config": {
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; "Hostname": "",
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; "Domainname": "",
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; "User": "",
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; "AttachStdin": false,
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; "AttachStdout": false,
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; "AttachStderr": false,
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; "Tty": false,
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; "OpenStdin": false,
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; "StdinOnce": false,
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; "Env": [
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ],
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; "Cmd": [
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; "/bin/sh"
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ],
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; "ArgsEscaped": true,
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; "Image": "sha256:fce4411719cb54972247bbe799cf1dd74ecffda05bad4909df5224000dfd070e",
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; "Volumes": null,
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; "WorkingDir": "",
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; "Entrypoint": null,
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; "OnBuild": null,
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; "Labels": null
&nbsp; &nbsp; &nbsp; &nbsp; },
&nbsp; &nbsp; &nbsp; &nbsp; "Architecture": "amd64",
&nbsp; &nbsp; &nbsp; &nbsp; "Os": "linux",
&nbsp; &nbsp; &nbsp; &nbsp; "Size": 5612304,
&nbsp; &nbsp; &nbsp; &nbsp; "VirtualSize": 5612304,
&nbsp; &nbsp; &nbsp; &nbsp; "GraphDriver": {
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; "Data": {
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; "MergedDir": "/var/lib/docker/overlay2/bb0a38faf8a51dd52fed8883ddefe73effab9736c4f67eea46a78a3ad4de4bc2/merged",
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; "UpperDir": "/var/lib/docker/overlay2/bb0a38faf8a51dd52fed8883ddefe73effab9736c4f67eea46a78a3ad4de4bc2/diff",
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; "WorkDir": "/var/lib/docker/overlay2/bb0a38faf8a51dd52fed8883ddefe73effab9736c4f67eea46a78a3ad4de4bc2/work"
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; },
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; "Name": "overlay2"
&nbsp; &nbsp; &nbsp; &nbsp; },
&nbsp; &nbsp; &nbsp; &nbsp; "RootFS": {
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; "Type": "layers",
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; "Layers": [
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; "sha256:3e207b409db364b595ba862cdc12be96dcdad8e36c59a03b7b3b61c946a5741a"
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ]
&nbsp; &nbsp; &nbsp; &nbsp; },
&nbsp; &nbsp; &nbsp; &nbsp; "Metadata": {
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; "LastTagTime": "0001-01-01T00:00:00Z"
&nbsp; &nbsp; &nbsp; &nbsp; }
&nbsp; &nbsp; }
]</pre>



<p>vedremo diversi hash, tag architettura di riferimento, versione di Docker e molte altre informazioni su che a mio avviso ha senso approfondire, soprattutto in questa fase.&nbsp;</p>



<p>La cosa strana è che eseguendo:</p>



<pre class="wp-block-preformatted">docker inspect alpine</pre>



<p>otteniamo esattamente lo stesso risultato.</p>



<h2>Perché ci sono due modi diversi di eseguire lo stesso comando?</h2>



<p>Questo avviene perché la CLI di Docker ha cambiato la sua notazione ed ora utilizza dei <strong>sotto-comandi</strong> per evitare di avere dei conflitti sui nomi e per rendere il tutto più chiaro.</p>



<p>Docker Inc. vorrebbe abbandonare il supporto alla notazione precedente, per capirci, quella senza i sotto-comandi. Ad oggi sono ancora operativi e siccome questo potrebbe rompere molti script su cui Docker non ha controllo è possibile che possa non avvenire nell’immediato (o forse non avvenire mai). Consiglio personale, abituiamoci ad usare la nuova notazione così ci proteggiamo da eventuali rimozioni di comandi legacy e evitiamo di incorrere in spiacevoli inconvenienti.</p>



<p>Ma quali sono questi sottocomandi?</p>



<p>Eseguiamo il comando “docker”, senza alcun parametro. </p>



<pre class="wp-block-code"><code>Usage:	docker &#91;OPTIONS] COMMAND

A self-sufficient runtime for containers

Options:
      --config string      Location of client config files (default "/Users/fabioros/.docker")
  -c, --context string     Name of the context to use to connect to the daemon (overrides DOCKER_HOST env var and default
                           context set with "docker context use")
  -D, --debug              Enable debug mode
  -H, --host list          Daemon socket(s) to connect to
  -l, --log-level string   Set the logging level ("debug"|"info"|"warn"|"error"|"fatal") (default "info")
      --tls                Use TLS; implied by --tlsverify
      --tlscacert string   Trust certs signed only by this CA (default "/Users/fabioros/.docker/ca.pem")
      --tlscert string     Path to TLS certificate file (default "/Users/fabioros/.docker/cert.pem")
      --tlskey string      Path to TLS key file (default "/Users/fabioros/.docker/key.pem")
      --tlsverify          Use TLS and verify the remote
  -v, --version            Print version information and quit

Management Commands:
  builder     Manage builds
  checkpoint  Manage checkpoints
  config      Manage Docker configs
  container   Manage containers
  context     Manage contexts
  image       Manage images
  network     Manage networks
  node        Manage Swarm nodes
  plugin      Manage plugins
  secret      Manage Docker secrets
  service     Manage services
  stack       Manage Docker stacks
  swarm       Manage Swarm
  system      Manage Docker
  trust       Manage trust on Docker images
  volume      Manage volumes

Commands:
  attach      Attach local standard input, output, and error streams to a running container
  build       Build an image from a Dockerfile
  commit      Create a new image from a container's changes
  cp          Copy files/folders between a container and the local filesystem
  create      Create a new container
  deploy      Deploy a new stack or update an existing stack
  diff        Inspect changes to files or directories on a container's filesystem
  events      Get real time events from the server
  exec        Run a command in a running container
  export      Export a container's filesystem as a tar archive
  history     Show the history of an image
  images      List images
  import      Import the contents from a tarball to create a filesystem image
  info        Display system-wide information
  inspect     Return low-level information on Docker objects
  kill        Kill one or more running containers
  load        Load an image from a tar archive or STDIN
  login       Log in to a Docker registry
  logout      Log out from a Docker registry
  logs        Fetch the logs of a container
  pause       Pause all processes within one or more containers
  port        List port mappings or a specific mapping for the container
  ps          List containers
  pull        Pull an image or a repository from a registry
  push        Push an image or a repository to a registry
  rename      Rename a container
  restart     Restart one or more containers
  rm          Remove one or more containers
  rmi         Remove one or more images
  run         Run a command in a new container
  save        Save one or more images to a tar archive (streamed to STDOUT by default)
  search      Search the Docker Hub for images
  start       Start one or more stopped containers
  stats       Display a live stream of container(s) resource usage statistics
  stop        Stop one or more running containers
  tag         Create a tag TARGET_IMAGE that refers to SOURCE_IMAGE
  top         Display the running processes of a container
  unpause     Unpause all processes within one or more containers
  update      Update configuration of one or more containers
  version     Show the Docker version information
  wait        Block until one or more containers stop, then print their exit codes

Run 'docker COMMAND --help' for more information on a command.</code></pre>



<p>Quello che ci verrà restituito è un semplice cheatsheet. Non è completo, per quello è sempre possibile utilizzare l’help come indicato nell&#8217;ultima riga (Run &#8216;docker COMMAND &#8211;help&#8217; for more information on a command.).<br>Tuttavia, questo comando ci fornisce tutto ciò di cui abbiamo bisogno in questo momento.</p>



<p>Tra i comandi (Commands) è possibile osservare la voce ‘inspect’.  </p>



<pre class="wp-block-preformatted">&nbsp; inspect &nbsp; &nbsp; Return low-level information on Docker objects</pre>



<p>La descrizione di questo comando fa riferimento ad oggetti Docker generici e non alle immagini. Probabilmente è sovraccaricato. Sappiamo già che è presente all’interno del sotto-comando image, verifichiamo se è definito anche all’interno del sotto-comando container. <br>Eseguiamo quindi:</p>



<pre class="wp-block-preformatted">docker container</pre>



<p>È possibile notare che il comando inspect è definito anche qui e si riferisce ai container.</p>



<p>Utilizzare i sotto-comandi aiuta molto a mettere ordine sia agli script, sia alle idee.</p>



<p>—<br><strong>Prosegui su:</strong> <a href="https://dockertutorial.it/nomi-delle-immagini/">Nomi delle immagini</a></p>



<p>Immagine: <a href="https://it.freepik.com/foto-gratuito/barca-rossa-nel-lago-vicino-alla-montagna_8151664.htm" class="aioseop-link">Barca rossa nel lago vicino alla montagna – it.freepik.com</a></p>
<p>L'articolo <a rel="nofollow" href="https://www.dockertutorial.it/docker-cli-prima-e-dopo/">Docker CLI &#8211; prima e dopo</a> proviene da <a rel="nofollow" href="https://www.dockertutorial.it">Docker Tutorial</a>.</p>
]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">352</post-id>	</item>
		<item>
		<title>Nomi delle immagini</title>
		<link>https://www.dockertutorial.it/nomi-delle-immagini/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=nomi-delle-immagini</link>
		
		<dc:creator><![CDATA[Fabio Ros]]></dc:creator>
		<pubDate>Sat, 23 May 2020 10:26:27 +0000</pubDate>
				<category><![CDATA[Immagini]]></category>
		<category><![CDATA[Tutorial]]></category>
		<guid isPermaLink="false">http://dockertutorial.it/?p=361</guid>

					<description><![CDATA[<p>Abbiamo sempre parlato di hash ottenuti tramite SHA256, ma per fare il pull di un’immagine abbiamo sempre utilizzato il suo nome e, in alcuni casi,...</p>
<p>L'articolo <a rel="nofollow" href="https://www.dockertutorial.it/nomi-delle-immagini/">Nomi delle immagini</a> proviene da <a rel="nofollow" href="https://www.dockertutorial.it">Docker Tutorial</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>Abbiamo sempre parlato di hash ottenuti tramite SHA256, ma per fare il pull di un’immagine abbiamo sempre utilizzato il suo nome e, in alcuni casi, un tag.</p>



<p>Come viene associato un nome ad un immagine? Per capirlo abbiamo bisogno di qualche informazione in più sul concetto di Registry.</p>



<p><strong>I Registry persistono le immagini</strong>. Per darvi un’idea, un registry fa per le immagini qualcosa di simile a quello che Github fa per il codice.</p>



<p>I registry permettono di creare diversi repository, ognuno dei quali può contenere diverse immagini, un po’ come se venissero fatti dei branch su Github.</p>



<p><strong>Ogni repository può contenere più immagini</strong>, spesso per fornirne diverse versioni.&nbsp;</p>



<p>Le <strong>immagini all’interno di un repository</strong> sono contraddistinte da un <strong>hash univoco</strong>, ma <strong>possono avere anche dei tag</strong>.</p>



<p>Anche i tag funzionano in modo simile a git, permettendo di gestire diverse versioni. In realtà non si tratta di un vero e proprio indicatore di versione, ma di un etichetta appiccicata ad uno specifico commit di quell’immagine nel suo repository.</p>



<p>Giusto per completezza, <strong>i Registry possono essere di tre tipi</strong>.</p>



<ol><li><strong>ufficiali</strong>: ovvero Docker Hub</li><li><strong>on-premise</strong>: dove viene installato sulle proprie macchine</li><li><strong>di terze parti</strong>: figure terze forniscono un servizio simile a quello offerto da Docker Hub</li></ol>



<h2>Docker Hub</h2>



<p>I <strong>repository presenti su Docker Hub</strong> si dividono in <strong>ufficiali</strong> e <strong>non ufficiali</strong>, ma come possiamo distinguerli?</p>



<p>Nella pagine relativa ad un&#8217;immagine ufficiale su docker hub, viene specificata la dicitura &#8220;Docker Official Images&#8221;. Inoltre, l&#8217;url di un repository non ufficiale è nella forma https://hub.docker.com/r/user_or_organization/repository mentre, nel caso di un repository ufficiale, l&#8217;utente è sostituito dal carattere underscore &#8216;_&#8217; (es. <a href="https://hub.docker.com/_/alpine">https://hub.docker.com/_/alpine</a>).</p>



<figure class="wp-block-image size-large"><img loading="lazy" width="817" height="336" src="http://dockertutorial.it/wp-content/uploads/2020/05/Schermata-2020-05-23-alle-12.46.07.png" alt="" class="wp-image-369" srcset="https://www.dockertutorial.it/wp-content/uploads/2020/05/Schermata-2020-05-23-alle-12.46.07.png 817w, https://www.dockertutorial.it/wp-content/uploads/2020/05/Schermata-2020-05-23-alle-12.46.07-300x123.png 300w, https://www.dockertutorial.it/wp-content/uploads/2020/05/Schermata-2020-05-23-alle-12.46.07-768x316.png 768w, https://www.dockertutorial.it/wp-content/uploads/2020/05/Schermata-2020-05-23-alle-12.46.07-100x41.png 100w, https://www.dockertutorial.it/wp-content/uploads/2020/05/Schermata-2020-05-23-alle-12.46.07-700x288.png 700w" sizes="(max-width: 817px) 100vw, 817px" /><figcaption>Repository ufficiale di alpine su docker hub</figcaption></figure>



<p>Quelle non ufficiali sono curate da figure terze, persone oppure organizzazioni. Come è possibile osservare anche dal repository &#8220;<a href="https://hub.docker.com/r/alpine/git">https://hub.docker.com/r/alpine/git</a>&#8220;, l’underscore è stato sostituito dal nome utente o dell’organizzazione che possiede il repository.</p>



<p>Immediatamente prima dello username, vi è l&#8217;indicazione del fatto che la risorsa sia un utente o un repository rispettivamente con le lettere &#8216;u&#8217; o &#8216;r&#8217;.</p>



<p>L&#8217;organizzazione relativa al repository di alpine con git dell&#8217;esempio qui sopra è &#8220;alpine&#8221;: <a href="https://hub.docker.com/u/alpine" class="aioseop-link">https://hub.docker.com/u/alpine</a> </p>



<div style="height:100px" aria-hidden="true" class="wp-block-spacer"></div>



<h2>Le immagini non hanno propriamente un nome</h2>



<p>Ora che sappiamo cos’è un registry, cos’è un repository e cos’è un tag, siamo pronti a scoprire che le immagini in realtà non hanno propriamente un nome ma <strong>solo repository e tag</strong>.</p>



<p>Eseguendo docker image ls, infatti, vediamo che la prima colonna non ha come titolo ‘NAME’ ma ‘REPOSITORY’.</p>



<p>Quando scarichiamo un’immagine da Docker Hub, quindi, ci stiamo riferendo ad una coppia di repository e tag.&nbsp;</p>



<p><strong>In caso di repository non ufficiali</strong>, dobbiamo <strong>specificare anche il nome o l’organizzazione</strong> dell’account che possiede il repository prima del nome del repository e separandolo con uno slash. </p>



<h2>Tag</h2>



<p>Quale versione dell’immagine viene scaricata all’esecuzione di docker image pull &lt;repository&gt; <strong>se non specifico il tag</strong>?</p>



<p>In caso di assenza di tag, <strong>Docker userà implicitamente il tag “latest”.</strong></p>



<p>Attenzione però. <strong>Non è scontato che latest sia il tag relativo all’ultima versione dell’immagine</strong>. Molti repository utilizzano tag alpha, beta, edge per indicare le ultime versioni disponibili.&nbsp;</p>



<p>Proprio come in git, ad un immagine possono essere associati molti tag.&nbsp;</p>



<p>È facile accorgersi di ciò guardando l’output di &#8220;docker image ls | grep alpine&#8221; : osserveremo un’occorrenza per ogni tag, ma l’hash (IMAGE ID) rimarrà lo stesso per le versioni 3.9 e 3.9.6.</p>



<pre class="wp-block-preformatted">redis &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 6-alpine&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 360360313017&nbsp; &nbsp; &nbsp; &nbsp; 3 weeks ago &nbsp; &nbsp; &nbsp; &nbsp; 31.6MB
redis &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 5-alpine&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 3661c84ee9d0&nbsp; &nbsp; &nbsp; &nbsp; 4 weeks ago &nbsp; &nbsp; &nbsp; &nbsp; 29.8MB
alpine&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 3.9 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <strong><span class="has-inline-color has-vivid-cyan-blue-color">78a2ce922f86</span></strong>&nbsp; &nbsp; &nbsp; &nbsp; 4 weeks ago &nbsp; &nbsp; &nbsp; &nbsp; 5.55MB
alpine&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 3.9.6 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <strong><span class="has-inline-color has-vivid-cyan-blue-color">78a2ce922f86</span></strong>&nbsp; &nbsp; &nbsp; &nbsp; 4 weeks ago &nbsp; &nbsp; &nbsp; &nbsp; 5.55MB
alpine&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; latest&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; f70734b6a266&nbsp; &nbsp; &nbsp; &nbsp; 4 weeks ago &nbsp; &nbsp; &nbsp; &nbsp; 5.61MB</pre>



<p>—<br><strong>Prosegui su:</strong>&nbsp;<a href="http://dockertutorial.it/cli-delle-immagini/" class="aioseop-link">CLI delle immagini</a></p>



<p>Immagine:&nbsp;<a href="https://it.freepik.com/foto-vettori-gratuito/annata">Annata foto creata da photoangel &#8211; it.freepik.com</a></p>
<p>L'articolo <a rel="nofollow" href="https://www.dockertutorial.it/nomi-delle-immagini/">Nomi delle immagini</a> proviene da <a rel="nofollow" href="https://www.dockertutorial.it">Docker Tutorial</a>.</p>
]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">361</post-id>	</item>
		<item>
		<title>CLI delle immagini</title>
		<link>https://www.dockertutorial.it/cli-delle-immagini/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=cli-delle-immagini</link>
		
		<dc:creator><![CDATA[Fabio Ros]]></dc:creator>
		<pubDate>Sat, 23 May 2020 12:12:32 +0000</pubDate>
				<category><![CDATA[Immagini]]></category>
		<category><![CDATA[Tutorial]]></category>
		<guid isPermaLink="false">http://dockertutorial.it/?p=379</guid>

					<description><![CDATA[<p>È giunto il momento di analizzare la Command-Line-Interface dedicata alle immagini. Premetto che non si tratterà di una guida esaustiva. Si tratta piuttosto di apprendere...</p>
<p>L'articolo <a rel="nofollow" href="https://www.dockertutorial.it/cli-delle-immagini/">CLI delle immagini</a> proviene da <a rel="nofollow" href="https://www.dockertutorial.it">Docker Tutorial</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>È giunto il momento di analizzare la Command-Line-Interface dedicata alle immagini.</p>



<p>Premetto che non si tratterà di una guida esaustiva. Si tratta piuttosto di apprendere il processo che porta a essere autonomi nella ricerca e utilizzo delle istruzioni necessarie a seconda delle circostanze e necessità.</p>



<div style="height:100px" aria-hidden="true" class="wp-block-spacer"></div>



<h2>Elencare le immagini</h2>



<p>Analizziamo l&#8217;help del comando di listing relativo alle immagini con:</p>



<pre class="wp-block-preformatted">docker image ls --help</pre>



<p>Ottenendo questo output:</p>



<pre class="wp-block-preformatted">Usage: docker image ls [OPTIONS] [REPOSITORY[:TAG]]
List images
Aliases:
&nbsp; ls, images, list

Options:
&nbsp; -a, --all &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Show all images (default hides intermediate images)
&nbsp; &nbsp; &nbsp; --digests &nbsp; &nbsp; &nbsp; &nbsp; Show digests
&nbsp; -f, --filter filter &nbsp; Filter output based on conditions provided
&nbsp; &nbsp; &nbsp; --format string &nbsp; Pretty-print images using a Go template
&nbsp; &nbsp; &nbsp; --no-trunc&nbsp; &nbsp; &nbsp; &nbsp; Don't truncate output
&nbsp; -q, --quiet &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Only show numeric IDs</pre>



<p>La prima cosa che salta all&#8217;occhio è che di default, tutte le immagini &#8220;intermedie&#8221; sono nascoste. </p>



<h3>Mostrare le immagini Nascoste</h3>



<p>Per accedere a <strong>tutte le immagini</strong>, comprese quelle intermedie, è necessario utilizzare un <strong>flag &#8211;all</strong> (o <strong>-a</strong> nella versione compatta).<br>Per il momento non è necessario approfondire la questione, sarà tutto più chiaro quando verrà affrontata la creazione delle immagini, tuttavia è possibile trovare ulteriori informazioni a <a href="https://docs.docker.com/develop/develop-images/dockerfile_best-practices/" class="aioseop-link">questo link</a>.</p>



<h3>Filtri sulla lista delle immagini</h3>



<p>Il flag <strong>&#8211;filter</strong> ( o <strong>-f</strong> nella versione compatta) permette di <strong>specificare quali immagini mostrare </strong>a seconda di alcune caratteristiche. In questo momento sono disponibili sono tre opzioni:</p>



<ol><li>dangling=&lt;booleano&gt;</li><li>before=&lt;hash_immagine&gt;</li><li>since=&lt;hash_immagine&gt;</li></ol>



<p>Nel primo caso, eseguendo:</p>



<pre class="wp-block-preformatted">docker image ls --filter dangling=true</pre>



<p>si ottiene un elenco delle<strong> immagini create e poi sostituite</strong>. Queste immagini <strong>non saranno mai parte di un container</strong>. <br>La creazione di questo tipo di immagini è frequente nel processo di sviluppo, dove si creano molte immagini in sequenza e alcune rimangono inutilizzate nelle versioni successive. È possibile riconoscere queste immagini con un docker image ls perché avranno la colonna &#8220;NAME&#8221; valorizzata a &#8220;none&#8221;.</p>



<p>È altresì presente il comando simmetrico che permette di visualizzare solo le immagini che non sono rimaste &#8220;pendenti&#8221;.</p>



<p>I filtri <strong>before</strong> e <strong>since</strong> sono molto più semplici, eseguendo:</p>



<pre class="wp-block-preformatted">docker image ls --filter before=14b3ad</pre>



<p>Si ottiene una lista di tutte le immagini presenti <strong>nel repository locale</strong> che sono state <strong>create prima </strong>dell&#8217;immagine con l&#8217;hash che inizia con 14b3ad. </p>



<p>Il filtro since funziona in modo simmetrico.</p>



<div style="height:100px" aria-hidden="true" class="wp-block-spacer"></div>



<h2>Scaricare un&#8217;immagine</h2>



<p>Analizziamo l&#8217;help del comando preposto allo scaricamento immagini, ovvero <strong>docker image pull</strong>,  con:</p>



<pre class="wp-block-preformatted">docker image pull --help</pre>



<p>Ottenendo questo output:</p>



<pre class="wp-block-preformatted">Usage: docker image pull [OPTIONS] NAME[:TAG|@DIGEST]

Pull an image or a repository from a registr

Options:
&nbsp; -a, --all-tags&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Download all tagged images in the repository
&nbsp; &nbsp; &nbsp; --disable-content-trust &nbsp; Skip image verification (default true)
&nbsp; &nbsp; &nbsp; --platform string &nbsp; &nbsp; &nbsp; &nbsp; Set platform if server is multi-platform
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; capable
&nbsp; -q, --quiet &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Suppress verbose output</pre>



<p>Con il flag &#8211;all  ( o -a nella versione compatta) vengono scaricate tutte le immagini del repository specificato per parametro per le quali sia stato definito un tag.<br>Questo comando torna comodo quando si vuole testare il comportamento di un servizio o di un aggiornamento su diverse versioni di una particolare immagine. </p>



<div style="height:100px" aria-hidden="true" class="wp-block-spacer"></div>



<h2>Rimozione delle immagini</h2>



<p>Abbiamo capito che le immagini dangling non ci servono, per poterle rimuovere docker ha previsto un comando ad-hoc ovvero: </p>



<pre class="wp-block-preformatted">docker image prune</pre>



<p>È tuttavia possibile rimuovere le immagini anche specificando l&#8217;elenco degli hash dopo il comando dedicato alla rimozione ovvero <strong>docker image rm</strong>.</p>



<p>Il comando seguente, è un esempio del comando di rimozione delle due immagini con hash che iniziano rispettivamente con ad17bc e cd55e6. </p>



<pre class="wp-block-preformatted">docker image rm ad17bc cd55e6</pre>



<p>È importante ricordare che il prefisso dell&#8217;hash dell&#8217;immagine utilizzabile per identificarla deve identificare una sola immagine nel repository locale. La regola che preferisco è quella del &#8220;più piccolo prefisso univoco&#8221;, in genere basta utilizzare un prefisso univoco.</p>



<p>È possibile che un immagine sia in utilizzo da un container, anche se esso è in stato di stop o pause, in quel caso vi sono due opzioni:</p>



<ol><li>rimuovere i container che usano l&#8217;immagine e poi rimuovere l&#8217;immagine</li><li>forzare la rimozione dell&#8217;immagine con il flag <strong>&#8211;force</strong> ( o <strong>-f </strong>nella forma compatta) </li></ol>



<div class="wp-block-coblocks-alert is-style-warning" style="background-color:;color:"><p class="wp-block-coblocks-alert__text">Rimuovendo forzatamente un&#8217;immagine relativa a un container in stato &#8220;Up&#8221;, esso rimane in  stato &#8220;Up&#8221; e possono verificarsi situazioni imprevedibili!</p></div>



<div style="height:100px" aria-hidden="true" class="wp-block-spacer"></div>



<h2>Ricerca delle immagini</h2>



<p>Con il comando <strong>docker search</strong> vengono ricercate le immagini che, nel docker hub, contengono la stringa specificata. Di default il numero di immagini restituite è 25, tuttavia questo valore è modificabile fino a un massimo di 100 risultati.</p>



<p>L&#8217;esempio seguente mostra una ricerca con chiave &#8220;rails&#8221; fissando un limite di 100 risultati.</p>



<pre class="wp-block-preformatted">docker search --limit 100 rails</pre>



<p>il risultato ha le seguenti colonne:</p>



<ul><li>NAME</li><li>DESCRIPTION</li><li>STARS</li><li>OFFICIAL</li><li>AUTOMATED</li></ul>



<p>Le prime quattro colonne hanno nomi parlanti, l&#8217;ultima invece sta a specificare che la build è avvenuta in modo automatizzato, probabilmente un sistema di Continuous Integration.</p>



<p>è possibile specificare dei trigger che permettono di affinare la ricerca, ad esempio: </p>



<pre class="wp-block-preformatted">docker search --filter "is-official=true" &lt;repository&gt;</pre>



<pre class="wp-block-preformatted">docker search --filter "is-automated=true" &lt;repository&gt;</pre>



<div style="height:100px" aria-hidden="true" class="wp-block-spacer"></div>



<h2>Immagini multi architettura</h2>



<p>Docker è nato su linux, ma si è poi esteso ad altri sistemi operativi, come Windows. <br>Inoltre ora docker supporta diverse architetture quali ad esempio ARM e RaspberryPy.</p>



<p>Sebbene questo sia assolutamente positivo, ci costringe a porci una domanda:</p>



<blockquote class="wp-block-quote"><p>L&#8217;immagine che sto costruendo può venire utilizzata per istanziare un container sulla macchina sulla quale sta girando docker?</p></blockquote>



<h3>Image &#8220;Manifest&#8221; e &#8220;Manifest List&#8221;</h3>



<p>Per ogni immagine, possono essere definiti due costrutti nel registry: Manifest e Manifest List.</p>



<figure class="wp-block-image size-large"><img loading="lazy" width="1024" height="596" src="https://dockertutorial.it/wp-content/uploads/2020/05/manifest-dockercon_eu_17-1024x596.png" alt="" class="wp-image-393" srcset="https://www.dockertutorial.it/wp-content/uploads/2020/05/manifest-dockercon_eu_17-1024x596.png 1024w, https://www.dockertutorial.it/wp-content/uploads/2020/05/manifest-dockercon_eu_17-300x175.png 300w, https://www.dockertutorial.it/wp-content/uploads/2020/05/manifest-dockercon_eu_17-768x447.png 768w, https://www.dockertutorial.it/wp-content/uploads/2020/05/manifest-dockercon_eu_17-1536x895.png 1536w, https://www.dockertutorial.it/wp-content/uploads/2020/05/manifest-dockercon_eu_17-100x58.png 100w, https://www.dockertutorial.it/wp-content/uploads/2020/05/manifest-dockercon_eu_17-700x408.png 700w, https://www.dockertutorial.it/wp-content/uploads/2020/05/manifest-dockercon_eu_17.png 1600w" sizes="(max-width: 1024px) 100vw, 1024px" /><figcaption><a href="https://www.docker.com/blog/multi-arch-all-the-things/" class="aioseop-link">https://www.docker.com/blog/multi-arch-all-the-things/</a></figcaption></figure>



<p>Lascio il link alla documentazione: <a href="https://docs.docker.com/registry/spec/manifest-v2-2/">https://docs.docker.com/registry/spec/manifest-v2-2/</a></p>



<p>La <strong>Manifest List </strong>è una <strong>lista di architetture</strong> supportate da una immagine con riferimento ad un particolare tag.</p>



<p>Ogni record di tale lista è associato a un file <strong>manifest</strong> che specifica <strong>com&#8217;è fatta un&#8217;immagine</strong> definendo <strong>configurazioni</strong> e i relativi <strong>layer</strong>.</p>



<div style="height:100px" aria-hidden="true" class="wp-block-spacer"></div>



<h3>Quindi cosa succede al pull di un&#8217;immagine?</h3>



<p>Ora possiamo fare un passo avanti e capire cosa accade in profondità al pull di un&#8217;immagine.</p>



<figure class="wp-block-image size-large"><img loading="lazy" width="802" height="351" src="https://dockertutorial.it/wp-content/uploads/2020/05/Untitled-Diagram-1.png" alt="" class="wp-image-395" srcset="https://www.dockertutorial.it/wp-content/uploads/2020/05/Untitled-Diagram-1.png 802w, https://www.dockertutorial.it/wp-content/uploads/2020/05/Untitled-Diagram-1-300x131.png 300w, https://www.dockertutorial.it/wp-content/uploads/2020/05/Untitled-Diagram-1-768x336.png 768w, https://www.dockertutorial.it/wp-content/uploads/2020/05/Untitled-Diagram-1-100x44.png 100w, https://www.dockertutorial.it/wp-content/uploads/2020/05/Untitled-Diagram-1-700x306.png 700w" sizes="(max-width: 802px) 100vw, 802px" /><figcaption>Flusso al pull immagine</figcaption></figure>



<p>Al pull di un immagine, viene ricercata la versione compatibile con l&#8217;architettura dove è in esecuzione il demone di docker. Se questa viene trovata, allora viene scaricata l&#8217;immagine corrispondente altrimenti verrà utilizzato il manifest di default previsto per ogni immagine.</p>



<p>La creazione di una Manifest List è opzionale. A volte per evitare un overhead ingiustificato, altre volte perché alcuni software non sono cross platform e la definizione di una Manifest List perderebbe di senso.</p>



<div style="height:100px" aria-hidden="true" class="wp-block-spacer"></div>



<p>—<br><strong>Prosegui su:</strong> <a href="https://dockertutorial.it/dockerizing-containerizing/" class="aioseop-link">Dockerizing/Containerizing</a></p>



<p>Immagine:  <a href="https://it.freepik.com/foto-gratuito/bella-vista-sul-parco-nazionale-di-banff_8162790.htm" class="aioseop-link">Bella vista sul parco nazionale di Banff &#8211; it.freepik.com</a>  </p>
<p>L'articolo <a rel="nofollow" href="https://www.dockertutorial.it/cli-delle-immagini/">CLI delle immagini</a> proviene da <a rel="nofollow" href="https://www.dockertutorial.it">Docker Tutorial</a>.</p>
]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">379</post-id>	</item>
		<item>
		<title>Dockerizing / Containerizing</title>
		<link>https://www.dockertutorial.it/dockerizing-containerizing/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=dockerizing-containerizing</link>
		
		<dc:creator><![CDATA[Fabio Ros]]></dc:creator>
		<pubDate>Sun, 24 May 2020 13:25:49 +0000</pubDate>
				<category><![CDATA[Immagini]]></category>
		<category><![CDATA[Tutorial]]></category>
		<guid isPermaLink="false">https://dockertutorial.it/?p=406</guid>

					<description><![CDATA[<p>Fino a questo punto abbiamo utilizzato le immagini fornite dal docker hub. Ora è il momento di iniziare a costruire le nostre. Uno dei casi...</p>
<p>L'articolo <a rel="nofollow" href="https://www.dockertutorial.it/dockerizing-containerizing/">Dockerizing / Containerizing</a> proviene da <a rel="nofollow" href="https://www.dockertutorial.it">Docker Tutorial</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>Fino a questo punto abbiamo utilizzato le immagini fornite dal docker hub. Ora è il momento di iniziare a costruire le nostre.</p>



<p>Uno dei casi d&#8217;uso più comuni quando si parla di Docker è <strong>adattare un software già esistente all&#8217;architettura a container</strong>. Questo procedimento si dice &#8220;<strong>containerizing</strong>&#8221; o &#8220;<strong>dockerizing</strong>&#8221; an application e per farlo vanno costruite delle immagini ad-hoc.</p>



<h2>Creare immagini</h2>



<p>Per iniziare a creare un immagine abbiamo bisogno di creare un file particolare. Questo file si chiama &#8220;<strong>Dockerfile</strong>&#8221; e va salvato così, senza estensione.</p>



<p>Pensiamo al Dockerfile come un manuale di assemblaggio per le immagini.</p>



<p>Il suo scopo però non si esaurisce qui. Oltre a specificare c<strong>ome deve essere costruita</strong> un&#8217;immagine, descrive anche la <strong>modalità (di default) con la quale verrà avviato un container a partire da essa</strong>.</p>



<p>Le istruzioni dichiarate nel Dockerfile <strong>verranno eseguite in ordine</strong> e, in buona approssimazione, <strong>per ognuna di esse verrà generato un layer</strong>.</p>



<p>Durante il processo di build, verrà eseguita una ricerca del Dockerfile a partire dalla <strong>root</strong> del progetto (che solitamente è la cartella da cui si lancia il comando di build). È comunque possibile specificare un <strong>percorso diverso</strong> utilizzando il flag <strong>-f</strong> nel comando di build. </p>



<p>Non abbiamo ancora affrontato una build, ma ne parleremo tra poco. Per ora poniamo l&#8217;attenzione sul Dockerfile.</p>



<p>Nel prossimo post affronteremo le istruzioni che compongono il Dockerfile.</p>



<p>Mi sono posto come obiettivo quello di affrontare tutte le istruzioni più rilevanti, tuttavia lascio un link alla documentazione(<a href="https://docs.docker.com/engine/reference/builder/">https://docs.docker.com/engine/reference/builder/</a>) per qualunque approfondimento o necessità diversa da quanto trattato.</p>



<p>Piccola nota a margine per chi conosce i design pattern. Osserviamo il link. Non leggiamo reference/Dockerfile ma reference/<strong>builder</strong>. <br><a href="https://it.wikipedia.org/wiki/Builder" class="aioseop-link">Vi ricorda niente?</a></p>



<p>—<br><strong>Prosegui su:</strong> <a class="aioseop-link" href="https://dockertutorial.it/dockerfile/">Dockerfile</a></p>



<p>Immagine:&nbsp;<a href="https://it.freepik.com/foto-vettori-gratuito/acqua" class="aioseop-link">Acqua foto creata da freepik &#8211; it.freepik.com</a></p>



<p></p>
<p>L'articolo <a rel="nofollow" href="https://www.dockertutorial.it/dockerizing-containerizing/">Dockerizing / Containerizing</a> proviene da <a rel="nofollow" href="https://www.dockertutorial.it">Docker Tutorial</a>.</p>
]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">406</post-id>	</item>
		<item>
		<title>Dockerfile: FROM, RUN, ARG e CMD</title>
		<link>https://www.dockertutorial.it/dockerfile-from-run-arg-e-cmd/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=dockerfile-from-run-arg-e-cmd</link>
		
		<dc:creator><![CDATA[Fabio Ros]]></dc:creator>
		<pubDate>Sun, 24 May 2020 13:48:02 +0000</pubDate>
				<category><![CDATA[Immagini]]></category>
		<category><![CDATA[Tutorial]]></category>
		<guid isPermaLink="false">https://dockertutorial.it/?p=413</guid>

					<description><![CDATA[<p>Questo post e, alcuni tra i prossimi, hanno lo scopo di dettagliare le istruzioni principali per la definizione di un Dockerfile necessario alla build di...</p>
<p>L'articolo <a rel="nofollow" href="https://www.dockertutorial.it/dockerfile-from-run-arg-e-cmd/">Dockerfile: FROM, RUN, ARG e CMD</a> proviene da <a rel="nofollow" href="https://www.dockertutorial.it">Docker Tutorial</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>Questo post e, alcuni tra i prossimi,  hanno lo scopo di dettagliare le istruzioni principali per la definizione di un Dockerfile necessario alla build di un&#8217;immagine.</p>



<p>Per la comprensione di alcuni concetti ricorrenti, utilizzeremo l&#8217;immagine ufficiale di mysql presente nel docker hub a questo indirizzo: <a href="https://hub.docker.com/_/mysql" class="aioseop-link">https://hub.docker.com/_/mysql</a>.<br>Ho scelto questo esempio perché è abbastanza completo e mi da modo di mostrare un implicazione reale di quasi tutti i costrutti principali.</p>



<p>Aprendo la pagina noteremo ad un certo punto una sezione con la dicitura &#8220;Supported tags and respective Dockerfile links&#8221;.</p>



<figure class="wp-block-image size-large"><img loading="lazy" width="737" height="205" src="https://dockertutorial.it/wp-content/uploads/2020/05/Schermata-2020-05-24-alle-15.57.27.png" alt="" class="wp-image-420" srcset="https://www.dockertutorial.it/wp-content/uploads/2020/05/Schermata-2020-05-24-alle-15.57.27.png 737w, https://www.dockertutorial.it/wp-content/uploads/2020/05/Schermata-2020-05-24-alle-15.57.27-300x83.png 300w, https://www.dockertutorial.it/wp-content/uploads/2020/05/Schermata-2020-05-24-alle-15.57.27-100x28.png 100w, https://www.dockertutorial.it/wp-content/uploads/2020/05/Schermata-2020-05-24-alle-15.57.27-700x195.png 700w" sizes="(max-width: 737px) 100vw, 737px" /></figure>



<p>Ogni riga contiene immagini che condividono lo stesso Dockerfile.</p>



<p>Facendo click su uno qualunque dei tag, si aprirà un link ad un Dockerfile che è esattamente quello utilizzato per creare l&#8217;immagine con tutti i tag presenti in quella riga.</p>



<p>Personalmente, ogni volta che ho a che fare con un&#8217;immagine che non conosco, vado a leggere il Dockerfile &#8211; se disponibile &#8211; per avere più informazioni possibili su come è stata costruita e su come è preferibile utilizzarla. Mi sento di consigliare questo approccio perché a mio avviso è molto utile. </p>



<h2>Sintassi</h2>



<p>È giunto il momento di una carrellata nozionistica, ma ahimè indispensabile.</p>



<h3>FROM</h3>



<p>Ogni Dockerfile &#8220;deve iniziare&#8221; con l&#8217;istruzione FROM.</p>



<p>Questa istruzione <strong>specifica l&#8217;immagine base da cui partire</strong> per costruirne una di nuova.</p>



<pre class="wp-block-preformatted">FROM alpine:latest</pre>



<p>Questa istruzione sta dicendo a Docker di costruire l&#8217;immagine a partire dall&#8217;immagine del repository alpine contrassegnato dal tag latest</p>



<div style="height:100px" aria-hidden="true" class="wp-block-spacer"></div>



<p>Piccola nota, ma di fondamentale importanza. Le immagini vengono tenute il più leggere possibile, di conseguenza è possibile che alcuni pacchetti che siamo soliti utilizzare nei sistemi corrispondenti all&#8217;immagine di base potrebbero non essere presenti di default e necessitare di installazione.</p>



<p>Ad esempio, l&#8217;immagine di base di Ubuntu non ha il comando ping abilitato di default. Per averne prova basta eseguire:</p>



<pre class="wp-block-preformatted">docker container run --rm ubuntu ping dockertutorial.it</pre>



<p>l&#8217;output che otteniamo è:</p>



<pre class="wp-block-preformatted">docker: Error response from daemon: OCI runtime create failed: container_linux.go:349: starting container process caused "exec: \"ping\": executable file not found in $PATH": unknown.</pre>



<p>Il demone ci dice che non sa come eseguire &#8220;ping&#8221; e fallisce.</p>



<div class="wp-block-coblocks-alert"><p class="wp-block-coblocks-alert__text">Ho approfittato di questo esempio per utilizzare il flag <strong>&#8211;rm</strong> all&#8217;interno di un istruzione per l&#8217;avvio di un container. Questo flag è comodissimo perché rimuove il container al termine dell&#8217;esecuzione evitando di lasciare memoria allocata inutilmente e evitandoci il lavoro di pulizia.</p></div>



<p>Eseguendo invece lo stesso container, ma con il comando ls</p>



<pre class="wp-block-preformatted">docker container run --rm ubuntu ls</pre>



<p> otteniamo l&#8217;elenco dei file e cartelle.</p>



<pre class="wp-block-preformatted">bin
boot
dev
etc
home
lib
lib32
lib64
libx32
media
mnt
opt
proc
root
run
sbin
srv
sys
tmp
usr
var</pre>



<p>Questo accade perché il listing è abilitato di default.<br>Finché parliamo di ping, può ance sembrare una cosa di scarso interesse, ma potrebbe capitare per servizi molto più di largo uso quali i package manager. In questo caso l&#8217;idea è di partire da immagini che già li supportano nativamente ad esempio Ubuntu per apt, Debian per yum o Alpine per pkg.</p>



<h3>ARG</h3>



<p>In casi particolari, può aver senso specificare uno o più <strong>parametri da passare come argomento al FROM.</strong></p>



<p>In ambiente Docker questi si chiamano <strong>argomenti</strong> e vengono definiti con la keyword <strong>ARG</strong>. </p>



<p class="wp-block-coblocks-highlight"><mark class="wp-block-coblocks-highlight__content">Solo la definizione di questi parametri può precedere la definizione dell&#8217;immagine di partenza, comparendo quindi prima della keyword FROM.</mark></p>



<p>Modifichiamo l&#8217;esempio visto in precedenza e incapsuliamo il tag latest in un argomento.</p>



<pre class="wp-block-preformatted">ARG VERSIONE_IMG=latest
FROM alpine:${VERSIONE_IMG}</pre>



<p>Andiamo per ordine. <br>In questo caso viene creato un parametro visibile <strong>solo al di fuori della build</strong> che riporta il tag dell&#8217;immagine di alpine da utilizzare come immagine di partenza.</p>



<p>La valutazione e restituzione dell&#8217;argomento viene eseguita mediante la sintassi bash ${} e verrà utilizzata nel comando che verrà invocato.</p>



<div class="wp-block-coblocks-alert is-style-warning" style="background-color:;color:"><p class="wp-block-coblocks-alert__title">Anche se ci assomiglia, non è bash!</p><p class="wp-block-coblocks-alert__text">Nel Dockerfile si utilizza anche lo scripting bash, ma il Dockerfile <strong>non è uno script bash</strong>.</p></div>



<p>Come abbiamo detto in precedenza, l&#8217;istruzione FROM è quella che determina l&#8217;inizio della build. Quindi tutti gli argomenti definiti con ARG non sono visibili dopo il tag FROM. Almeno non di default.</p>



<p>Si possono <strong>rendere visibili gli argomenti anche all&#8217;interno del processo di costruzione</strong> dell&#8217;immagine <strong>dichiarandoli anche dopo il tag FROM, senza assegnarne alcun valore</strong>.</p>



<pre class="wp-block-preformatted">ARG VERSIONE_IMG=latest
FROM alpine:${VERSIONE_IMG}
<strong><span class="has-inline-color has-vivid-cyan-blue-color">ARG VERSIONE_IMG</span></strong>
RUN echo $VERSION &gt; file.txt</pre>



<p>Subito dopo la dichiarazione dell&#8217;argomento, vediamo il comando RUN.</p>



<p>In questo caso verrà eseguito un echo che produrrà in output la stringa &#8220;latest&#8221;. L&#8217;output verrà poi dirottato in un nuovo file che ho chiamato &#8220;file.txt&#8221;.</p>



<h3>RUN</h3>



<p>Il comando RUN ha lo scopo di <strong>eseguire una o più istruzioni</strong> definite in formato bash in un nuovo layer. Di fatto <strong>aggiungendo un blocco immutabile</strong> all&#8217;immagine.</p>



<p>Durante la build, l&#8217;istruzione di build successiva a quella del RUN appena definito, sarà costruita a partire dall&#8217;immagine ottenuta dall&#8217;applicazione di tutti i layer precedenti. Quello appena definito sarà l&#8217;ultimo in ordine di comparizione.</p>



<p>Un po&#8217; come una pila di piatti, noi prendiamo tutta la pila ma ogni piatto viene posto sopra la tutti quelli impilati precedentemente.</p>



<p>Questo è un concetto chiave del Dockerfile e di Docker in generale. La build avviene per composizione di layer successivi definiti con buona approssimazione da ogni riga del dockerfile a partire da FROM.</p>



<h4>Due modalità distinte per invocare il RUN</h4>



<p>Quando definiamo i comandi RUN, possiamo scegliere tra due tipologie di sintassi:</p>



<ol><li>Modalità <strong>bash</strong></li><li>Modalità <strong>exec</strong> ( detta anche <strong>json</strong> )</li></ol>



<hr class="wp-block-separator"/>



<p>La modalità <strong>bash</strong> esegue il comando <strong>in una shell</strong>.<br>Diretta conseguenza di ciò è che <strong>viene prefissa implicitamente la dichiarazione della shell</strong>. Nello specifico, in ambiente unix il modulo builder del docker engine ci anteporrà &#8220;/bin/sh -c&#8221;.</p>



<pre class="wp-block-preformatted">RUN echo 'testo di prova'</pre>



<p>Ricordiamoci di questa semplificazione perché non viene proprio a gratis, ma porta con se delle conseguenze. </p>



<hr class="wp-block-separator"/>



<p>L’altra sintassi è quella <strong>exec</strong>. Questa modalità <strong>non invoca la shell direttamente</strong> ma fa il <strong>parse di un array json e compone la stringa dell’istruzione da eseguire fondendo i valori recuperati da tale array.&nbsp;</strong></p>



<p>&nbsp;Tutte le stringhe che compongono l’istruzione devono essere <strong>racchiuse da doppi apici</strong> e non da apici singoli.</p>



<pre class="wp-block-preformatted">RUN ["sh", "-c", "echo hello"]
RUN ["/bin/bash", "-c", "echo hello"]
RUN ["file_eseguibile.sh"]
RUN ["sh", "-c", "echo $ARG_ESEMPIO"]</pre>



<p>Inoltre, non essendo direttamente un comando su shell, la <strong>sostituzione delle stringhe con gli argomenti</strong> (quelli preceduti dal dollaro che abbiamo visto in precedenza) <strong>non funziona</strong>.</p>



<p>Se dovessimo trovarci nella situazione in cui necessitiamo che vengano interpretate alcune variabili,&nbsp; dovremmo <strong>predisporre l’array impostando le prime stringhe con la definizione di una shell</strong>, ad esempio RUN [“sh”, “-c”, “echo $ARG_ESEMPIO”]. Questo è un mezzo trucchetto perché la $ARG_ESEMPIO non verrebbe comunque interpretata in modalità exec, però, essendo preceduta da una shell la valutazione e sostituzione delle stringhe avviene in un secondo momento, al di fuori della valutazione dell’array json.</p>



<p>Essendo json, può essere necessario fare l’<strong>escape</strong> dei caratteri speciali, il carattere preposto per questo scopo è, come di consueto, il <strong>backslash</strong> (<strong>\</strong>). Lo scopo è quello di comunicare all&#8217;interprete di trattare il carattere successivo al backslash come carattere di contenuto e non come un carattere che potrebbe avere una valenza diversa(ad esempio i doppi apici che chiuderebbero la stringa&#8221;).</p>



<h2>Errori noti</h2>



<p>Ricordate quando parlavamo di layer delle immagini? Avevamo visto che <strong>un layer che non viene modificato dalla build precedente</strong>, non viene ricostruito nuovamente durante la build di un’immagine perché <strong>già in cache</strong>.</p>



<p>Ma cosa succede se il layer è generato, ad esempio, da un comando che fa il pull da un dato branch di un repository? Oppure se verifica l’ora corrente e se maggiore di un certo valore cambia il comportamento?</p>



<p>Attenzione che questo aspetto provoca spesso errori. <strong>Le informazioni cambiano al di fuori</strong> del Dockerfile, quindi verrebbe <strong>eseguito solo la prima volta</strong>, perché <strong>l’istruzione che lo genera non ha subito modifiche</strong> e di conseguenza verrebbe semplicemente recuperato dalla cache. </p>



<div class="wp-block-coblocks-alert"><p class="wp-block-coblocks-alert__text">Docker costruisce le immagini con <strong>i Dockerfile che non hanno consapevolezza delle modifiche apportate all’esterno, ma solo delle variazioni dei propri layer</strong>.</p></div>



<p>Quando vi sono di questi problemi, è il caso di eseguire la build utilizzando il flag <strong>&#8211;no-cache </strong>che ha lo scopo di invalidare la cache relativa alle <strong>sole</strong> istruzioni <strong>RUN</strong>.</p>



<p>Dato che siamo in tema di errori noti, ne approfitto per darvi una dritta sull’invocazione dei comandi bash. Può capitare a volte di vedere delle invocazioni di più comandi separati dai caratteri<strong> &#8220;&amp;&amp;&#8221; </strong>oppure dal carattere &#8220;<strong>;</strong>&#8220;. La differenza sta nel fatto che <strong>nel primo caso, ogni comando viene eseguito solo se tutti i precedenti sono andati a buon fine</strong>, mentre nel <strong>secondo caso, verranno eseguite sempre tutte le istruzioni</strong>. Quando scriviamo dei Dockerfile oppure anche dei file bash generici, dobbiamo sempre pensare bene al flusso delle istruzioni multiple in modo da evitare risultati diversi da quelli che ci aspettiamo.</p>



<p>Fatte queste considerazioni, torniamo per un attimo al Dockerfile di mysql.</p>



<pre class="wp-block-preformatted">RUN set -eux<strong>;</strong> <strong>\</strong>
savedAptMark="$(apt-mark showmanual)"<strong>;</strong> <strong>\</strong>
apt-get update<strong>;</strong> <strong>\</strong>
apt-get install -y --no-install-recommends ca-certificates wget<strong>;</strong> <strong>\</strong>
rm -rf /var/lib/apt/lists/*<strong>;</strong> <strong>\</strong>
dpkgArch="$(dpkg --print-architecture | awk -F- '{ print $NF }')"<strong>;</strong> <strong>\</strong>
wget -O /usr/local/bin/gosu "https://github.com/tianon/gosu/releases/download/$GOSU_VERSION/gosu-$dpkgArch"<strong>;</strong> <strong>\</strong>
wget -O /usr/local/bin/gosu.asc "https://github.com/tianon/gosu/releases/download/$GOSU_VERSION/gosu-$dpkgArch.asc"<strong>;</strong> <strong>\</strong>
export GNUPGHOME="$(mktemp -d)"<strong>;</strong> <strong>\</strong>
gpg --batch --keyserver hkps://keys.openpgp.org --recv-keys B42F6819007F00F88E364FD4036A9C25BF357DD4<strong>;</strong> <strong>\</strong>
gpg --batch --verify /usr/local/bin/gosu.asc /usr/local/bin/gosu<strong>;</strong> <strong>\</strong>
gpgconf --kill all<strong>;</strong> <strong>\</strong>
rm -rf "$GNUPGHOME" /usr/local/bin/gosu.asc<strong>;</strong> <strong>\</strong>
apt-mark auto '.*' &gt; /dev/null<strong>;</strong> <strong>\</strong>
[ -z "$savedAptMark" ] || apt-mark manual $savedAptMark &gt; /dev/null<strong>;</strong> <strong>\</strong>
apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false<strong>;</strong> <strong>\</strong>
chmod +x /usr/local/bin/gosu<strong>;</strong> <strong>\</strong>
gosu --version<strong>;</strong> <strong>\</strong>
gosu nobody true</pre>



<p> Il comando RUN si estende per più righe utilizzando l’apposito <strong>carattere per mandare accapo: ‘\’</strong>; Colgo la palla al balzo per evidenziare che se l’istruzione seguente è un comando, deve essere preceduta dall’indicazione di concatenazione affinché venga concatenata correttamente (in questo caso viene usato il carattere &#8216;;&#8217;).</p>



<p>Quest’ultimo punto <strong>può sembrare solo un aspetto stilistico, ma in realtà non lo è</strong> per niente. Ricordate che poco fa vi avevo detto che <strong>ogni riga del Dockerfile origina un nuovo layer</strong>? Utilizzare questa sintassi permette di <strong>raggruppare più istruzioni in un solo layer</strong> ottimizzando il processo.</p>



<h2>CMD</h2>



<p>Passiamo ora all’ultima istruzione necessaria per permetterci di fare la nostra prima build, ovvero CMD.</p>



<p>CMD è l’<strong>istruzione di default per l’esecuzione di un container</strong>. Fondamentalmente significa che <strong>al run di un container a partire dall’immagine che stiamo definendo, verrà invocata questa istruzione</strong>.</p>



<p>Il comando CMD, viene <strong>eseguito ogni volta che</strong> viene <strong>avviato un nuovo container</strong> oppure quando viene avviato con il comando<strong> docker container start</strong> dopo aver fermato il relativo container con docker container stop.</p>



<p>E’ possibile<strong> sovrascrivere questa istruzione esplicitandone una di diversa in coda al comando docker container run</strong> come abbiamo visto poche righe sopra quando abbiamo testato ping e ls sull&#8217;immagine di Ubuntu.</p>



<p>Ogni Dockerfile ben formato dovrebbe avere al massimo <strong>una sola occorrenza di CMD</strong>.&nbsp;Ad ogni modo, in presenza di invocazioni multiple, verrà <strong>utilizzata solo l’ultima</strong> di esse.</p>



<p>Anche in questo caso è possibile utilizzare<strong> sia la modalità bash sia quella exec</strong>.</p>



<p>Può sembrare che CMD e RUN siano equivalenti, ma in realtà non è così.</p>



<p>Sebbene siano simili nella forma non lo sono nella sostanza.</p>



<p><strong>RUN&nbsp; agisce in fase di build </strong>apportando modifiche all’immagine, mentre il comando <strong>CMD specifica cosa fare quando viene avviato un container </strong>a partire da un’immagine che a tutti gli effetti è già sigillata.</p>



<div style="height:100px" aria-hidden="true" class="wp-block-spacer"></div>



<p>—<br><strong>Prosegui su:</strong> <a href="https://dockertutorial.it/creare-unimmagine/" title="Creare un’immagine">Creare un&#8217;immagine</a></p>



<p>Immagine:&nbsp; <a href="https://it.freepik.com/foto-vettori-gratuito/acqua">Acqua foto creata da freepik &#8211; it.freepik.com</a></p>
<p>L'articolo <a rel="nofollow" href="https://www.dockertutorial.it/dockerfile-from-run-arg-e-cmd/">Dockerfile: FROM, RUN, ARG e CMD</a> proviene da <a rel="nofollow" href="https://www.dockertutorial.it">Docker Tutorial</a>.</p>
]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">413</post-id>	</item>
	</channel>
</rss>
