Last active
September 14, 2021 23:53
-
-
Save adrianord/5c51bd0f087cca2818ac15b076a72727 to your computer and use it in GitHub Desktop.
Generic DotNet Dockerfile using BuildKit `RUN --mount` directive to keep csproj structure.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# This is an example of what you might have in your .dockerignore. Some items can be omitted like `!/test/**` or added | |
# like `**/node_modules` if you have a node/frontend project. | |
* | |
!/*.sln | |
!/nuget.config | |
!/src/** | |
**/bin | |
**/obj |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#syntax=docker/dockerfile:1.2 | |
####################################### | |
## This Dockerfile requires BuildKit ## | |
####################################### | |
## Build Stage | |
FROM mcr.microsoft.com/dotnet/sdk:5.0 as build | |
## Build stage arguments | |
ARG CONFIG_PROFILE=Release | |
ARG PROJECT_DIR | |
ARG PROJECT_NAME | |
ENV PROJECT=${PROJECT_DIR}/${PROJECT_NAME}.csproj | |
WORKDIR /app | |
COPY nuget.config* ./ | |
COPY *.sln ./ | |
## Copy .csproj files into the correct file structure | |
SHELL ["/bin/bash", "-O", "globstar", "-c"] | |
RUN --mount=target=docker_build_context \ | |
cd docker_build_context;\ | |
cp **/*.csproj ../ --parents; | |
RUN rm -rf docker_build_context | |
SHELL ["/bin/sh", "-c"] | |
## Restore project | |
RUN dotnet restore ${PROJECT} | |
## Copy all files if restore succeeds | |
COPY . ./ | |
## Publish project without restoring | |
RUN dotnet publish --no-restore -c ${CONFIG_PROFILE} -o out ${PROJECT} | |
## New stage used to reduce the size of the final image --- | |
FROM mcr.microsoft.com/dotnet/aspnet:5.0 | |
## Final stage arguments | |
ARG PROJECT_NAME | |
WORKDIR /app | |
COPY --from=build /app/out . | |
ENV ASPNETCORE_URLS=http://+:80 | |
## Create a symlink so we can use exec form entrypoint | |
RUN ln -s ${PROJECT_NAME}.dll Entrypoint.dll | |
ENTRYPOINT [ "dotnet", "Entrypoint.dll" ] |
It blew my mind that Docker build doesn't support globstar. I ended up using a combination of find
and cpio
.
find . -name *.csproj | cpio -pdm [wherever]
Do you think there's any advantage to the BuildKit + mount approach?
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
After attempting to use the old version of this Dockerfile (the non-buildkit version) in production, I hit some issues. The regex for the
.sln
file wasn't working great and I had a misunderstanding about how Docker handles "globstar", in that it does not at all.This caused an issue when the projects were not a flat structure on the filesystem.
So I decided to go down the rabbit hole of BuildKit and the new
RUN --mount
directive and produced a much more reliable Dockerfile. Along the way I also discovered you could symlink the assembly that needed to run so that you can always use EXEC form which allows the dotnet process to be PID 1 in the container. This helps with shutdown times and signal processing since SHELL form work eat the signals and not send it to the dotnet process.It still takes advantage of all that layer caching goodness as well.