Ottimizzare i Dockerfile di Windows
Esistono molti modi per ottimizzare sia il processo di compilazione Docker che le immagini Docker risultanti. Questo articolo illustra come funziona il processo di compilazione Docker e come creare immagini in modo ottimale per i contenitori Di Windows.
Livelli di immagine nella compilazione Docker
Prima di poter ottimizzare la compilazione Docker, è necessario conoscere il funzionamento della compilazione Docker. Durante il processo di compilazione Docker viene usato un Dockerfile e le istruzioni eseguibili vengono effettivamente eseguite, una alla volta, nel relativo contenitore temporaneo. Il risultato è un nuovo livello di immagine per ogni istruzione eseguibile.
Ad esempio, il Dockerfile di esempio seguente usa l'immagine del mcr.microsoft.com/windows/servercore:ltsc2019
sistema operativo di base, installa IIS e quindi crea un sito Web semplice.
# Sample Dockerfile
FROM mcr.microsoft.com/windows/servercore:ltsc2019
RUN dism /online /enable-feature /all /featurename:iis-webserver /NoRestart
RUN echo "Hello World - Dockerfile" > c:\inetpub\wwwroot\index.html
CMD [ "cmd" ]
Si potrebbe prevedere che questo Dockerfile produrrà un'immagine con due livelli, uno per l'immagine del sistema operativo contenitore e un secondo che include IIS e il sito Web. Tuttavia, l'immagine effettiva ha molti livelli e ogni livello dipende da quello precedente.
Per renderlo più chiaro, eseguire il docker history
comando sull'immagine creata dal Dockerfile di esempio.
docker history iis
IMAGE CREATED CREATED BY SIZE COMMENT
f4caf476e909 16 seconds ago cmd /S /C REM (nop) CMD ["cmd"] 41.84 kB
f0e017e5b088 21 seconds ago cmd /S /C echo "Hello World - Dockerfile" > c 6.816 MB
88438e174b7c About a minute ago cmd /S /C dism /online /enable-feature /all / 162.7 MB
6801d964fda5 4 months ago 0 B
L'output mostra che questa immagine ha quattro livelli: il livello di base e tre livelli aggiuntivi mappati a ogni istruzione nel Dockerfile. Il livello inferiore (6801d964fda5
in questo esempio) rappresenta l'immagine del sistema operativo di base. Un livello su è l'installazione di IIS. Il livello ancora successivo include il nuovo sito Web e così via.
I Dockerfile possono essere scritti per ridurre al minimo i livelli di immagine, ottimizzare le prestazioni di compilazione e ottimizzare l'accessibilità tramite leggibilità. In definitiva esistono molti modi per completare l'attività di compilazione della stessa immagine. Comprendere in che modo il formato del Dockerfile influisce sul tempo di compilazione e l'immagine creata migliora l'esperienza di automazione.
Ottimizzare le dimensioni dell'immagine
A seconda dei requisiti di spazio, le dimensioni dell'immagine possono essere un fattore importante durante la compilazione di immagini contenitore Docker. Le immagini contenitore vengono spostate tra registri e host, esportate e importate, perciò consumano spazio. Questa sezione descrive come ridurre al minimo le dimensioni dell'immagine durante il processo di compilazione Docker per i contenitori Windows.
Per altre informazioni sulle procedure consigliate per Dockerfile, vedere Procedure consigliate per la scrittura di Dockerfile in Docker.com.
Raggruppare le azioni correlate
Poiché ogni RUN
istruzione crea un nuovo livello nell'immagine contenitore, il raggruppamento delle azioni in un'unica RUN
istruzione può ridurre il numero di livelli in un Dockerfile. Mentre la riduzione dei livelli al minimo potrebbe non influire molto sulla dimensione dell'immagine, ciò che potrebbe influire è invece il raggruppamento delle azioni correlate, trattato negli esempi successivi.
In questa sezione verranno confrontati due Dockerfile di esempio che eseguono le stesse operazioni. Tuttavia, un Dockerfile ha un'istruzione per azione, mentre l'altra ha raggruppato le azioni correlate.
L'esempio dockerfile di esempio non raggruppato seguente scarica Python per Windows, lo installa e rimuove il file di installazione scaricato al termine dell'installazione. In questo Dockerfile a ogni azione viene assegnata una propria RUN
istruzione.
FROM mcr.microsoft.com/windows/servercore:ltsc2019
RUN powershell.exe -Command Invoke-WebRequest "https://www.python.org/ftp/python/3.5.1/python-3.5.1.exe" -OutFile c:\python-3.5.1.exe
RUN powershell.exe -Command Start-Process c:\python-3.5.1.exe -ArgumentList '/quiet InstallAllUsers=1 PrependPath=1' -Wait
RUN powershell.exe -Command Remove-Item c:\python-3.5.1.exe -Force
L'immagine risultante è costituita da tre livelli aggiuntivi, uno per ogni istruzione RUN
.
docker history doc-example-1
IMAGE CREATED CREATED BY SIZE COMMENT
a395ca26777f 15 seconds ago cmd /S /C powershell.exe -Command Remove-Item 24.56 MB
6c137f466d28 28 seconds ago cmd /S /C powershell.exe -Command Start-Proce 178.6 MB
957147160e8d 3 minutes ago cmd /S /C powershell.exe -Command Invoke-WebR 125.7 MB
Il secondo esempio è un Dockerfile che esegue esattamente la stessa operazione. Tuttavia, tutte le azioni correlate sono state raggruppate in una singola RUN
istruzione. Ogni passaggio dell'istruzione RUN
si trova in una nuova riga del Dockerfile, mentre il carattere '\' viene usato per eseguire il wrapping della riga.
FROM mcr.microsoft.com/windows/servercore:ltsc2019
RUN powershell.exe -Command \
$ErrorActionPreference = 'Stop'; \
Invoke-WebRequest https://www.python.org/ftp/python/3.5.1/python-3.5.1.exe -OutFile c:\python-3.5.1.exe ; \
Start-Process c:\python-3.5.1.exe -ArgumentList '/quiet InstallAllUsers=1 PrependPath=1' -Wait ; \
Remove-Item c:\python-3.5.1.exe -Force
L'immagine risultante ha un solo livello aggiuntivo per l'istruzione RUN
.
docker history doc-example-2
IMAGE CREATED CREATED BY SIZE COMMENT
69e44f37c748 54 seconds ago cmd /S /C powershell.exe -Command $ErrorAct 216.3 MB
Rimuovere i file in eccesso
Se è presente un file nel Dockerfile, ad esempio un programma di installazione, che non è necessario dopo che è stato usato, è possibile rimuoverlo per ridurre le dimensioni dell'immagine. È necessario farlo nello stesso passaggio in cui il file viene copiato nel livello di immagine. In questo modo, il file non viene mantenuto in un livello di immagine di livello inferiore.
Nell'esempio seguente Dockerfile il pacchetto Python viene scaricato, eseguito e quindi rimosso. Tutto questo viene completato in una sola operazione RUN
e genera un singolo livello di immagine.
FROM mcr.microsoft.com/windows/servercore:ltsc2019
RUN powershell.exe -Command \
$ErrorActionPreference = 'Stop'; \
Invoke-WebRequest https://www.python.org/ftp/python/3.5.1/python-3.5.1.exe -OutFile c:\python-3.5.1.exe ; \
Start-Process c:\python-3.5.1.exe -ArgumentList '/quiet InstallAllUsers=1 PrependPath=1' -Wait ; \
Remove-Item c:\python-3.5.1.exe -Force
Ottimizzare la velocità di compilazione
Più righe
È possibile suddividere le operazioni in più istruzioni singole per ottimizzare la velocità di compilazione di Docker. Più RUN
operazioni aumentano l'efficacia della memorizzazione nella cache perché vengono creati singoli livelli per ogni RUN
istruzione. Se un'istruzione identica è già stata eseguita in un'operazione di compilazione Docker diversa, questa operazione memorizzata nella cache (livello immagine) viene riutilizzata, con conseguente riduzione del runtime di compilazione Docker.
Nell'esempio seguente i pacchetti Apache e Visual Studio Redistribute vengono scaricati, installati e quindi puliti rimuovendo i file che non sono più necessari. Questa operazione viene eseguita con un'unica RUN
istruzione. Se una di queste azioni viene aggiornata, tutte le azioni verranno eseguite di nuovo.
FROM mcr.microsoft.com/windows/servercore:ltsc2019
RUN powershell -Command \
# Download software ; \
wget https://www.apachelounge.com/download/VC11/binaries/httpd-2.4.18-win32-VC11.zip -OutFile c:\apache.zip ; \
wget "https://download.microsoft.com/download/1/6/B/16B06F60-3B20-4FF2-B699-5E9B7962F9AE/VSU_4/vcredist_x86.exe" -OutFile c:\vcredist.exe ; \
wget -Uri http://windows.php.net/downloads/releases/php-5.5.33-Win32-VC11-x86.zip -OutFile c:\php.zip ; \
# Install Software ; \
Expand-Archive -Path c:\php.zip -DestinationPath c:\php ; \
Expand-Archive -Path c:\apache.zip -DestinationPath c:\ ; \
Start-Process c:\vcredist.exe -ArgumentList '/quiet' -Wait ; \
# Remove unneeded files ; \
Remove-Item c:\apache.zip -Force; \
Remove-Item c:\vcredist.exe -Force; \
Remove-Item c:\php.zip
L'immagine risultante ha due livelli, uno per l'immagine del sistema operativo di base e uno che contiene tutte le operazioni della singola RUN
istruzione.
docker history doc-sample-1
IMAGE CREATED CREATED BY SIZE COMMENT
9bdf3a21fd41 8 minutes ago cmd /S /C powershell -Command Invoke-WebR 205.8 MB
6801d964fda5 5 months ago 0 B
Di seguito sono riportate le stesse azioni suddivise in tre RUN
istruzioni. In questo caso, ogni RUN
istruzione viene memorizzata nella cache in un livello immagine contenitore e solo quelle modificate devono essere rieseguite nelle compilazioni dockerfile successive.
FROM mcr.microsoft.com/windows/servercore:ltsc2019
RUN powershell -Command \
$ErrorActionPreference = 'Stop'; \
wget https://www.apachelounge.com/download/VC11/binaries/httpd-2.4.18-win32-VC11.zip -OutFile c:\apache.zip ; \
Expand-Archive -Path c:\apache.zip -DestinationPath c:\ ; \
Remove-Item c:\apache.zip -Force
RUN powershell -Command \
$ErrorActionPreference = 'Stop'; \
wget "https://download.microsoft.com/download/1/6/B/16B06F60-3B20-4FF2-B699-5E9B7962F9AE/VSU_4/vcredist_x86.exe" -OutFile c:\vcredist.exe ; \
Start-Process c:\vcredist.exe -ArgumentList '/quiet' -Wait ; \
Remove-Item c:\vcredist.exe -Force
RUN powershell -Command \
$ErrorActionPreference = 'Stop'; \
wget http://windows.php.net/downloads/releases/php-5.5.33-Win32-VC11-x86.zip -OutFile c:\php.zip ; \
Expand-Archive -Path c:\php.zip -DestinationPath c:\php ; \
Remove-Item c:\php.zip -Force
L'immagine risultante è costituita da quattro livelli; un livello per l'immagine del sistema operativo di base e ognuna delle tre RUN
istruzioni. Poiché ogni RUN
istruzione è stata eseguita nel proprio livello, tutte le esecuzioni successive di questo Dockerfile o un set identico di istruzioni in un Dockerfile diverso useranno i livelli immagine memorizzati nella cache, riducendo il tempo di compilazione.
docker history doc-sample-2
IMAGE CREATED CREATED BY SIZE COMMENT
ddf43b1f3751 6 days ago cmd /S /C powershell -Command Sleep 2 ; Inv 127.2 MB
d43abb81204a 7 days ago cmd /S /C powershell -Command Sleep 2 ; Inv 66.46 MB
7a21073861a1 7 days ago cmd /S /C powershell -Command Sleep 2 ; Inv 115.8 MB
6801d964fda5 5 months ago
L'ordine delle istruzioni è importante quando si utilizzano le cache delle immagini, come si vedrà nella sezione successiva.
Istruzioni per l'ordinamento
Un Dockerfile viene elaborato dall'alto verso il basso e ogni istruzione viene confrontata rispetto ai livelli memorizzati nella cache. Quando viene rilevata un'istruzione senza un livello memorizzato nella cache, l'istruzione e tutte le istruzioni successive vengono elaborate in nuovi livelli dell'immagine contenitore. Per questo motivo è importante l'ordine in cui vengono posizionate le istruzioni. Inserire le istruzioni che rimangono costanti nella parte superiore del Dockerfile. Inserire le istruzioni che possono cambiare nella parte inferiore del Dockerfile. In questo modo si riduce la probabilità di un mancato riconoscimento di copie effettivamente esistenti nella cache.
Gli esempi seguenti illustrano come l'ordinamento delle istruzioni Dockerfile può influire sull'efficacia della memorizzazione nella cache. In questo semplice esempio Dockerfile sono presenti quattro cartelle numerate.
FROM mcr.microsoft.com/windows/servercore:ltsc2019
RUN mkdir test-1
RUN mkdir test-2
RUN mkdir test-3
RUN mkdir test-4
L'immagine risultante ha cinque livelli, uno per l'immagine del sistema operativo di base e ognuna delle RUN
istruzioni.
docker history doc-sample-1
IMAGE CREATED CREATED BY SIZE COMMENT
afba1a3def0a 38 seconds ago cmd /S /C mkdir test-4 42.46 MB
86f1fe772d5c 49 seconds ago cmd /S /C mkdir test-3 42.35 MB
68fda53ce682 About a minute ago cmd /S /C mkdir test-2 6.745 MB
5e5aa8ba1bc2 About a minute ago cmd /S /C mkdir test-1 7.12 MB
6801d964fda5 5 months ago 0 B
Questo dockerfile successivo è stato leggermente modificato, con la terza RUN
istruzione modificata in un nuovo file. Quando la compilazione Docker viene eseguita su questo Dockerfile, le prime tre istruzioni, che sono identiche a quelle nell'ultimo esempio, usano i livelli di immagine memorizzati nella cache. Tuttavia, poiché l'istruzione modificata RUN
non viene memorizzata nella cache, viene creato un nuovo livello per l'istruzione modificata e per tutte le istruzioni successive.
FROM mcr.microsoft.com/windows/servercore:ltsc2019
RUN mkdir test-1
RUN mkdir test-2
RUN mkdir test-5
RUN mkdir test-4
Quando si confrontano gli ID immagine della nuova immagine con quello nel primo esempio di questa sezione, si noterà che i primi tre livelli dal basso verso l'alto sono condivisi, ma il quarto e il quinto sono univoci.
docker history doc-sample-2
IMAGE CREATED CREATED BY SIZE COMMENT
c92cc95632fb 28 seconds ago cmd /S /C mkdir test-4 5.644 MB
2f05e6f5c523 37 seconds ago cmd /S /C mkdir test-5 5.01 MB
68fda53ce682 3 minutes ago cmd /S /C mkdir test-2 6.745 MB
5e5aa8ba1bc2 4 minutes ago cmd /S /C mkdir test-1 7.12 MB
6801d964fda5 5 months ago 0 B
Ottimizzazione cosmetica
Caso di istruzione
Le istruzioni di Dockerfile non fanno distinzione tra maiuscole e minuscole, ma la convenzione prevede l'uso di maiuscole e minuscole. Ciò migliora la leggibilità differenziando la chiamata all'istruzione e l'operazione di istruzione. I due esempi seguenti confrontano un Dockerfile senza maiuscole e senza maiuscole.
Di seguito è riportato un Dockerfile non capitalizzato:
# Sample Dockerfile
from mcr.microsoft.com/windows/servercore:ltsc2019
run dism /online /enable-feature /all /featurename:iis-webserver /NoRestart
run echo "Hello World - Dockerfile" > c:\inetpub\wwwroot\index.html
cmd [ "cmd" ]
Di seguito è riportato lo stesso Dockerfile usando il maiuscolo:
# Sample Dockerfile
FROM mcr.microsoft.com/windows/servercore:ltsc2019
RUN dism /online /enable-feature /all /featurename:iis-webserver /NoRestart
RUN echo "Hello World - Dockerfile" > c:\inetpub\wwwroot\index.html
CMD [ "cmd" ]
Ritorno a capo linea
Le operazioni lunghe e complesse possono essere separate su più righe in base al carattere barra rovesciata \
. Il Dockerfile seguente installa il pacchetto ridistribuibile di Visual Studio, rimuove i file del programma di installazione e poi crea un file di configurazione. Queste tre operazioni sono tutte specificate su una sola riga.
FROM mcr.microsoft.com/windows/servercore:ltsc2019
RUN powershell -Command c:\vcredist_x86.exe /quiet ; Remove-Item c:\vcredist_x86.exe -Force ; New-Item c:\config.ini
Il comando può essere suddiviso con barre rovesciate in modo che ogni operazione di un'istruzione RUN
venga specificata sulla propria riga.
FROM mcr.microsoft.com/windows/servercore:ltsc2019
RUN powershell -Command \
$ErrorActionPreference = 'Stop'; \
Start-Process c:\vcredist_x86.exe -ArgumentList '/quiet' -Wait ; \
Remove-Item c:\vcredist_x86.exe -Force ; \
New-Item c:\config.ini
Altre letture e riferimenti
Procedure consigliate per la scrittura di Dockerfile in Docker.com