How To Execute Multiple Commands Per Dockerfile
April 04, 2021
I dabbled into .NET recently and after finishing the project I ended up with 2 microservices which were .NET projects under the same solution. It turns out that when dockerizing the microservices their build instructions are identical. The only difference is the command which needs to be invoked in order to start the microservice.
Below you can see a sample Dockerfile for a .NET application with multiple microservices:
FROM mcr.microsoft.com/dotnet/sdk:5.0 AS build
WORKDIR /app
# install necessary packages
COPY *.sln .
COPY MicroserviceA/*.csproj ./MicroserviceA/
COPY MicroserviceB/*.csproj ./MicroserviceB/
COPY Common/*.csproj ./Common/
RUN dotnet restore ./MySolution.sln
# build executables of all projects/microservices
COPY . ./
RUN dotnet publish -c Release -o out
# Copy executables
FROM mcr.microsoft.com/dotnet/aspnet:5.0
WORKDIR /app
COPY --from=build /app/out .
CMD ["dotnet", "MicroserviceA.dll"]
As you can see the CMD
directive invokes MicroserviceA
, but what about MicroserviceB
? Because all previous stages are the same for MicroserviceB
itβs redundant to have another Dockerfile dedicated just to MicroserviceB
.
Luckily, the CMD
specified in the Dockerfile is only a default. This means that it can be overridden. Same logic goes for ENTRYPOINT
directive.
This means that executing docker run myimage
on the image built by the Dockerfile above will start MicroserviceA
by default. However, executing docker run myimage dotnet MicroserviceB.dll
will override the default CMD
and invoke MicroserviceB
instead. As a result the Dockerfile can be re-used for any microservice project in the .NET app.
An even cleaner solution is to use docker-compose
command
option in order to specify each microservice:
version: "3.9"
services:
microservicea:
image: myimage/microservicea
build: .
command: ["dotnet", "MicroserviceA.dll"]
microserviceb:
image: myimage/microserviceb
build: .
command: ["dotnet", "MicroserviceB.dll"]
I hope the post shed some light on overriding Dockerfile default CMD
and on organizing your .NET apps!