5

我正在开发一个 CloudBuild 脚本,该脚本为集成测试构建多阶段 Docker 映像。为了优化构建脚本,我选择使用Kaniko。下面提供了 Dockerfile 和 cloudbuild.yaml 文件的相关部分。

cloudbuild.yaml

steps:
  # Build BASE image
  - name: gcr.io/kaniko-project/executor:v0.17.1
    id: buildinstaller
    args:
      - --destination=gcr.io/$PROJECT_ID/<MY_REPO>-installer:$BRANCH_NAME
      - --destination=gcr.io/$PROJECT_ID/<MY_REPO>-installer:$SHORT_SHA
      - --cache=true
      - --cache-ttl=24h
      - --cache-repo=gcr.io/$PROJECT_ID/<MY_REPO>/cache
      - --target=installer
  # Build TEST image
  - name: gcr.io/kaniko-project/executor:v0.17.1
    id: buildtest
    args:
      - --destination=gcr.io/$PROJECT_ID/<MY_REPO>-test:$BRANCH_NAME
      - --destination=gcr.io/$PROJECT_ID/<MY_REPO>-test:$SHORT_SHA
      - --cache=true
      - --cache-ttl=24h
      - --cache-repo=gcr.io/$PROJECT_ID/<MY_REPO>/cache
      - --target=test-image
    waitFor:
      - buildinstaller
  # --- REMOVED SOME CODE FOR BREVITY ---
  # Build PRODUCTION image
  - name: gcr.io/kaniko-project/executor:v0.17.1
    id: build
    args:
      - --destination=gcr.io/$PROJECT_ID/<MY_REPO>:$BRANCH_NAME
      - --destination=gcr.io/$PROJECT_ID/<MY_REPO>:$SHORT_SHA
      - --destination=gcr.io/$PROJECT_ID/<MY_REPO>:latest
      - --cache=true
      - --cache-ttl=24h
      - --cache-dir=/cache
      - --target=production-image
    waitFor:
      - test # TODO: This will run after tests which were not included here for brevity
images:
  - gcr.io/$PROJECT_ID/<MY_REPO>

Dockerfile

FROM ruby:2.5-alpine AS installer

# Expose port
EXPOSE 3000

# Set desired port
ENV PORT 3000

# set the app directory var
ENV APP_HOME /app
RUN mkdir -p ${APP_HOME}
WORKDIR ${APP_HOME}

# Install necessary packanges
RUN apk add --update --no-cache \
  build-base curl less libressl-dev zlib-dev git \
  mariadb-dev tzdata imagemagick libxslt-dev \
  bash nodejs

# Copy gemfiles to be able to bundle install
COPY Gemfile* ./

#############################
# STAGE 1.5: Test build #
#############################
FROM installer AS test-image

# Set environment
ENV RAILS_ENV test

# Install gems to /bundle
RUN bundle install --deployment --jobs $(nproc) --without development local_gems 

# Add app files
ADD . .
RUN bundle install --with local_gems

#############################
# STAGE 2: Production build #
#############################
FROM installer AS production-image

# Set environment
ENV RAILS_ENV production

# Install gems to /bundle
RUN bundle install --deployment --jobs $(nproc) --without development test local_gems 

# Add app files
ADD . .
RUN bundle install --with local_gems

# Precompile assets
RUN DB_ADAPTER=nulldb bundle exec rake assets:precompile assets:clean

# Puma start command
CMD ["bundle", "exec", "puma", "-C", "config/puma.rb"]

由于我的 Docker 映像是一个多阶段构建,具有 2 个独立的结束阶段,它们共享一个公共基础构建,我想在公共部分和其他两个部分之间共享缓存。为此,我将所有构建设置为共享同一个缓存存储库- --cache-repo=gcr.io/$PROJECT_ID/<MY_REPO>/cache。到目前为止,它在我所有的测试中都有效。但是,我无法确定这是否是最佳实践,或者是否会推荐其他缓存基本图像的方式。这是一个可接受的实现吗?

我遇到了Kaniko-warmer,但我无法根据我的情况使用它。

4

1 回答 1

6

在提及有关如何缓存基本映像的任何最佳实践之前,有一些最佳实践可以优化构建的性能。由于您已经使用 Kaniko 并且正在缓存存储库中的图像,我相信您的实现遵循上述最佳实践。

我要提出的唯一建议是使用Google Cloud Storage重用您之前构建的结果。如果您的构建需要很长时间,并且生成的文件不多,并且将它们从Cloud Storage 复制Cloud Storage并不需要很多时间,那么这将加快您的构建速度。

此外,以下文章中还介绍了一些关于优化构建缓存的最佳实践。我认为其中最重要的是:

“将经常更改的构建步骤放在 Dockerfile 的底部。如果将它们放在顶部,Docker 将无法将其构建缓存用于其他不经常更改的构建步骤。因为通常为每个构建步骤构建一个新的 Docker 映像新版本的源代码,请在 Dockerfile 中尽可能晚地将源代码添加到镜像中”。

最后我要考虑的另一件事是缓存过期时间

请记住,它必须进行适当的配置,以免丢失任何依赖项的更新,但不会在没有任何使用的情况下运行构建。

您可能认为有用的更多链接(请记住,这些不是 Google 来源):

关于多阶段构建的 Docker 文档

使用多阶段构建来简化和标准化构建过程

于 2020-02-11T12:02:11.570 回答