feat: Speed up docker builds

This commit is contained in:
Robert Prehn 2021-06-10 16:06:38 -05:00
parent 9fa40ca392
commit 8a6cfa79a0
4 changed files with 80 additions and 22 deletions

View file

@ -15,9 +15,8 @@ variables:
# Test stage. Runs various tests and speculatively builds docker image in
# parallel, in case the build passes.
test:
.test_template: &test_template
stage: test
image: "elixir:1.10.4-alpine"
cache:
paths:
- _build/
@ -26,6 +25,18 @@ test:
- name: postgres:12
script: script/cibuild
test:
<<: *test_template
image: "elixir:1.10.4-alpine"
test_1.11.4:
<<: *test_template
image: "elixir:1.11.4-alpine"
test_1.12.1:
<<: *test_template
image: "elixir:1.12.1-alpine"
build_image_for_commit:
stage: test
image: "docker:20.10"
@ -37,20 +48,11 @@ build_image_for_commit:
- deps/
services:
- name: docker:20.10-dind
before_script:
- apk add git
- script/ci-docker-prebuild
script:
- docker login "https://${CI_REGISTRY}" -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD
- docker pull $CI_REGISTRY_IMAGE:latest || true
# This enables fast parallel builds
- export DOCKER_BUILDKIT=1
- mkdir -p _build/prod
- docker build --cache-from $CI_REGISTRY_IMAGE:latest -t $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA .
# Push the commit SHA tagged version to registry. We will later choose to tag that as stable
# if everything passes.
- docker push $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
# Pull out the built _build/prod directory so we can cache it!
- CONTAINER_HANDLE=`docker create $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA`
- docker cp $CONTAINER_HANDLE:/root/app/_build/prod _build
- docker cp $CONTAINER_HANDLE:/root/app/deps deps
- script/ci-docker-build
# If tests pass, tag the commit and update package versions
deploy_to_tags:
@ -92,13 +94,16 @@ deploy_commit_image_to_tag:
- name: docker:19.03.12-dind
variables:
GIT_STRATEGY: none # this job does not need the project files, only docker
parallel:
matrix:
- IMAGE_TYPE: ["", "-elixir-builder", "-asset-builder"]
script:
- echo "BUILD_VERSION is ${BUILD_VERSION}"
- docker login "https://${CI_REGISTRY}" -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD
# Run the docker pull, but retry if it doesn't work at first because layers may be
# still be loading to storage
- for i in 1 2 3 4 5; do docker pull $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA && break || sleep 15; done
- docker tag $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA $CI_REGISTRY_IMAGE:$BUILD_VERSION
- docker tag $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA $CI_REGISTRY_IMAGE:latest
- docker push $CI_REGISTRY_IMAGE:$BUILD_VERSION
- docker push $CI_REGISTRY_IMAGE:latest
- for i in 1 2 3 4 5; do docker pull $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA$IMAGE_TYPE && break || sleep 15; done
- docker tag $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA$IMAGE_TYPE $CI_REGISTRY_IMAGE:$BUILD_VERSION$IMAGE_TYPE
- docker tag $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA$IMAGE_TYPE $CI_REGISTRY_IMAGE:latest$IMAGE_TYPE
- docker push $CI_REGISTRY_IMAGE:$BUILD_VERSION$IMAGE_TYPE
- docker push $CI_REGISTRY_IMAGE:latest$IMAGE_TYPE

View file

@ -1,4 +1,4 @@
FROM elixir:1.10.4-alpine AS elixir1
FROM elixir:1.10.4-alpine AS elixir-builder
RUN apk add make gcc libc-dev
@ -47,7 +47,7 @@ COPY --from=0 /root/app/ /root/app/
RUN npm install
RUN npm run deploy
FROM elixir1
FROM elixir-builder
ADD ./apps /root/app/apps

36
script/ci-docker-build Executable file
View file

@ -0,0 +1,36 @@
#!/bin/sh
export DOCKER_BUILDKIT=1
docker build \
--target elixir-builder \
--cache-from $CI_REGISTRY_IMAGE:$PARENT_COMMIT-elixir-builder \
--cache-from $CI_REGISTRY_IMAGE:latest-elixir-builder \
--build-arg BUILDKIT_INLINE_CACHE=1 \
-t $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA-elixir-builder .
docker build \
--target asset-builder \
--cache-from $CI_REGISTRY_IMAGE:$PARENT_COMMIT-elixir-builder \
--cache-from $CI_REGISTRY_IMAGE:latest-elixir-builder \
--cache-from $CI_REGISTRY_IMAGE:$PARENT_COMMIT-asset-builder \
--cache-from $CI_REGISTRY_IMAGE:latest-asset-builder \
--build-arg BUILDKIT_INLINE_CACHE=1 \
-t $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA-asset-builder .
docker build \
--target asset-builder \
--cache-from $CI_REGISTRY_IMAGE:$PARENT_COMMIT-elixir-builder \
--cache-from $CI_REGISTRY_IMAGE:latest-elixir-builder \
--cache-from $CI_REGISTRY_IMAGE:$PARENT_COMMIT-asset-builder \
--cache-from $CI_REGISTRY_IMAGE:latest-asset-builder \
--cache-from $CI_REGISTRY_IMAGE:$PARENT_COMMIT \
--cache-from $CI_REGISTRY_IMAGE:latest \
--build-arg BUILDKIT_INLINE_CACHE=1 \
-t $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA .
# Push the commit SHA tagged version to registry. We will later choose to tag that as stable
# if everything passes.
docker push $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA-elixir-builder
docker push $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA-asset-builder
docker push $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA

17
script/ci-docker-prebuild Executable file
View file

@ -0,0 +1,17 @@
#!/bin/sh
PARENT_COMMIT=`git rev-list --parents -n 1 HEAD | cut -d' ' -f2`
docker login "https://${CI_REGISTRY}" -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD
docker pull $CI_REGISTRY_IMAGE:$PARENT_COMMIT-elixir-builder || \
docker pull $CI_REGISTRY_IMAGE:latest-elixir-builder || \
true
docker pull $CI_REGISTRY_IMAGE:$PARENT_COMMIT-asset-builder || \
docker pull $CI_REGISTRY_IMAGE:latest-asset-builder || \
true
docker pull $CI_REGISTRY_IMAGE:$PARENT_COMMIT || \
docker pull $CI_REGISTRY_IMAGE:latest || \
true