Questa pagina descrive come creare immagini Docker più snelle.
Creazione di container più snelli
Quando esegui il containerizzazione di un'applicazione, i file non necessari in fase di esecuzione, come le dipendenze di compilazione e i file intermedi, possono essere inclusi inavvertitamente nell'immagine del contenitore. Questi file non necessari possono aumentare le dimensioni dell'immagine del contenitore e, di conseguenza, aggiungere tempo e costi aggiuntivi durante il trasferimento dell'immagine tra il registry Docker e il runtime del contenitore.
Per contribuire a ridurre le dimensioni dell'immagine del container, separa la compilazione dell'applicazione, insieme agli strumenti utilizzati per compilarla, dall'assemblaggio del container di runtime.
Cloud Build fornisce una serie di container Docker con strumenti comuni per gli sviluppatori come Git, Docker e l'Google Cloud CLI. Utilizza questi strumenti per definire un file di configurazione della build con un passaggio per compilare l'applicazione e un altro per assemblare il relativo ambiente di runtime finale.
Ad esempio, se stai creando un'applicazione Java, che richiede file come il codice sorgente, le librerie dell'applicazione, i sistemi di compilazione, le dipendenze del sistema di compilazione e il JDK, potresti avere un Dockerfile simile al seguente:
FROM java:8
COPY . workdir/
WORKDIR workdir
RUN GRADLE_USER_HOME=cache ./gradlew buildDeb -x test
RUN dpkg -i ./gate-web/build/distributions/*.deb
CMD ["/opt/gate/bin/gate"]
Nell'esempio riportato sopra, Gradle, che viene utilizzato per compilare il pacchetto, scarica un gran numero di librerie per funzionare. Queste librerie sono essenziali per la compilazione del pacchetto, ma non sono necessarie in fase di esecuzione. Tutte le dipendenze di runtime sono raggruppate nel pacchetto.
Ogni comando in Dockerfile
crea un nuovo livello nel contenitore. Se i dati vengono generati in quel livello e non vengono eliminati nello stesso comando, lo spazio non può essere recuperato. In questo caso, Gradle scarica centinaia di megabyte di librerie nella directory cache
per eseguire la compilazione, ma le librerie non vengono eliminate.
Un modo più efficiente per eseguire la compilazione è utilizzare Cloud Build per separare la compilazione dell'applicazione dalla compilazione del relativo livello di runtime.
L'esempio seguente separa il passaggio per la compilazione dell'applicazione Java dal passaggio per l'assemblaggio del contenitore del runtime:
YAML
-
Crea l'applicazione: in
cloudbuild.yaml
, aggiungi un passaggio per compilare l'applicazione.Il codice seguente aggiunge un passaggio che genera l'immagine
java:8
, che contiene il codice Java.steps: - name: 'java:8' env: ['GRADLE_USER_HOME=cache'] entrypoint: 'bash' args: ['-c', './gradlew gate-web:installDist -x test']
- Assembla il contenitore del runtime: in
cloudbuild.yaml
, aggiungi un passaggio per assemblare il contenitore del runtime.Il codice seguente aggiunge un passaggio denominato
gcr.io/cloud-builders/docker
che assembla il contenitore del runtime. Definisce il contenitore di runtime in un file separato denominatoDockerfile.slim
.L'esempio utilizza il livello di base di Alpine Linux
openjdk:8u111-jre-alpine
, che è incredibilmente snello. Inoltre, include il JRE anziché il JDK più ingombrante necessario per compilare l'applicazione.cloudbuild.yaml steps: - name: 'java:8' env: ['GRADLE_USER_HOME=cache'] entrypoint: 'bash' args: ['-c', './gradlew gate-web:installDist -x test'] - name: 'gcr.io/cloud-builders/docker' args: ['build', '-t', 'gcr.io/$PROJECT_ID/$REPO_NAME:$COMMIT_SHA', '-t', 'gcr.io/$PROJECT_ID/$REPO_NAME:latest', '-f', 'Dockerfile.slim', '.' ] Dockerfile.slim FROM openjdk:8-jre-alpine COPY ./gate-web/build/install/gate /opt/gate CMD ["/opt/gate/bin/gate"]
- Crea le immagini Docker: in
cloudbuild.yaml
, aggiungi un passaggio per creare le immagini.steps: - name: 'java:8' env: ['GRADLE_USER_HOME=cache'] entrypoint: 'bash' args: ['-c', './gradlew gate-web:installDist -x test'] - name: 'gcr.io/cloud-builders/docker' args: ['build', '-t', 'gcr.io/$PROJECT_ID/$REPO_NAME:$COMMIT_SHA', '-t', 'gcr.io/$PROJECT_ID/$REPO_NAME:latest', '-f', 'Dockerfile.slim', '.'] images: - 'gcr.io/$PROJECT_ID/$REPO_NAME:$COMMIT_SHA' - 'gcr.io/$PROJECT_ID/$REPO_NAME:latest'
JSON
-
Crea l'applicazione: in
cloudbuild.json
, aggiungi un passaggio per compilare l'applicazione.Il codice seguente aggiunge un passaggio denominato
java:8
per compilare il codice Java.{ "steps": [ { "name": "java:8", "env": [ "GRADLE_USER_HOME=cache" ], "entrypoint": "bash", "args": [ "-c", "./gradlew gate-web:installDist -x test" ] }, }
-
Assembla il contenitore di runtime: in
cloudbuild.json
, aggiungi un passaggio per assemblare il contenitore di runtime.Il codice seguente aggiunge un passaggio denominato
gcr.io/cloud-builders/docker
che assembla il contenitore del runtime. Definisce il contenitore di runtime in un file separato denominatoDockerfile.slim
.L'esempio utilizza il livello di base di Alpine Linux
openjdk:8u111-jre-alpine
, che è incredibilmente snello. Inoltre, include il JRE anziché il JDK più ingombrante necessario per compilare l'applicazione.cloudbuild.json: { "steps": [ { "name": "java:8", "env": [ "GRADLE_USER_HOME=cache" ], "entrypoint": "bash", "args": [ "-c", "./gradlew gate-web:installDist -x test" ] }, { "name": "gcr.io/cloud-builders/docker", "args": [ "build", "-t", "gcr.io/$PROJECT_ID/$REPO_NAME:$COMMIT_SHA", "-t", "gcr.io/$PROJECT_ID/$REPO_NAME:latest", "-f", "Dockerfile.slim", "." ] } ], } Dockerfile.slim: FROM openjdk:8u111-jre-alpine COPY ./gate-web/build/install/gate /opt/gate CMD ["/opt/gate/bin/gate"]
- Crea le immagini Docker: in
cloudbuild.json
, aggiungi un passaggio per creare le immagini.{ "steps": [ { "name": "java:8", "env": [ "GRADLE_USER_HOME=cache" ], "entrypoint": "bash", "args": [ "-c", "./gradlew gate-web:installDist -x test" ] }, { "name": "gcr.io/cloud-builders/docker", "args": [ "build", "-t", "gcr.io/$PROJECT_ID/$REPO_NAME:$COMMIT_SHA", "-t", "gcr.io/$PROJECT_ID/$REPO_NAME:latest", "-f", "Dockerfile.slim", "." ] } ], "images": [ "gcr.io/$PROJECT_ID/$REPO_NAME:$COMMIT_SHA", "gcr.io/$PROJECT_ID/$REPO_NAME:latest" ] }