Dockerizing aspnetcore-react template fails - c#

Recently I've created an aspnetcore-2.2 project from a react template, which, as i noticed, doesn't have docker support out of the box.
So I added dockerfile which was generated by VS'17:
FROM microsoft/dotnet:2.2-aspnetcore-runtime AS base
WORKDIR /app
EXPOSE 80
EXPOSE 443
FROM microsoft/dotnet:2.2-sdk AS build
COPY ["SpaProj.WebUI/SpaProj.WebUI.csproj", "SpaProj.WebUI/"]
COPY ["SpaProj.Application/SpaProj.Application.csproj", "SpaProj.Application/"]
COPY ["SpaProj.Domain/SpaProj.Domain.csproj", "SpaProj.Domain/"]
COPY ["SpaProj.Persistence/SpaProj.Persistence.csproj", "SpaProj.Persistence/"]
RUN dotnet restore "SpaProj.WebUI/SpaProj.WebUI.csproj"
COPY . .
WORKDIR "/src/SpaProj.WebUI"
RUN dotnet build "SpaProj.WebUI.csproj" -c Release -o
FROM build AS publish
RUN dotnet publish "SpaProj.WebUI.csproj" -c Release -o /app
FROM base AS final
WORKDIR /app
COPY --from=publish /app .
ENTRYPOINT ["dotnet", "SpaProj.WebUI.dll"]
As far as my research goes, the latest dotnet images don't have nodejs pre-installed so the outcome was a foregone conclusion:
System.AggregateException: One or more errors occurred. (One or more errors occurred. (Failed to start 'npm'. To resolve this:.
[1] Ensure that 'npm' is installed and can be found in one of the PATH directories.
Current PATH enviroment variable is: /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
Make sure the executable is in one of those directories, or update your PATH.
[2] See the InnerException for further details of the cause.)) ---> System.AggregateException: One or more errors occurred. (Failed to start 'npm'. To resolve this:.
And so on.
After that, I was browsing web for like two complete days to resolve the issue, and after some research added few lines (which, as i thought, would help me to install/launch nodejs) into my dockerfile:
FROM microsoft/dotnet:2.2-aspnetcore-runtime AS Base
WORKDIR /app
EXPOSE 80 443
FROM microsoft/dotnet:2.2-sdk AS build
# install node and npm
ENV NODE_VERSION 10.16.0
ENV NODE_DOWNLOAD_SHA 2e2cddf805112bd0b5769290bf2d1bc4bdd55ee44327e826fa94c459835a9d9a
ENV NODE_DOWNLOAD_URL https://nodejs.org/dist/v$NODE_VERSION/node-v$NODE_VERSION-linux-x64.tar.gz
RUN wget "$NODE_DOWNLOAD_URL" -O nodejs.tar.gz \
&& echo "$NODE_DOWNLOAD_SHA nodejs.tar.gz" | sha256sum -c - \
&& tar -xzf "nodejs.tar.gz" -C /usr/local --strip-components=1 \
&& rm nodejs.tar.gz \
&& ln -s /usr/local/bin/node /usr/local/bin/nodejs
RUN curl -sL https://deb.nodesource.com/setup_10.x | bash -
RUN apt-get install -y nodejs
# install npm packages first, this is slow so we want to minimise the number of un-cached runs
WORKDIR /src/SpaProj.WebUI/ClientApp/
COPY SpaProj.WebUI/ClientApp/package.json .
COPY SpaProj.WebUI/ClientApp/package-lock.json .
RUN npm install
RUN npm audit fix
# restore dotnet before build to allow it sit to cache
WORKDIR /
COPY ["SpaProj.Application/SpaProj.Application.csproj", "src/SpaProj.Application/"]
COPY ["SpaProj.Domain/SpaProj.Domain.csproj", "src/SpaProj.Domain/"]
COPY ["SpaProj.Persistence/SpaProj.Persistence.csproj", "src/SpaProj.Persistence/"]
COPY ["SpaProj.WebUI/SpaProj.WebUI.csproj", "src/SpaProj.WebUI/"]
RUN dotnet restore src/SpaProj.WebUI/SpaProj.WebUI.csproj
# copy source files and build
COPY . /src
RUN dotnet build /src/SpaProj.WebUI/SpaProj.WebUI.csproj --no-restore -c Release
RUN dotnet publish /src/SpaProj.WebUI/SpaProj.WebUI.csproj --no-restore -c Release -o /app
# Copy compiled app to runtime container
FROM base AS final
COPY --from=build /app .
CMD ["dotnet", "SpaProj.WebUI.dll"]
But it didnt help at all.
I also tried multistage build to gather dependencies from node image like this:
FROM 10.16.1-jessie as node-build
WORKDIR /src
COPY SpaProj.WebUI/ClientApp .
RUN npm install
RUN npm run build
The app was still throwing the same exception.
Did anyone had the same issue? Is there another was to dockerize this kind of app?

Related

Docker build not finding nuget package from local directory

I have a nuget package stored on my local filesystem at C:\Temp. When I add the nuget package to my Visual Studio Solution everything builds as expected. However when I run my docker build command, I receive this error:
MyProject depends on NugetExample.DLL (>= 0.0.4) but NugetExample.DLL 0.0.4 was not found.
Heres a copy of my Dockerfile
FROM mcr.microsoft.com/dotnet/sdk:6.0 as build
WORKDIR /build
EXPOSE 80
EXPOSE 443
EXPOSE 3000
COPY . .
# Restore/build...
# Use debug publish when you need to debug the service running in docker
RUN dotnet publish src/app/MyProject.csproj -c Debug -o /app
# Stage 2
FROM mcr.microsoft.com/dotnet/aspnet:6.0
WORKDIR /app
COPY --from=build /app .
RUN sed -i -e "s|^MinProtocol = .*|MinProtocol = TLSv1.0|g" "/etc/ssl/openssl.cnf"
ENTRYPOINT ["dotnet", "MyProject.dll"]
Is there a way to get docker to find my nuget package stored on my local filesystem?
To pull a NuGet from your local filesystem it needs to be in your Docker build context: https://docs.docker.com/build/building/context/
Alternatively, you can use the new dotnet publish support for making a container image (https://learn.microsoft.com/en-us/dotnet/core/docker/publish-as-container) which does a local build and then copies it into a container image for you. One caveat for your use, to get maintain the effect of:
RUN sed -i -e "s|^MinProtocol = .*|MinProtocol = TLSv1.0|g" "/etc/ssl/openssl.cnf"
You would need to create a base image based on your current stage 2 and then configure publish to use it with ContainerBaseImage

"The type initializer for 'SkiaSharp.SKAbstractManagedWStream' threw an exception." occuring if QuestPDF library published in Docker container

I am trying to use the QuestPDF library with docker container.
If i try to send a request via Postman, the following exception was occured:
"The type initializer for 'SkiaSharp.SKAbstractManagedWStream' threw an exception."
This is my current Dockerfile
FROM mcr.microsoft.com/dotnet/sdk:6.0-focal as build
WORKDIR /src
RUN apt-get update && apt-get install libfontconfig1 -y
COPY . .
RUN dotnet restore "./DataExportService.csproj"
RUN dotnet publish "./DataExportService.csproj" -c Release -o /app --no-restore
FROM mcr.microsoft.com/dotnet/aspnet:6.0-focal
WORKDIR /app
COPY --from=build /app ./
EXPOSE 5000
ENTRYPOINT ["dotnet", "DataExportService.dll"]
Also i tried to add all needed nuget packages.
VS Solution Explorer
Is it possible to suppress this error and make the container work correctly? I have no idea. Thanks.
I managed to solve the problem myself. Below you can find the updated Dockerfile.
FROM mcr.microsoft.com/dotnet/aspnet:6.0-focal AS base
WORKDIR /app
RUN apt-get update && apt-get install -y ttf-mscorefonts-installer fontconfig libc6 libc6-dev libgtk2.0-0 libnss3 libatk-bridge2.0-0 libx11-xcb1 libxcb-dri3-0 libdrm-common libgbm1 libasound2 libappindicator3-1 libxrender1 libfontconfig1 libxshmfence1
RUN chmod 777 .
FROM mcr.microsoft.com/dotnet/sdk:6.0-focal AS build
WORKDIR /src
COPY ["DataExportService.csproj", "DataExportService/"]
RUN dotnet restore "DataExportService/DataExportService.csproj"
WORKDIR "/src/DataExportService"
COPY . .
RUN dotnet build "DataExportService.csproj" -c Release -o /app/build
FROM build AS publish
RUN dotnet publish "DataExportService.csproj" -c Release -o /app/publish
FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "DataExportService.dll"]
Additional info:
Also you need to specify a supported font in the document
page.DefaultTextStyle(x => x.FontFamily(Fonts.Arial));

System.DllNotFoundException: Unable to load shared library 'cvextern' or one of its dependencies. (libcvextern.so) Emgu.CV

Any idea how to solve this issue?
I'm trying to deploy my project in an environment in Elastic Beanstalk AWS, Platform: Docker running on 64bit Amazon Linux/2.16.8
When I run the project locally in a windows machine, it works properly, bu in server I get this error:
System.TypeInitializationException: The type initializer for 'Emgu.CV.CvInvoke' threw an exception.
---> System.DllNotFoundException: Unable to load shared library 'cvextern' or one of its dependencies. In order to help diagnose loading problems, consider setting the LD_DEBUG environment variable: libcvextern: cannot open shared object file: No such file or directory
I already tried copying files directly in the project with "Copy always" property, but not luck.
This is my docker file:
#See https://aka.ms/containerfastmode to understand how Visual Studio uses this Dockerfile to build your images for faster debugging.
FROM mcr.microsoft.com/dotnet/core/runtime:3.1-buster-slim AS base
WORKDIR /app
EXPOSE 80
FROM mcr.microsoft.com/dotnet/core/sdk:3.1-buster AS build
WORKDIR /src
COPY
["ProcessingFaceDetection.Worker/ProcessingFaceDetection.Worker.csproj", "ProcessingFaceDetection.Worker/"]
RUN dotnet restore "ProcessingFaceDetection.Worker/ProcessingFaceDetection.Worker.csproj"
COPY . .
WORKDIR "/src/ProcessingFaceDetection.Worker"
RUN dotnet build "ProcessingFaceDetection.Worker.csproj" -c Release -o /app/build
FROM build AS publish
RUN dotnet publish "ProcessingFaceDetection.Worker.csproj" -c Release -o /app/publish
FROM base AS final
RUN apt-get update && apt-get install -y libgdiplus libc6-dev libx11-dev && ln -s /usr/lib/libgdiplus.so /usr/lib/gdiplus.dll
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "ProcessingFaceDetection.Worker.dll"]
I don't know what else to try.

