本页面介绍如何构建更精简的 Docker 映像。
构建更精简的容器
当您对应用进行容器化时,在运行时不需要的文件(例如构建时依赖项和中间文件)可能会意外包含在容器映像中。当映像在您的 Docker 注册表和容器运行时之间移动时,这些不需要的文件会增加容器映像的大小,从而增加额外时间和费用。
为了帮助减小容器映像的大小,请将应用的构建(以及构建应用所用的工具)与运行时容器的组建分开。
Cloud Build 提供一系列 Docker 容器,这些容器安装有常用开发者工具,例如 Git、Docker 和 Google Cloud CLI。使用这些工具可以定义构建配置文件,其中一个步骤用于构建应用,另一个步骤用于组建应用的最终运行时环境。
例如,如果您要构建一个 Java 应用,该应用需要 源代码、应用库、构建系统、构建系统 则您可能会有一个类似于 以下:
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
-
构建应用:在
cloudbuild.yaml
中,添加一个步骤来构建应用。以下代码会添加一个步骤,用于构建包含 Java 代码的
java:8
映像。steps: - name: 'java:8' env: ['GRADLE_USER_HOME=cache'] entrypoint: 'bash' args: ['-c', './gradlew gate-web:installDist -x test']
- 组建运行时容器:在
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"]
- 创建 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
-
构建应用:在
cloudbuild.json
中,添加一个步骤来构建应用。以下代码添加一个名为
java:8
的步骤,用于构建 Java 代码。{ "steps": [ { "name": "java:8", "env": [ "GRADLE_USER_HOME=cache" ], "entrypoint": "bash", "args": [ "-c", "./gradlew gate-web:installDist -x test" ] }, }
-
组建运行时容器:在
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"]
- 创建 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" ] }