Multi-stage building with Docker

Docker supports a feature, where you can create multiple containers with a single dockerfile and at the same time share the contents between the containers. This feature gives you the possibility of having multi-stage builds and opens one significant spot for creating repeatable builds.

The idea behind it is simple, you can have multiple FROM statements inside the same Dockerfile. Each FROM statement can use different images, therefore defines it’s own dependencies and allows you to connect the containers from one base to the other by using COPY --from=0or COPY --from=previous-stage.

Docker stages

Each stage could be responsible for doing one thing only(don’t forget the unix philosphy), e.g. run unit tests.

Multi-Stage Builds in dotnet core

Here is a simplified example of a multi-stage Dockerfile which is used to build, test a dotnet core 2.0 application, plus a ready to run container.

# 1st stage
FROM microsoft/dotnet:2-sdk-jessie as builder

RUN mkdir /app
COPY . /app
RUN dotnet restore \
    && dotnet build -c Release /app/src/MyProject \
    && dotnet build -c Release /app/test/Tests.MyProject \
    && dotnet test /app/test/Tests.MyProject \
    && dotnet publish -c Release -o /app/bin/MyProject /app/src/MyProject

# 2nd stage
FROM microsoft/dotnet:2.0.0-runtime-jessie

RUN mkdir -p /opt/app/bin
COPY --from=builder /app/bin /opt/app/bin
COPY --from=builder /app/ /opt/app

ENTRYPOINT ["/opt/app/"]

Why use it

The benefits are very clear:

There is one minor issue, you need to remove a dangling image at the end of the build process ;)


The ability to repeat one build with the same consistency is crucial in today’s constantly changing dependencies. Docker allows you to maintain the same environment, even by making sure your build steps are the same. If you are already using docker it’s dead simple to use multi-stage builds. If you are new to docker you will still grasp the concept quickly.


NOTE: originally posted on medium