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
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.
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
RUN mkdir -p /opt/app/bin
COPY --from=builder /app/bin /opt/app/bin
COPY --from=builder /app/startup.sh /opt/app
Why use it
The benefits are very clear:
- you create builds that are CI/CD independent, i.e. you don’t care if you run a build with TeamCity or Gitlab or Jenkins.
- you have one host dependency, i.e. docker
- you commit in your repository the steps of your build, which means that you can have different steps on different branches (it might not work very well in TeamCity, but still it’s possible).
- consistent build environment, i.e. what is inside docker does not change, they are repeatable and consistent.
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 https://medium.com/@ipinak/multi-stage-building-with-docker-37cd10a44e3c