【问题标题】:How to cache multi-stage docker build in google cloud builder如何在谷歌云构建器中缓存多阶段 docker 构建
【发布时间】:2018-05-09 09:13:43
【问题描述】:

我有 docker 多阶段构建,例如:

FROM golang:1.7.3
WORKDIR /go/src/github.com/alexellis/href-counter/
RUN go get -d -v golang.org/x/net/html  
COPY app.go .
RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o app .

FROM alpine:latest  
RUN apk --no-cache add ca-certificates
WORKDIR /root/
COPY --from=0 /go/src/github.com/alexellis/href-counter/app .
CMD ["./app"]  

比我有 cloudbuild.yml:

steps:
- name: 'gcr.io/cloud-builders/docker'
  args: ['pull', 'gcr.io/$PROJECT_ID/app:$BRANCH_NAME']
- name: 'gcr.io/cloud-builders/docker'
  args: ['pull', 'gcr.io/$PROJECT_ID/app:latest']
- name: 'gcr.io/cloud-builders/docker'
  args: [
            'build',
            '--cache-from', 'gcr.io/$PROJECT_ID/app:latest',
            '--cache-from', 'gcr.io/$PROJECT_ID/app:$BRANCH_NAME',
            '--build-arg', 'COMMIT_HASH=$COMMIT_SHA',
            '-t', 'gcr.io/$PROJECT_ID/app:$COMMIT_SHA',
            '-f', 'config/dockerfiles/app.dockerfile',
            '.'
        ]
- name: 'gcr.io/cloud-builders/docker'
  args: ["tag", "gcr.io/$PROJECT_ID/app:$COMMIT_SHA", "gcr.io/$PROJECT_ID/app:$BRANCH_NAME"]
- name: 'gcr.io/cloud-builders/docker'
  args: ["tag", "gcr.io/$PROJECT_ID/app:$COMMIT_SHA", "gcr.io/$PROJECT_ID/app:latest"]
images: [
  'gcr.io/$PROJECT_ID/app:$COMMIT_SHA',
  'gcr.io/$PROJECT_ID/app:$BRANCH_NAME',
  'gcr.io/$PROJECT_ID/app:latest'
]

现在我不仅要缓存生成的图像,还要缓存构建器步骤。例如,在 go 中,我有使用 dep 构建的 /vendor,并希望缓存这些依赖项。我将如何通过谷歌云平台实现最简单的目标?我认为我的问题主要是特定于码头工人的,但仍然如此。

【问题讨论】:

  • 您是否从我们的文档中查看了此页面? cloud.google.com/container-builder/docs/…
  • 我做了,但是你怎么引用它?如果你能提供端到端的例子,我会非常高兴
  • 你应该把这个帖子发到ServerFault,Stackoverflow更适合开发者关注。
  • 你有没有找到任何解决方法?你做得怎么样?
  • 最后,我制作了每次更新的次要图像,它是构建器图像。 ((即第一阶段是单独的 docker 文件,第二阶段使用带有 COPY --from 的第一阶段))

标签: docker google-cloud-platform


【解决方案1】:

构建器映像需要单独构建和标记。您需要从构建阶段推送该图像并在下一个构建中将其用作缓存。为此,命名您的构建阶段更方便。

FROM golang:1.7.3 as builder
WORKDIR /go/src/github.com/alexellis/href-counter/
RUN go get -d -v golang.org/x/net/html  
COPY app.go .
RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o app .

FROM alpine:latest  
RUN apk --no-cache add ca-certificates
WORKDIR /root/
COPY --from=builder /go/src/github.com/alexellis/href-counter/app .
CMD ["./app"]

在您的cloudbuild.yaml 中,您需要知道应该提取哪个图像以更好地使用缓存,并将该决定“存储”在某处。我将向您展示如何通过存储在文件中来完成。

如果您将逻辑保留在一个构建步骤中会更容易:

steps:
- name: 'gcr.io/cloud-builders/docker'
  entrypoint: 'bash'
  args:
    - '-c'
    - |
      mkdir tmp
      (docker pull gcr.io/$PROJECT_ID/app:$BRANCH_NAME && echo "$BRANCH_NAME" > tmp/base) ||
        echo "master" > tmp/base

      docker pull "us.gcr.io/$PROJECT_ID/app-builder:$(cat tmp/base)" || true
      docker pull "us.gcr.io/$PROJECT_ID/app:$(cat tmp/base)" || true

      docker build \
          --cache-from "gcr.io/$PROJECT_ID/app-builder:$(cat tmp/base)" \
          -t us.gcr.io/$PROJECT_ID/app-builder:$BRANCH_NAME \
          -t us.gcr.io/$PROJECT_ID/app-builder:$COMMIT_SHA \
          -t us.gcr.io/$PROJECT_ID/app-builder:latest \
          --build-arg COMMIT_HASH=$COMMIT_SHA \
          -f config/dockerfiles/app.dockerfile \
          --target builder \
          .

      docker build \
          --cache-from "gcr.io/$PROJECT_ID/app-builder:$COMMIT_SHA" \
          --cache-from "gcr.io/$PROJECT_ID/app:$(cat tmp/base)" \
          -t us.gcr.io/$PROJECT_ID/app:$BRANCH_NAME \
          -t us.gcr.io/$PROJECT_ID/app:$COMMIT_SHA \
          -t us.gcr.io/$PROJECT_ID/app:latest \
          --build-arg COMMIT_HASH=$COMMIT_SHA \
          -f config/dockerfiles/app.dockerfile \
          .
images: [
  'gcr.io/$PROJECT_ID/app-builder:$COMMIT_SHA',
  'gcr.io/$PROJECT_ID/app-builder:$BRANCH_NAME',
  'gcr.io/$PROJECT_ID/app-builder:latest',
  'gcr.io/$PROJECT_ID/app:$COMMIT_SHA',
  'gcr.io/$PROJECT_ID/app:$BRANCH_NAME',
  'gcr.io/$PROJECT_ID/app:latest'
]

脚本在tmp/ 内创建tag 文件,因此Docker 忽略此目录或文件很重要(将其放在.dockerignore 上)。

请注意,我避免在两张图片中使用--cache-from。这是因为在我的实验中,由于构建使用最旧的图像作为缓存,所以缓存失效了。还要注意第一个docker build 命令有一个--target 参数。这告诉 Docker 只在该阶段结束之前构建。

我将默认镜像更改为master,因为它可以保证基础镜像是稳定的,并且不会在与您的分支相差太大的分支中,从而获得更好的性能。在我的示例中,latest 标记是不必要的。


【讨论】:

    猜你喜欢
    • 2020-04-16
    • 2019-03-12
    • 2019-03-09
    • 1970-01-01
    • 2020-03-19
    • 2020-07-13
    • 2022-11-25
    • 1970-01-01
    • 2018-06-06
    相关资源
    最近更新 更多