Como criar contêineres mais enxutos

Nesta página, você vê como criar imagens mais enxutas do Docker.

Como criar contêineres mais enxutos

Quando você coloca um aplicativo em contêineres, os arquivos que não são necessários no ambiente de execução, como dependências de tempo de compilação e arquivos intermediários, são incluídos inadvertidamente na imagem do contêiner. Esses arquivos desnecessários aumentam o tamanho da imagem e geram mais tempo e custo à medida que ela é transferida entre o registro do Docker e o ambiente de execução do contêiner.

Para reduzir o tamanho da imagem do contêiner, separe a compilação do aplicativo, além das ferramentas usadas para criá-lo, a partir da montagem do contêiner do ambiente de execução.

O Cloud Build oferece uma série de contêineres do Docker com ferramentas comuns para desenvolvedores, como Git, Docker e a interface de linha de comando gcloud. Use essas ferramentas para definir um arquivo de configuração de versão com uma etapa para criar o aplicativo e outra para montar o ambiente de tempo de execução final.

Por exemplo, se você estiver criando um aplicativo Java, que exige arquivos como o código-fonte, as bibliotecas de aplicativos, os sistemas de versão, as dependências do sistema de versão e o JDK, é possível ter um Dockerfile como o mostrado abaixo:

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"]

No exemplo acima, o Gradle, que é usado para criar o pacote, faz o download de um grande número de bibliotecas para fins de funcionamento. Essas bibliotecas são essenciais para a criação do pacote, mas não são necessárias no momento da execução. Todas as dependências de tempo de execução são agrupadas no pacote.

Cada comando no Dockerfile cria uma nova camada no contêiner. Se os dados forem gerados nessa camada e não forem excluídos no mesmo comando, esse espaço não poderá ser recuperado. Neste caso, o Gradle está fazendo o download de centenas de megabytes de bibliotecas para o diretório de cache, a fim de executar a versão, mas as bibliotecas não são excluídas.

Uma maneira mais eficiente de executar a versão é usar o Cloud Build para separar a criação do aplicativo da criação da camada de tempo de execução dele.

No exemplo a seguir, separamos a etapa de criação do aplicativo Java da etapa de montagem do contêiner de tempo de execução:

YAML

  1. Crie o aplicativo: em cloudbuild.yaml, adicione uma etapa para criar o aplicativo.

    Com o código a seguir, você adiciona uma etapa que cria a imagem java:8, que contém o código Java.

    steps:
    
    - name: 'java:8'
      env: ['GRADLE_USER_HOME=cache']
      entrypoint: 'bash'
      args: ['-c', './gradlew gate-web:installDist -x test']
    
    
  2. Monte o contêiner de ambiente de execução: em cloudbuild.yaml, adicione uma etapa para montar o contêiner de ambiente de execução.

    O código a seguir adiciona uma etapa chamada gcr.io/cloud-builders/docker, que monta o contêiner de tempo de execução. Ele define o contêiner de tempo de execução em um arquivo separado chamado Dockerfile.slim.

    O exemplo usa a camada de base Alpine Linux openjdk:8u111-jre-alpine, que é incrivelmente enxuta. Além disso, ele inclui o JRE em vez do JDK mais volumoso, que foi necessário para criar o aplicativo.

    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"]
    
  3. Crie as imagens do Docker: em cloudbuild.yaml, adicione uma etapa para criar as imagens.
    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

  1. Crie o aplicativo: em cloudbuild.json, adicione uma etapa para criar o aplicativo.

    O código a seguir adiciona uma etapa chamada java:8 para criar o código Java.

    {
        "steps": [
        {
            "name": "java:8",
            "env": [
                "GRADLE_USER_HOME=cache"
            ],
            "entrypoint": "bash",
            "args": [
                "-c",
                "./gradlew gate-web:installDist -x test"
            ]
        },
    }
    
  2. Monte o contêiner de ambiente de execução: em cloudbuild.json, adicione uma etapa para montar o contêiner de ambiente de execução.

    O código a seguir adiciona uma etapa chamada gcr.io/cloud-builders/docker, que monta o contêiner de tempo de execução. Ele define o contêiner de tempo de execução em um arquivo separado chamado Dockerfile.slim.

    O exemplo usa a camada de base Alpine Linux openjdk:8u111-jre-alpine, que é incrivelmente enxuta. Além disso, ele inclui o JRE em vez do JDK mais volumoso, que foi necessário para criar o aplicativo.

    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"]
    
  3. Crie as imagens do Docker: em cloudbuild.json, adicione uma etapa para criar as imagens.
    {
        "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"
        ]
    }
    

Enviar comentários sobre…