Edits
2016-09-12 Edited to prevent caching of builds in pull requests.
2017-07-07 Edited to point to exact git commit b/c we don't use Travis for Snippets Service anymore.
I blogged before about building Docker images on Travis and suggested uploading images after successful test runs to Docker Hub and use them as Cache after downloading them in next Travis runs.
Travis upgraded recently to Docker version 1.12 (from 1.9) and since version 1.10 Docker features Content Addressability for layers. This change breaks caching and we need to implement a workaround using Travis cache.
Changes need to be made in .travis.yml
:
Enable cache
cache:
directories:
- /home/travis/docker/
Start by requesting Travis to cache /home/travis/docker
directory.
Load Docker images previously cached
before_install:
- if [ -f ${DOCKER_CACHE_FILE} ]; then gunzip -c ${DOCKER_CACHE_FILE} | docker load; fi
This checks that ${DOCKER_CACHE_FILE} exists and then loads it in Docker while gunzip-ing it. For convenience and smaller lines I did setup ${DOCKER_CACHE_FILE} as environment variable
env:
global:
- DOCKER_CACHE_FILE=/home/travis/docker/cache.tar.gz
Save image to cache
After building the image and running the tests it's time to save the new Docker image to Travis cache.
I chose to save only when I'm building the master branch but all branches and PRs will still get the cache as Travis will make the cache directory available to all builds.
script:
# Tests go here
- if [[ ${TRAVIS_BRANCH} == "master" ]] && [[ ${TRAVIS_PULL_REQUEST} == "false" ]]; then mkdir -p $(dirname ${DOCKER_CACHE_FILE}) ; docker save $(docker history -q ${DOCKER_REPOSITORY}:${TRAVIS_COMMIT} | grep -v '<missing>') | gzip > ${DOCKER_CACHE_FILE}; fi
Note that we don't just docker save
the resulting image. Instead we need to
save all the intermediate layers explicitly. We get all the layers using docker
history
and we grep out all the <missing>
images.
It's important that docker save
happens in script
step because right after
this step Travis will save the contents of the cached directory.
That's all!
Note that Docker saving and loading, as well as Travis uploading and downloading of cache from S3 costs time. It may be faster to rebuilt your Docker image instead of caching it.
See also:
-
Wikipedia article on Content-addressable storage
You can find a real life example of .travis.yml
in the
Mozilla Snippets
project.