How to lower down the size of dockerized .Net Core apps?

I normally use Rider for that but for reproduction purposes I will describe the process by using the terminal
I created a .Net 5 Web Api and want to add Docker support for it. I tried to get into it by playing around with a sample app. So with the terminal I create a new Web Api
mkdir project
cd project
dotnet new sln
dotnet new webapi -o Api
dotnet sln add ./Api
I check that everything is fine with
cd Api
dotnet run
call https://localhost:5001/weatherforecast in the browser
close with ctrl + c
Inside the Api project I create a Dockerfile with this content
FROM mcr.microsoft.com/dotnet/sdk:5.0 AS build
WORKDIR /app
COPY *.csproj ./
RUN dotnet restore
COPY . ./
RUN dotnet publish -c Release -o out
FROM mcr.microsoft.com/dotnet/aspnet
WORKDIR /app
EXPOSE 80
COPY --from=build /app/out .
ENTRYPOINT [ "dotnet", "Rest.dll" ]
I also create a .dockerignore file with this content
.git
Dockerfile
bin/
obj/
I'm building the image with
docker build -t api .
When I now run
docker images
this image has a size of 209MB. I would like to know if this is "the best/right way to go" or if there is something I can improve in the Dockerfile or .dockerignore file.
Thanks in advance
You can base your Dockerfile off a smaller image. Searching the catalogue of available images in the Microsoft container registry (MCR) here, the Linux alpine (5.0-alpine) is probably the most lightweight. Note that for the other distros, there may be a regular and slim variant, where the regular is the SDK environment and the slim is the production environment.
Then you can structure your Dockerfile as follows to move the artefacts from the build output in the SDK image to the final lightweight deployment image:
FROM mcr.microsoft.com/dotnet/core/runtime:3.1-buster-slim AS base
WORKDIR /app
# Main build (SDK environment)
FROM mcr.microsoft.com/dotnet/core/sdk:3.1-buster AS build
WORKDIR /src
RUN dotnet restore "webapi.csproj"
COPY . .
WORKDIR "/src/webapi"
RUN dotnet build "webapi.csproj" -c Release -o /app/build
# Publish build outputs to /app dir
FROM build AS publish
RUN dotnet publish "webapi.csproj" -c Release -o /app/publish
# Final deployment image
FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "api.dll"]
In my example, I've used the Debian buster SDK image for the build stage and the buster slim for deployment.

