{"id":4019,"date":"2022-01-07T13:58:00","date_gmt":"2022-01-07T12:58:00","guid":{"rendered":"https:\/\/blog.besharp.it\/?p=4019"},"modified":"2022-01-05T16:12:52","modified_gmt":"2022-01-05T15:12:52","slug":"deep-dive-in-docker-trucchi-e-suggerimenti-per-costruire-immagini-docker-ottimizzate-per-sicurezza-e-dimensioni","status":"publish","type":"post","link":"https:\/\/blog.besharp.it\/it\/deep-dive-in-docker-trucchi-e-suggerimenti-per-costruire-immagini-docker-ottimizzate-per-sicurezza-e-dimensioni\/","title":{"rendered":"Deep dive in Docker: trucchi e suggerimenti per costruire immagini Docker ottimizzate per sicurezza e dimensioni."},"content":{"rendered":"\n
Oggigiorno abbiamo sempre pi\u00f9 workload basati su Docker ed \u00e8 di grande importanza tenere le nostre immagini Docker sicure ed ottimizzate per il cloud. Abbiamo gi\u00e0 discusso su Docker nel nostro blog, potete approfondire l\u2019argomento con le origini di Docker<\/a> o con un caso d\u2019uso con WordPress<\/a>.<\/p>\n\n\n\n Nei prossimi paragrafi vedremo alcuni suggerimenti e trucchi su come evitare le falle di sicurezza pi\u00f9 comuni e come ottimizzare le dimensioni delle nostre immagini Docker.<\/p>\n\n\n\n Ma prima dobbiamo capire uno dei concetti chiave di Docker: il sistema di layering.<\/p>\n\n\n\n Il Dockerfile \u00e8 il file principale che definisce il modo in cui un\u2019immagine Docker \u00e8 costruita. In esso viene definita l\u2019immagine di base da cui partire, il modo in cui l\u2019applicativo viene pacchettizzato e come viene eseguito.<\/p>\n\n\n\n Quando avviamo il processo di build a partire da un Dockerfile, il motore di Docker crea una serie di layer, uno per ciascun comando nel Dockerfile. Ogni volta che eseguiamo un comando all\u2019interno del Dockerfile, un nuovo layer viene creato al di sopra del precedente. Il motore di Docker esegue i comandi in modo sequenziale e infine unisce tutti i layer per creare l\u2019immagine finale.<\/p>\n\n\n\n Generalmente, avere un\u2019immagine piccola velocizza la fase di build, deploy ed esecuzione. Per ottenere questo, una buona idea \u00e8 partire da un\u2019immagine di base che \u00e8 essa stessa piccola. Puoi usare `alpine:3.15` che \u00e8 di circa 5.6 MB invece di `ubuntu:20.04` che \u00e8 (al momento di scrittura di questo articolo) di 72 MB.<\/p>\n\n\n\n Alpine<\/a> \u00e8 una distribuzione Linux costruita con musl libc e BusyBox che punta alla semplicit\u00e0, sicurezza e all\u2019efficienza delle risorse. Essa contiene soltanto i pacchetti assolutamente necessari perch\u00e9\u2026 se una cosa non c\u2019\u00e8, non pu\u00f2 rompersi<\/em>.<\/p>\n\n\n\n Bisogna tenere in mente che ha anche alcuni svantaggi. Per esempio, visto che Alpine \u00e8 basata sulla libreria C musl, invece che sulla libreria pi\u00f9 diffusa GNU C Library, ci possono essere problemi con alcune dipendenze in C.<\/p>\n\n\n\n Oltre a usare Alpine come immagine di base, un altro metodo per ridurre le dimensioni delle immagini Docker \u00e8 l\u2019uso delle build multistage. Una build multistage consiste in un unico Dockerfile in cui definiamo pi\u00f9 istruzioni FROM, ed ognuna di esse \u00e8 uno stage.<\/p>\n\n\n\n In ogni FROM possiamo partire da uno stage precedente per trarre vantaggio dagli artefatti di build in cache oppure possiamo partire da un\u2019immagine di base totalmente diversa e copiare solamente alcuni artefatti dallo stage precedente.<\/p>\n\n\n\n Vediamo un veloce esempio:<\/p>\n\n\n\n In questo Dockerfile multistage abbiamo creato un\u2019immagine di base che ha tutte le dipendenze della nostra applicazione, abbiamo creato uno stage per fare la build dell\u2019applicazione e infine, per l\u2019immagine di runtime, abbiamo usato un\u2019immagine di base pulita, ci abbiamo installato le dipendenze di produzione e copiato gli artefatti necessari.<\/p>\n\n\n\n Di default vengono costruiti tutti gli stage ma possiamo specificarne uno in particolare con il flag `–target <stage-name>`<\/p>\n\n\n\n `docker build –target release –tag image .`<\/p>\n\n\n\nCome posso ridurre le dimensioni?<\/h2>\n\n\n\n
Usa un\u2019immagine di base piccola. Alpine \u00e8 una buona scelta<\/strong><\/h3>\n\n\n\n
Usa i Dockerfile multi-stage<\/strong><\/h3>\n\n\n\n
# Base image with dependencies\nFROM node:17.3.0-alpine3.12 AS base\nWORKDIR \/app\n# Copy package.json and package-lock.json\nCOPY package*.json .\/\n# Install dependencies\nRUN npm install\n \n \n# Build Stage\nFROM base AS build\nWORKDIR \/app\nCOPY . .\/\n# Build and bundle static files\nRUN npm run build\n \n \n# Release Stage\nFROM node:17.3.0-alpine3.12 AS release\nWORKDIR \/app\nCOPY --from=base \/app\/package.json .\/\n# Install app dependencies\nRUN npm install --only=production\nCOPY --from=build \/app\/dist\/ .\/\nCMD [ \"npm\", \"run\", \"start\" ]<\/code><\/pre>\n\n\n\n