Search code examples
dockerdocker-composedockerfilecontainersdevops

Multiple queries regarding Docker Multi Stage Build process


I am new to Docker and got confused in couple of things. I have few queries as well. Please find them below. I would be happy if these queries got resolved.

Question 1: In multi-stage builds, how does docker identify the artifacts of a stage? Because I saw in many articles, people say COPY --from=0 src dest will copy the artifacts from the last build stage. I mean where have we explicitly defined that you need to copy the artifacts from this folder? What defines the build output/build artifact of a stage?

# Stage 1
FROM mcr.microsoft.com/dotnet/core/sdk:3.1 AS build
WORKDIR /build
COPY . .
RUN dotnet restore
RUN dotnet publish -c Release -o /app

# Stage 2
FROM mcr.microsoft.com/dotnet/core/aspnet:3.1 AS final
WORKDIR /app
COPY --from=build /app .
ENTRYPOINT ["dotnet", "Core3Api.dll"]
  • Q2 - Does COPY --from=build src dest copy files from a previous build or the image?
  • Q3 - Normally copy has two parameters, one is the source and the other is a destination. Above we have three parameters, --from=build src dest. How does this copy works?
  • Q4 - Do we need to set WORKDIR in every build stage? Because I think every build stage executes in a new isolated context? OR it uses the same context?
  • Q5 - Where does Docker stores previous build's image when it moves to next stage?

All my questions are interrelated, that's why I clubbed all into one.


Solution

  • Docker builds images; each image consists of a filesystem plus some additional metadata. Within the context of a multi-stage build (Q5) each FROM line starts a new image build, and the result of these image builds are totally normal images; you can see them (probably with a <none> name) in docker images output. Similarly, because each build stage stars FROM the context of some previous image, (Q4) you do need to repeat WORKDIR in every stage where it matters (but since each stage is in an isolated build context, different stages don't necessarily need the same working directory).

    The Dockerfile COPY command (Q3) can take options, in much the same way as you can cp -r from to in a normal shell. The --from option (Q2) names an image; it can be an earlier build stage FROM ... AS name in the same Dockerfile, or it can be an arbitrary other image. (Q1) It copies from whatever the filesystem result of the image build is.

    FROM ... AS build
    WORKDIR /build
    RUN ...
    COPY ...
    # An image is created that's effectively a snapshot here
    
    FROM ...
    WORKDIR /app
    COPY src dest                       # from the build context
    COPY --from=build /build/dir dest2  # from the "snapshot" point
    COPY --from=0 /build/dir dest3      # from the first image in this Dockerfile
    COPY --from=busybox:latest /bin/busybox dest4  # from another image