How to cache package manager downloads for docker builds?
Use the experimental feature : Docker buildkit (Supported Since docker 18.09, docker-compose 1.25.4)
In your dockerfile
# syntax=docker/dockerfile:experimentalFROM ....# ...... RUN --mount=type=cache,target=/var/composer composer install -n -o --no-dev
Now before building, make sure the env var is exported:
export DOCKER_BUILDKIT=1docker build ....
If you are using docker-compose, make sure to export also COMPOSE_DOCKER_CLI_BUILD
:
export COMPOSE_DOCKER_CLI_BUILD=1 DOCKER_BUILDKIT=1docker-compose build ...
If it does not work with docker-compose, make sure your docker-compose version is above 1.25.4
docker-compose version
I found two ways of dealing with this problem, yet none deal with composer volumes anymore.
Fasten composer download process: Use hirak/prestissimo
composer global require "hirak/prestissimo:^0.3"
💡 With Composer 2.0, the above step is no longer required for faster downloads. In fact, it won't install on Composer 2.0 environments.
Force docker to use a cached composer install.
Docker uses a cache on aRUN
if the added files didn't change. If you only doCOPY . /your-php-app
,docker build
will refresh all the cashes and re-run composer install even if only one unrelated file in the source tree changed.
In order to make docker build to run composer install only install on package changes, one has to addcomposer.json
andcomposer.lock
file before adding the source files. Since one also needs the source files anyway, one has to use different folders for composer install and rsync the content back to the then added folder; furthermore one then has to run the post-install scripts manually.
It should look something like this (untested):WORKDIR /tmp/COPY composer.json composer.lock ./RUN composer install -n -o --no-dev --no-scriptsWORKDIR /your-php-app/ COPY . /your-php-app/RUN rsync -ah /tmp/* /your/php-app/RUN composer run-script post-install-cmd
or combine the two =)
I would consider utilizing the $HOME/.composer/cache/files
directory. This is where composer reads/write to when using composer install.
If you are able to mount it from your host to your container that would work. Also you could just tar it up after each time your run composer install
and then drop that in before you run composer install
the next time.
This is loosely how Travis CI recommends doing this.
Also, consider using the --prefer-dist
flag with your composer install
command.
Info on that can be found here: https://getcomposer.org/doc/03-cli.md#install
--prefer-dist: Reverse of --prefer-source, composer will install from dist if possible. This can speed up installs substantially on build servers and other use cases where you typically do not run updates of the vendors. It is also a way to circumvent problems with git if you do not have a proper setup.
Some references on utilizing the composer cache for you: