Как кэшировать многоэтапную сборку докеров в Google Cloud Builder - PullRequest
0 голосов
/ 09 мая 2018

У меня есть многоэтапная сборка 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? Я думаю, что мой вопрос в основном относится к докеру, но все же.

1 Ответ

0 голосов
/ 23 октября 2018

Образ строителя должен быть собран и помечен отдельно. Вам нужно вытолкнуть этот образ со стадии сборки и использовать его в следующих сборках в качестве кэша. Для этого удобнее назвать этап сборки.

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

Сценарий создает файл tag внутри tmp/, поэтому важно, чтобы Docker игнорировал этот каталог или файл (укажите это .dockerignore).

Обратите внимание, что я избегал использования --cache-from с двумя изображениями. Это потому, что в моих экспериментах я получал аннулирование кэша, потому что сборка использовала самое старое изображение в качестве кэша. Также обратите внимание, что первая команда docker build имеет аргумент --target. Это говорит Docker строить только до конца этого этапа.

Я изменил изображение по умолчанию на master, потому что это гарантирует, что базовое изображение стабильно и не слишком сильно отличается от вашего, что приводит к повышению производительности. Тег latest в моем примере не нужен.


Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...