From 8a6cfa79a003be51415ac93c89f2ae4899aad3d6 Mon Sep 17 00:00:00 2001 From: Robert Prehn <3952444+prehnRA@users.noreply.github.com> Date: Thu, 10 Jun 2021 16:06:38 -0500 Subject: [PATCH] feat: Speed up docker builds --- .gitlab-ci.yml | 45 ++++++++++++++++++++++----------------- Dockerfile | 4 ++-- script/ci-docker-build | 36 +++++++++++++++++++++++++++++++ script/ci-docker-prebuild | 17 +++++++++++++++ 4 files changed, 80 insertions(+), 22 deletions(-) create mode 100755 script/ci-docker-build create mode 100755 script/ci-docker-prebuild diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 27812d1f..42240103 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -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 diff --git a/Dockerfile b/Dockerfile index 967c78a1..9b21e9c6 100644 --- a/Dockerfile +++ b/Dockerfile @@ -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 diff --git a/script/ci-docker-build b/script/ci-docker-build new file mode 100755 index 00000000..2f4cc228 --- /dev/null +++ b/script/ci-docker-build @@ -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 diff --git a/script/ci-docker-prebuild b/script/ci-docker-prebuild new file mode 100755 index 00000000..19c73c7d --- /dev/null +++ b/script/ci-docker-prebuild @@ -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