Is it better to COPY multiple project files in separate layers, or in one go when creating a Docker image?

1.5k views Asked by At

I am creating a Docker container from this .NET Core application that has multiple projects inside the solution, and I wonder if it is better to COPY each project file separately, or in a single line.

Visual Studio generates a Dockerfile that copies each project file on a new line, like this:

WORKDIR /src
COPY Dir1/Dir1.csproj Dir1/
COPY Dir2/Dir2.csproj Dir2/
COPY Dir3/Dir4/Dir4.csproj Dir3/Dir4/
RUN dotnet restore Dir1/Dir1.csproj

However, the Microsoft documentation for creating a .NET application with Docker shows as an "optimization" to use only a single COPY statement, like so:

WORKDIR /src
COPY . .
RUN dotnet restore Dir1/Dir1.csproj

Which is said to, in my understanding of the article, create a larger image, but wouldn't have to COPY all other projects if one project changes.

Interestingly, the Docker documentation mentions to

COPY them individually, rather than all at once. This ensures that each step’s build cache is only invalidated (forcing the step to be re-run) if the specifically required files change.

Which basically contradicts what the Microsoft article says, about the COPY step having to be rerun when one project changes.

I would like to know which option is better, and why, or for what purpose. Or perhaps I misunderstood some of the documentation, then please explain the difference to me.

1

There are 1 answers

4
Efrat Levitan On

IMO the best practice approach is to copy each project as a separated layer, ie a dedicated COPY statement.

use separated layers.

  1. faster build: docker is caching the layers, so if you made a change in one project - next time the image is built docker will only build the changed layer and use cache for the others.
  2. faster deployment: layers can be pulled in parallel
  3. efficient hosting: thanks to docker copy on write mechanism, layers can be shared across images to save space and IO:

Copy-on-write is a strategy of sharing and copying files for maximum efficiency. If a file or directory exists in a lower layer within the image, and another layer (including the writable layer) needs read access to it, it just uses the existing file. The first time another layer needs to modify the file (when building the image or running the container), the file is copied into that layer and modified. This minimizes I/O and the size of each of the subsequent layers

the reason why you see the common COPY . . statement in Dockerfiles is because usually a dockerfile contains a single project, thats a best practice which i would like to recommend for your case too - place a dockerfile in each project and build separated images (on top of a common base image).

if you ought to host all of your projects in a single image, at least copy them as different layers.