Turbocharging Docker build

Building a Docker image can take a bit of time depending on what you have to do. Specially when you have to do something like DNU Restore, DotNet Restore, NPM Install or Nuget Restore builds can become slow because packages might have to be downloaded from the internet.

Take the following Dockerfile which does a DNU Restore.

FROM microsoft/aspnet:1.0.0-rc1-update1-coreclr

MAINTAINER Maurice de Beijer <maurice.de.beijer@gmail.com>

COPY . ./app

WORKDIR ./app
RUN dnu restore

EXPOSE 5000

CMD ["--server.urls", "http://*:5000"]
ENTRYPOINT ["dnx", "web"]

Running the Docker build multiple times without any changes is quite fast. To time it I am using the command:

time docker build -t dotned .
This reports it takes between 1.3 and 1.5 seconds on my aging laptop. Not too bad really.
 
Unfortunately this changes quite a bit when I make a change to the source code of the application. Just adding some non significant whitespace slows the build from 1.5 seconds to 58 seconds which is quite a bit of time to wait before being able to run the container.
 
The reason for this slowdown is that Docker has to do a lot more work. When you build a Docker container for the second time Docker creates a layer for each command executed. And each layer is cached to be reused. But if a cached layer depends on another layer that is changed it can’t be reused anymore. This means that once the source code is changes the result of the COPY command is a different layer and the DNU Restore layer has to be recreated which takes a long time.
 
A much faster approach is to copy just the project.json file so we can do a DNU Restore before copying the rest of the source code. With this approach Docker build are down to quite a reasonable 3.3 seconds  and only take a long time when there is a change to the project.json file. Something that should not happen very often. The functionally identical but much faster Dockerfile looks like this:
 
FROM microsoft/aspnet:1.0.0-rc1-update1-coreclr

MAINTAINER Maurice de Beijer <maurice.de.beijer@gmail.com>

COPY ./project.json ./app/

WORKDIR ./app
RUN dnu restore

COPY . ./app

EXPOSE 5000

CMD ["--server.urls", "http://*:5000"]
ENTRYPOINT ["dnx", "web"]

Enjoy Smile
 
 

One thought on “Turbocharging Docker build

Leave a Reply

Your email address will not be published. Required fields are marked *