I cache gems in a tar file in the tmp directory of the application. Then I copy the gems to the layer using the ADD command before installing the package. From my Dockerfile.yml :
WORKDIR /home/app
Make sure you send the gem cache to your docker machine. My gemcache is 118 MB, but since I create locally, it is quickly copied. My .dockerignore :
tmp !tmp/gemcache.tar.bz2
You need to cache gems from the embedded image, but initially you may not have the image. Create an empty cache like this (I have this in a rake task):
task :clear_cache do sh "tar -jcf tmp/gemcache.tar.bz2 -T /dev/null" end
After creating the image, copy the gems into the cache. My image is tagged app . I am creating a docker container from an image, copy /var/lib/gems/2.2.0 to my gemcache using the docker cp , and then delete the container. Here is my task:
task :cache_gems do id = `docker create app`.strip begin sh "docker cp #{id}:/var/lib/gems/2.2.0/ - | bzip2 > tmp/gemcache.tar.bz2" ensure sh "docker rm -v #{id}" end end
The next time you build the image, gemcache is copied to the layer before calling bundle install . This takes some time, but it is faster than bundle install from scratch.
Building after that is even faster because docker loaded the ADD tmp/gemcache.tar.bz2 /var/lib/gems/ layer ADD tmp/gemcache.tar.bz2 /var/lib/gems/ . If there are any changes to Gemfile.lock , only those changes will be created.
There is no reason to restore the gem cache every time you change Gemfile.lock . When there are enough differences between the cache and the Gemfile.lock tag that bundle install is slow, you can restore the cache. When I want to rebuild the cache, this is a simple rake cache_gems .
source share