Making docker-in-docker builds x2 faster using Docker “cache-from” option
There are many reasons for not using docker-in-docker (DIND) in a CI setup. The biggest reason against using DIND in CI is: you cannot use images from the host machine, i.e. every time you make a build, Docker will download all layers of your image.
If you are curious why not just mount
/var/run/docker.sock
as recommended in Jérôme Petazzoni article, this comment summarises my reasons (concurrency being the main reason).
The good news is that Docker v1.13 added a capability to specify images used as a cache source during the build step. These images do not need to have a local parent chain and can be pulled from other registries.
To leverage this feature, you need to add --cache-from
option to your build script, i.e. if earlier your CI manifest was building an image as such:
docker build --tag $CONTAINER_IMAGE:$CI_BUILD_REF .
Then to leverage cache reuse you need to change it to:
docker build\
--cache-from $CONTAINER_IMAGE:latest\
--tag $CONTAINER_IMAGE:$CI_BUILD_REF\
--tag $CONTAINER_IMAGE:latest\
.
and ensure that you push $CONTAINER_IMAGE:latest
image after successful builds.
Using a different storage driver
While on the subject, in addition to using --cache-from
, evaluate an alternative storage driver. By default, docker:dind
uses vfs storage driver. vfs storage driver is designed to be used only for debugging. vfs storage driver is slow to commit
and to run
.
Therefore, consider using overlay
(or overlay2
).
DIND storage driver can be specified using Custom daemon flags (also see Start a daemon instance note about picking the storage driver).
GitLab CI
If you (like me) are using GitLab enterprise edition, feel free to have a look at my .gitlab-ci.yml
configuration for the above changes. This configuration leverages --cache-from
Docker build option and overlay2 storage driver.
Furthermore, this configuration demonstrates how to use semantic-release-gitlab (a GitLab equivalent of semantic-release).
How many times faster, really?
Naturally, the build time improvements depend on what part of the CI job is pulling the images.
With Node.js projects, I have observed CI job improvements upwards of x3 times (from avg. 20 minutes to 7 minutes, for build, test, release).