We’ve been using multistage docker builds to help reduce the time it takes to build our apps. This works great locally and on some other CI/CD services we’ve tested, but we haven’t been able to get --target
and --cache-from
to work as we’d expect it with Codefresh when using a build step.
Our workflow is to try and pull an image of a previously built intermediate stage, and then use that image for the docker layer cache using --cache-from while we target the same stage to be built.
docker pull ${AWS_ECR_ACCOUNT_URL}/${PROJECT_REPONAME}:cf-build-pip || true
docker pull ${AWS_ECR_ACCOUNT_URL}/${PROJECT_REPONAME}:cf-build-pybase || true
docker pull ${AWS_ECR_ACCOUNT_URL}/${PROJECT_REPONAME}:latest || true
docker build -t ${PROJECT_REPONAME}:cf-build-pip -f compose/production/django/Dockerfile \
--target pip-install \
--cache-from ${AWS_ECR_ACCOUNT_URL}/${PROJECT_REPONAME}:cf-build-pip
docker build -t ${PROJECT_REPONAME}:cf-build-pybase -f compose/production/django/Dockerfile \
--target py-base \
--cache-from ${PROJECT_REPONAME}:cf-build-pip \
--cache-from ${AWS_ECR_ACCOUNT_URL}/${PROJECT_REPONAME}:cf-build-pybase
docker build -t ${PROJECT_REPONAME}:latest -f compose/production/django/Dockerfile \
--target py-app \
--cache-from ${PROJECT_REPONAME}:cf-build-pip \
--cache-from ${PROJECT_REPONAME}:cf-build-pybase \
--cache-from ${AWS_ECR_ACCOUNT_URL}/${PROJECT_REPONAME}:latest
#
# More logic to tag/push cf-build-pip, cf-build-pybase and latest to ECR
#
The above is a simplified version of the process. Since we’re using multistage builds, the intermediate stages are discarded after a build completes and aren’t available in the layer cache.
The first build on a new pull request also has no existing local layer cache on CF, and it would be nice to prepopulate with something that’s likely to have some level of shared history.
Any thoughts on how we can make the above work?
Here’s one of the variations we’ve tried in Codefresh:
steps:
load_cached_images:
description: Filling docker cache
image: codefresh/cf-docker-builder:v14
commands:
- docker pull r.cfcr.io/account/cfcr/projectname:cfcr-pip || true
- docker pull r.cfcr.io/account/cfcr/projectname:cfcr-pybase || true
- docker pull r.cfcr.io/account/cfcr/projectname:latest || true
pip_image:
type: build
description: installing pip requirements
target: pip-install
dockerfile: compose/production/django/Dockerfile
image_name: cfcr/projectname
tag: cfcr-pip
build_arguments:
- --cache-from=r.cfcr.io/account/cfcr/projectname:cfcr-pip
stage: build
base_image:
type: build
description: creating base image
target: py-base
dockerfile: compose/production/django/Dockerfile
image_name: cfcr/projectname
tag: cfcr-pybase
build_arguments:
- --cache-from=cfcr/projectname:cfcr-pip
- --cache-from=r.cfcr.io/account/cfcr/projectname:cfcr-pybase
stage: build
final_image:
type: build
description: Building the final image
target: py-app
dockerfile: compose/production/django/Dockerfile
image_name: cfcr/projectname
build_arguments:
- --cache-from=cfcr/projectname:cfcr-pip
- --cache-from=cfcr/projectname:cfcr-pybase
- --cache-from=r.cfcr.io/account/cfcr/projectname:latest
Thanks for the help!