Speed up your builds with Docker Cache
Publié le 29 février 2016 - 2 min de lecture
When you start with Docker, it seems normal to get inspired by some samples and examples you grabed around the web.
First steps with Docker
Let’s start, for example, with a simple nodejs project. You grab this nice Dockerfile, and, yes, it works great.
FROM mhart/alpine-nodeWORKDIR /src# Copy your code in the docker imageCOPY . /src# Install your project dependenciesRUN npm install# Expose the port 3000EXPOSE 3000# Set the default command to run when a container startsCMD ["npm", "start"]
Building again and again but no gain
Now, you are working on your source code. And each time you want to build your image to test your code, you have to wait…
Step 1 : FROM mhart/alpine-node— -> cdbaa8672a25Step 2 : WORKDIR /src— -> Using cache— -> b45c7e778213Step 3 : COPY . /src— -> efdeb7ccd271Removing intermediate container 8658a7345ce0Step 4 : RUN npm install— -> Running in f48b8e022460Removing intermediate container f48b8e022460Step 5 : EXPOSE 3000---> Running in 60bccf4e876e---> d3591a082b67Removing intermediate container 60bccf4e876eStep 6 : CMD npm start---> Running in 9f130513aef6---> 627434bc0bd3Removing intermediate container 9f130513aef6Successfully built 627434bc0bd3
Each build took over a minute on my MacBook Pro… and 90% of this minute is dedicated to the step 4, the npm install.
Here comes three things to know :
- Docker build your image step by step.
- Each step is dependent to the previous one.
- Each step is cached by Docker
Because my code have changed, Docker use his cache before the step 3. After this, docker rebuild intermediates images from step 3 to step 6.
We can see the “Removing intermediate container” logs : docker don’t use his cache for this steps because it depends on the step 3.
Optimize your Dockerfile to get the best of cache
To get the best of Docker cache :
Think your Dockerfile like layers of images storted by specialization.
- First, i need a node ready image :
- Second, i need a node image which working dir is /src
- Then, i need a node ready image which working dir is /src and listening on port 3000.
- Then, i need a node ready image which working dir is /src and listening on port 3000 and running npm start as default command.
- I need this previous image but with the node dependencies i specified in my package.json
- Last step is the most specified step of this image, i want my current source code on it
Here is it ! An optimized Dockerfile of my project :
FROM mhart/alpine-node:5.6.0WORKDIR /src# Expose the port 3000EXPOSE 3000# Set the default command to run when a container startsCMD ["npm", "start"]# Install app dependenciesCOPY package.json /srcRUN npm install# Copy your code in the docker imageCOPY . /src
Built it again and again after making some changes to our code :
Step 1 : FROM mhart/alpine-node— -> cdbaa8672a25Step 2 : WORKDIR /src— -> Using cache— -> b45c7e778213Step 3 : EXPOSE 3000— -> Using cache— -> 02992be285dbStep 4 : CMD npm start— -> Using cache— -> 4e7f1d140eb1Step 5 : COPY package.json /src— -> Using cache— -> faa22ea65977Step 6 : RUN npm install— -> Using cache— -> ea3b2c32a045Step 7 : COPY . /src— -> 45c61b45bb99Removing intermediate container 871632345f49Successfully built 45c61b45bb99
Rebuilding this image take only 2 seconds now, is far better than over a minute !!!
We can see the “Using cache” logs.
Steps 1 to 4 are always the same in our project, so cache is always used.
The long npm install task at step 6 is only ran if there is a change on copied package.json file on step 5.
The step 7 is the only step where an image is rebuilt based on previous steps when we make a change on our source code.
We hope this post will help you gain time on your future Docker ready projects.
Checkout our website and twitter