构建更精简的容器

本页面介绍如何构建更精简的 Docker 映像。

构建更精简的容器

当您对应用进行容器化时,在运行时不需要的文件(例如构建时依赖项和中间文件)可能会意外包含在容器映像中。当映像在您的 Docker 注册表和容器运行时之间移动时,这些不需要的文件会增加容器映像的大小,从而增加额外时间和费用。

为了帮助减小容器映像的大小,请将应用的构建(以及构建应用所用的工具)与运行时容器的组建分开。

Cloud Build 提供一系列 Docker 容器,这些容器安装有常用开发者工具,例如 Git、Docker 和 Google Cloud CLI。使用这些工具可以定义构建配置文件,其中一个步骤用于构建应用,另一个步骤用于组建应用的最终运行时环境。

例如,如果您要构建一个 Java 应用,该应用需要源代码、应用库、构建系统、构建系统依赖项和 JDK 等文件,则您可能会有一个如下所示的 Dockerfile:

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

在上面的示例中,用于构建软件包的 Gradle 下载了大量库以便正常工作。这些库对于构建软件包至关重要,但在运行时不需要。所有运行时依赖项都捆绑在软件包中。

Dockerfile 中的每个命令都会在容器中创建一个新层。如果在该层中生成数据但未在同一命令中删除,则无法恢复该空间。在这种情况下,Gradle 会将数百兆字节的库下载到 cache 目录以执行构建,但不会删除库。

更有效的执行构建的方法是使用 Cloud Build 将构建应用与构建其运行时层分开。

以下示例将构建 Java 应用的步骤与组建运行时容器的步骤分开:

YAML

  1. 构建应用:在 cloudbuild.yaml 中,添加一个步骤来构建应用。

    以下代码会添加一个步骤,用于构建包含 Java 代码的 java:8 映像。

    steps:
    
    - name: 'java:8'
      env: ['GRADLE_USER_HOME=cache']
      entrypoint: 'bash'
      args: ['-c', './gradlew gate-web:installDist -x test']
    
    
  2. 组建运行时容器:在 cloudbuild.yaml 中,添加一个步骤来组建运行时容器。

    以下代码会添加一个名为 gcr.io/cloud-builders/docker 的步骤,用于组建运行时容器。该代码在名为 Dockerfile.slim 的单独文件中定义运行时容器。

    以下示例使用非常精简的 Alpine Linux 基础层 openjdk:8u111-jre-alpine。此外,该示例还包含 JRE,而不是构建应用所需的庞大的 JDK。

    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. 创建 Docker 映像:在 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', '.']
    images:
    - 'gcr.io/$PROJECT_ID/$REPO_NAME:$COMMIT_SHA'
    - 'gcr.io/$PROJECT_ID/$REPO_NAME:latest'
    

JSON

  1. 构建应用:在 cloudbuild.json 中,添加一个步骤来构建应用。

    以下代码添加一个名为 java:8 的步骤,用于构建 Java 代码。

    {
        "steps": [
        {
            "name": "java:8",
            "env": [
                "GRADLE_USER_HOME=cache"
            ],
            "entrypoint": "bash",
            "args": [
                "-c",
                "./gradlew gate-web:installDist -x test"
            ]
        },
    }
    
  2. 组建运行时容器:在 cloudbuild.json 中,添加一个步骤来组建运行时容器。

    以下代码会添加一个名为 gcr.io/cloud-builders/docker 的步骤,用于组建运行时容器。该代码在名为 Dockerfile.slim 的单独文件中定义运行时容器。

    以下示例使用非常精简的 Alpine Linux 基础层 openjdk:8u111-jre-alpine。此外,该示例还包含 JRE,而不是构建应用所需的庞大的 JDK。

    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. 创建 Docker 映像:在 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",
                "."
            ]
        }
        ],
        "images": [
            "gcr.io/$PROJECT_ID/$REPO_NAME:$COMMIT_SHA",
            "gcr.io/$PROJECT_ID/$REPO_NAME:latest"
        ]
    }