How to start multiple microservices after docker build finished for .net projects?

Viewed 83

I have a .net solution which has 2 projects, and each project is a microservice (a server). I have a dockerfile which first installs all the dependencies which are used by both projects. Then I publish the solution:

    FROM mcr.microsoft.com/dotnet/sdk:5.0 AS build
    WORKDIR /app
    
    # Copy csproj and restore as distinct layers
    COPY *.sln .
    COPY Server/*.csproj ./Server/
    COPY JobRunner/*.csproj ./JobRunner/
    RUN dotnet restore ./MySolution.sln
    
    # Copy everything else and build
    COPY . ./
    RUN dotnet publish -c Release -o out
    
    # Build runtime image
    FROM mcr.microsoft.com/dotnet/aspnet:5.0
    WORKDIR /app
    COPY --from=build /app/out .
    ENTRYPOINT ["dotnet", "Server.dll"]

When the solution is published, 2 executables are available: Server.dll and JobRunner.dll. However, I can only start only one of them in Dockerfile.

This seems to be wasteful because restoring the solution is a common step for both Server and JobRunner project. In addition this line RUN dotnet publish -c Release -o out produces both an executable for Server and JobRunner. I could write a separate Dockerfile for each project but this seems redundant as 99% of the build steps for each project is identical.

Is there a way to somehow start 2 executables from a single file without using a script (I don't want that both services will be started in a single container)? The closest I've found is the --target option in docker build but it probably won't work because I'd need multiple entrypoints.

1 Answers

In your Dockerfile, change ENTRYPOINT to CMD in the very last line.

Once you do this, you can override the command by just providing an alternate command after the image name in the docker run command:

docker run ... my-image \
  dotnet JobRunner.dll

(In principle you can do this without changing the Dockerfile, but the docker run construction is awkward, and there's no particular benefit to using ENTRYPOINT here. If you're using Docker Compose, you can override either entrypoint: or command: on a container-by-container basis.)

Related