How can I reduce the build time for a .NET Core application using Docker and Kaniko?

I have following Dockerfile in my .NET Core 2.2 console application.
FROM mcr.microsoft.com/dotnet/core/runtime:2.2-stretch-slim AS base
WORKDIR /app
FROM mcr.microsoft.com/dotnet/core/sdk:2.2-stretch AS build
WORKDIR /src
COPY ["TaikunBillerPoller.csproj", ""]
RUN dotnet restore "TaikunBillerPoller.csproj"
COPY . .
WORKDIR "/src/"
RUN dotnet build "TaikunBillerPoller.csproj" -c Release -o /app
FROM build AS publish
RUN dotnet publish "TaikunBillerPoller.csproj" -c Release -o /app
FROM base AS final
WORKDIR /app
COPY --from=publish /app .
ENTRYPOINT ["dotnet", "TaikunBillerPoller.dll"]
My .dockerignore file looks like
**/.dockerignore
**/.env
**/.git
**/.gitignore
**/.vs
**/.vscode
**/*.*proj.user
**/azds.yaml
**/charts
**/bin
**/obj
**/Dockerfile
**/Dockerfile.develop
**/docker-compose.yml
**/docker-compose.*.yml
**/*.dbmdl
**/*.jfm
**/secrets.dev.yaml
**/values.dev.yaml
**/.toolstarget
We are using GitLab and Kaniko for building gitlab-ci.yml file.
This console application takes 7 minutes to build, but another application written in the Go language takes 40 seconds.
How might I reduce the build time for this application?
Your first FROM line is completely unused. Instead change your FROM base line to FROM mcr.microsoft.com/dotnet/core/runtime:2.2-stretch-slim
This issue may be due to the fact that Kaniko **/someDir .dockerignore patterns are not properly observed. I'm noticing that /obj, /bin, .idea (rider) and .git folders are all being copied.
https://github.com/GoogleContainerTools/kaniko/issues/1396
You are also not using the alpine based sdk and runtime images.
In the dotnet restore command you can use the --no-cache flag because docker layer cacheing will take care of that.
dotnet publish does a build so you can skip calling dotnet build. If you want to perform testing you can call dotnet test then
You are explicitly calling dotnet restore so in all subsequent dotnet commands you can use the --no-restore option.
FROM mcr.microsoft.com/dotnet/core/sdk:2.2-alpine AS base
#Add whatever tools you need to the base image
RUN apk add --update --no-cache git bash curl zip; \
export PATH="$PATH:/root/.dotnet/tools"; \
dotnet tool install --global dotnet-xunit-to-junit --version 1.0.2
FROM base AS restore
WORKDIR /src
COPY ["TaikunBillerPoller.csproj", ""]
RUN dotnet restore --no-cache "TaikunBillerPoller.csproj"
COPY . .
FROM restore as publish
ARG VERSION="0.0.0"
RUN dotnet test "TaikunBillerPoller.csproj" --configuration Release --no-restore
RUN dotnet publish "TaikunBillerPoller.csproj" --output /app --configuration Release --no-restore /p:Version=$VERSION
FROM mcr.microsoft.com/dotnet/core/runtime:2.2-alpine AS final
WORKDIR /app
COPY --from=publish /app .
ENTRYPOINT ["dotnet", "TaikunBillerPoller.dll"]
On a 2015 Mac I have an asp.net microservice that builds, tests, publishes and creates a beanstalk_bundle zip using a normal docker build with the following times:
51s No cache
22s Code change
<1s No code change (pipeline yml change)
Kaniko adds overhead because layer caching is done remotely to some repository (typically).
This time is going to depend a lot on how you have your Kaniko cache and mounted volumes configured. Here is something I use on my local machine for debugging.
#!/bin/bash
# Assuming this is either not an ephemeral machine, or the ephemeral machine
# maps the cache directory to permanent volume.
# We cache images into the local machine
# so that the Kaniko container, which is ephemeral, does not have to pull them each time.
docker run -v $(pwd):/workspace gcr.io/kaniko-project/warmer:latest \
--cache-dir=/workspace/cache \
--image=mcr.microsoft.com/dotnet/core/sdk:2.2-alpine \
--image=mcr.microsoft.com/dotnet/core/aspnet:2.2-alpine
docker run -it --rm \
-v `pwd`:/workspace \
-v `pwd`/kaniko-config.json:/kaniko/.docker/config.json:ro \
-v `pwd`/reports:/reports \
-v `pwd`/beanstalk_bundle:/beanstalk_bundle \
gcr.io/kaniko-project/executor:latest \
--dockerfile "buildTestPublish.Dockerfile" \
--destination "registry.gitlab.com/somePath/theImageName:theVersion" \
--skip-unused-stages \
--cache \
--cache-dir=/workspace/cache \
--verbosity=trace

Categories