En esta página, se describe cómo compilar imágenes de Docker más eficaces.
Compila contenedores más eficientes
Cuando creas contenedores para una aplicación, los archivos que no se necesitan en el entorno de ejecución, como las dependencias de tiempo de compilación y los archivos intermedios, se pueden incluir inadvertidamente en la imagen del contenedor. Estos archivos innecesarios pueden aumentar el tamaño de la imagen del contenedor y agregar tiempo y costo adicionales cuando la imagen se mueve entre tu registro de Docker y el entorno de ejecución de tu contenedor.
Para ayudar a reducir el tamaño de la imagen de tu contenedor, separa la compilación de la aplicación, junto con las herramientas usadas para compilarla, del ensamblaje del contenedor de entorno de ejecución.
Cloud Build proporciona una serie de contenedores de Docker con herramientas para desarrolladores comunes como Git, Docker y Google Cloud CLI. Usa estas herramientas a fin de definir un archivo de configuración de compilación con un paso de compilación de la aplicación y otro paso para ensamblar su entorno de ejecución final.
Por ejemplo, si compilas una aplicación Java, que requiere archivos como el código fuente, las bibliotecas de la aplicación, los sistemas de compilación, las dependencias del sistema de compilación y el JDK, es posible que tengas un Dockerfile similar al siguiente:
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"]
En el ejemplo anterior, Gradle, que se usa a fin de compilar el paquete, descarga muchas bibliotecas para funcionar. Estas bibliotecas son indispensables para la compilación del paquete, pero no son necesarias en el entorno de ejecución. Todas las dependencias del entorno de ejecución se juntan en el paquete.
Con cada comando en el Dockerfile
, se crea una capa nueva en el contenedor. Si se generan datos en esa capa y no se borran en el mismo comando, ese espacio no se puede recuperar. En este caso, Gradle descarga cientos de megabytes de bibliotecas en el directorio cache
para realizar la compilación, pero las bibliotecas no se borran.
Una forma más eficaz de realizar la compilación es usar Cloud Build a fin de separar la compilación de la aplicación de la compilación de su capa de entorno de ejecución.
El ejemplo siguiente separa el paso de compilación de la aplicación Java del paso de ensamblaje del contenedor del entorno de ejecución:
YAML
-
Compila la aplicación: En
cloudbuild.yaml
, agrega un paso para compilar la aplicación.Con el siguiente código, se agrega un paso que compila la imagen
java:8
, que contiene el código de Java.steps: - name: 'java:8' env: ['GRADLE_USER_HOME=cache'] entrypoint: 'bash' args: ['-c', './gradlew gate-web:installDist -x test']
- Ensambla el contenedor de entorno de ejecución: En
cloudbuild.yaml
, agrega un paso para ensamblar el contenedor de entorno de ejecución.Con el siguiente código, se agrega un paso llamado
gcr.io/cloud-builders/docker
que ensambla el contenedor de entorno de ejecución. Define el contenedor de entorno de ejecución en un archivo diferente llamadoDockerfile.slim
.En el ejemplo, se usa la capa base de Alpine Linux
openjdk:8u111-jre-alpine
, que es increíblemente eficiente. Además, incluye el JRE, en lugar del JDK más voluminoso que era necesario para compilar la aplicación.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 las imágenes de Docker: En
cloudbuild.yaml
, agrega un paso para crear las imágenes.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
-
Compila la aplicación: En
cloudbuild.json
, agrega un paso para compilar la aplicación.Con el siguiente código, se agrega un paso llamado
java:8
para compilar el código de Java.{ "steps": [ { "name": "java:8", "env": [ "GRADLE_USER_HOME=cache" ], "entrypoint": "bash", "args": [ "-c", "./gradlew gate-web:installDist -x test" ] }, }
-
Ensambla el contenedor de entorno de ejecución: En
cloudbuild.json
, agrega un paso para ensamblar el contenedor de entorno de ejecución.Con el siguiente código, se agrega un paso llamado
gcr.io/cloud-builders/docker
que ensambla el contenedor de entorno de ejecución. Define el contenedor de entorno de ejecución en un archivo diferente llamadoDockerfile.slim
.En el ejemplo, se usa la capa base de Alpine Linux
openjdk:8u111-jre-alpine
, que es increíblemente eficiente. Además, incluye el JRE, en lugar del JDK más voluminoso que era necesario para compilar la aplicación.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 las imágenes de Docker: En
cloudbuild.json
, agrega un paso para crear las imágenes.{ "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" ] }