Criar contentores mais simples

Esta página descreve como criar imagens Docker mais simples.

Criar contentores mais simples

Quando coloca uma aplicação num contentor, os ficheiros que não são necessários no tempo de execução, como dependências de tempo de compilação e ficheiros intermédios, podem ser incluídos inadvertidamente na imagem do contentor. Estes ficheiros desnecessários podem aumentar o tamanho da imagem do contentor e, assim, adicionar tempo e custos adicionais à medida que a imagem se move entre o registo do Docker e o tempo de execução do contentor.

Para ajudar a reduzir o tamanho da imagem do contentor, separe a criação da aplicação, juntamente com as ferramentas usadas para a criar, da montagem do contentor de tempo de execução.

O Cloud Build fornece uma série de contentores Docker com ferramentas de programador comuns, como o Git, o Docker e a CLI Google Cloud. Use estas ferramentas para definir um ficheiro de configuração de compilação com um passo para compilar a aplicação e outro passo para montar o respetivo ambiente de tempo de execução final.

Por exemplo, se estiver a criar uma aplicação Java, que requer ficheiros como o código fonte, as bibliotecas de aplicações, os sistemas de compilação, as dependências do sistema de compilação e o JDK, pode ter um Dockerfile com o seguinte aspeto:

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, transfere um grande número de bibliotecas para funcionar. Estas bibliotecas são essenciais para a criação do pacote, mas não são necessárias no tempo de execução. Todas as dependências de tempo de execução estão incluídas no pacote.

Cada comando em Dockerfile cria uma nova camada no contentor. Se os dados forem gerados nessa camada e não forem eliminados no mesmo comando, não é possível recuperar esse espaço. Neste caso, o Gradle transfere centenas de megabytes de bibliotecas para o diretório cache para realizar a compilação, mas as bibliotecas não são eliminadas.

Uma forma mais eficiente de realizar a compilação é usar o Cloud Build para separar a compilação da aplicação da compilação da respetiva camada de tempo de execução.

O exemplo seguinte separa o passo de criação da aplicação Java do passo de montagem do contentor de tempo de execução:

YAML

  1. Crie a aplicação: no cloudbuild.yaml, adicione um passo para criar a aplicação.

    O código seguinte adiciona um passo 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. Crie o contentor de tempo de execução: em cloudbuild.yaml, adicione um passo para criar o contentor de tempo de execução.

    O código seguinte adiciona um passo denominado gcr.io/cloud-builders/docker que monta o contentor de tempo de execução. Define o contentor de tempo de execução num ficheiro separado denominado Dockerfile.slim.

    O exemplo usa a camada base do Alpine Linux openjdk:8u111-jre-alpine, que é incrivelmente simples. Além disso, inclui o JRE, em vez do JDK mais volumoso que era necessário para criar a aplicação.

    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 de Docker: em cloudbuild.yaml, adicione um passo 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 a aplicação: no cloudbuild.json, adicione um passo para criar a aplicação.

    O código seguinte adiciona um passo denominado 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. Crie o contentor de tempo de execução: em cloudbuild.json, adicione um passo para criar o contentor de tempo de execução.

    O código seguinte adiciona um passo denominado gcr.io/cloud-builders/docker que monta o contentor de tempo de execução. Define o contentor de tempo de execução num ficheiro separado denominado Dockerfile.slim.

    O exemplo usa a camada base do Alpine Linux openjdk:8u111-jre-alpine, que é incrivelmente simples. Além disso, inclui o JRE, em vez do JDK mais volumoso que era necessário para criar a aplicação.

    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 de Docker: em cloudbuild.json, adicione um passo 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"
        ]
    }