dockerdockerfile

What is --from, as used in COPY command in Dockerfile?


I am seeing a dockerfile whose code is given below:

FROM mcr.microsoft.com/dotnet/aspnet:5.0-buster-slim AS base
WORKDIR /app
EXPOSE 80
EXPOSE 443

FROM mcr.microsoft.com/dotnet/sdk:5.0-buster-slim AS build
WORKDIR /src
COPY ["FirstDockerApp/FirstDockerApp.csproj", "FirstDockerApp/"]
RUN dotnet restore "FirstDockerApp/FirstDockerApp.csproj"
COPY . .
WORKDIR "/src/FirstDockerApp"
RUN dotnet build "FirstDockerApp.csproj" -c Release -o /app/build

FROM build AS publish
RUN dotnet publish "FirstDockerApp.csproj" -c Release -o /app/publish

FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "FirstDockerApp.dll"]

On the 2nd last line there is COPY --from=publish /app/publish .. I don't understand why --from is used and what purpose it solves. Can you please help me to understand it?


Solution

  • This is a multi-stage build. This is used to keep the running docker container small while still be able to build/compile things needing a lot of dependencies.

    For example a go application could be built by using:

    FROM golang:1.7.3 AS builder
    WORKDIR /go/src/github.com/alexellis/href-counter/
    RUN go get -d -v golang.org/x/net/html  
    COPY app.go .
    RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o app .
    
    FROM alpine:latest  
    RUN apk --no-cache add ca-certificates
    WORKDIR /root/
    COPY --from=builder /go/src/github.com/alexellis/href-counter/app .
    CMD ["./app"]  
    

    So in the first part we need a complete go environment to compile our software. Notice the name for the first part and the alias builder

    FROM golang:1.7.3 AS builder
    

    In the second part beginning from the second FROM we only need the compiled app and no other go dependencies anymore. So we can change the base image to using a much smaller alpine Linux. But the compiled files are still in our builder image and not part of the image we want to start. So we need to copy files from the builder image via

    COPY --from=builder
    

    You can have as many stages as you want. The last one is the one defining the image which will be the template for the docker container.

    You can read more about it in the official documentation: https://docs.docker.com/develop/develop-images/multistage-build/