如何在google cloud builder中缓存多阶段docker build

disho6za  于 2023-01-29  发布在  Docker
关注(0)|答案(2)|浏览(214)

例如,我有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中我有/vendor,我用dep构造了它,我想缓存那些依赖项。我怎样才能在google云平台上最容易地做到这一点呢?我想我的问题主要是针对docker的,但仍然如此。

cbeh67ev

cbeh67ev1#

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

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,因为它保证了基本映像是稳定的,并且不会位于与您的映像差异太大的分支中,这会带来更好的性能。

kb5ga3dv

kb5ga3dv2#

想在“菲利普”的回答上加一句。
Google cloud实际上在/workspace目录中运行你的构建步骤,在每一个构建步骤中,这个卷都会被再次挂载,这意味着其中存在的任何文件都可以在接下来的构建步骤中访问。
因此,您不需要创建一个tmp文件,也不需要在一个步骤中完成所有操作(如果您愿意的话)。
另一个注意事项是,如果您的构建步骤很长并且需要更复杂,我建议您使用script键而不是entrypoint-c
记住传递所有必需的变量(包括PROJECT_IDBRANCH_NAME等现成的替换

- name: gcr.io/cloud-builders/docker
    env:
      - 'PROJECT_ID=$PROJECT_ID'
    script: |
            #!bin/bash
            <your script>

或者,您可以将shell脚本直接提供给入口点参数

- name: gcr.io/cloud-builders/docker
    env:
      - 'PROJECT_ID=$PROJECT_ID'
    entrypoint: /my_script.sh

相关问题