Questa pagina descrive come creare immagini Docker più snelle.
Creazione di container più snelli
Quando containerizza un'applicazione, i file che non sono necessari in fase di runtime, come dipendenze in fase di build e file intermedi, possono essere inclusi inavvertitamente nell'immagine container. 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 Docker di grandi dimensioni con come Git, Docker e 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 delle applicazioni, i sistemi di build, e JDK, potresti avere un Dockerfile simile al seguenti:
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 precedente, Gradle, utilizzato per creare il pacchetto, scarica un numero elevato di librerie per funzionare. Queste librerie sono essenziali per la compilazione del pacchetto, ma non sono necessarie in fase di esecuzione. Tutto il runtime le dipendenze sono raggruppate nel pacchetto.
Ogni comando in Dockerfile
crea un nuovo livello nel container. 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 container di runtime: in
cloudbuild.yaml
, aggiungi un passaggio per assemblare il container 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, invece del più ingombrante JDK necessario per creare un'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 runtime containerizzato. 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, invece del più ingombrante JDK necessario per creare un'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" ] }