I have followed these steps:
1) Create a new ASP.NET Core Web application (MVC) without Docker support.
2) Create two new folders (one inside the other) inside the solution called Application\Image (Application is at the same level as the Controllers folder).
3) Add a file called TestImage.png into the Image folder.
4) Access the file successfully using the following code:
byte[] image = System.IO.File.ReadAllBytes("Application\\Image\\TestImage.png");
Expected behaviour up to now; here is the problematic bit:
5) Right click on the solution and select: Add Container Orchestration Support/Docker Compose/Linux (target OS)
6) Run the project (docker-compose is the startup project). I get an error saying: System.IO.IOException: 'Invalid argument'
I have done a lot of Googling and it tells me I have to configure the Dockerfile to copy the image to the container. The Dockerfile currently looks like this:
FROM microsoft/dotnet:2.2-aspnetcore-runtime AS base
WORKDIR /app
EXPOSE 80
FROM microsoft/dotnet:2.2-sdk AS build
WORKDIR /src
COPY WebApplication1/WebApplication1.csproj WebApplication1/
RUN dotnet restore WebApplication1/WebApplication1.csproj
COPY . .
WORKDIR /src/WebApplication1
RUN dotnet build WebApplication1.csproj -c Release -o /app
FROM build AS publish
RUN dotnet publish WebApplication1.csproj -c Release -o /app
FROM base AS final
WORKDIR /app
COPY --from=publish /app .
ENTRYPOINT ["dotnet", "WebApplication1.dll"]
I have tried adding this line (below this line: COPY WebApplication1/WebApplication1.csproj WebApplication1/):
COPY WebApplication1/Application/Image/TestImage.png WebApplication1/Application/Image/
However, I see the same error. How can I get the app to read the image now I am using Docker?
Related
I have multiple dotnet projects with multi level nesting and I am specifying each csproj with their path structure below for each and every application's docker file.
Whenever there is a addition and deletion of projects all docker file have to be update.
Can I avoid it and make some generic docker file?
FROM mcr.microsoft.com/dotnet/core/aspnet: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 My.sln .
COPY ["Core/Events.csproj", "Core/"]
COPY ["Core/Infra/Services/Services.csproj", "Core/Infra/Services/"]
COPY ["Features/Feature.A.API/Feature.A.API.csproj", "Features/Feature.A.API/"]
RUN dotnet restore
COPY . .
You could store all needed projects in a root dir lets call it src then you just have to use the main project for restore/build/publish (the one with your asp .net core webapi), all the other sources (dependencies) needed during build would then be present (in the src dir), with correct paths.
For example:
src/Core/....
src/Features/...
src/Features/Feature.A.API/Dockerfile
The docker file would then look like this (aspnet 5.0):
with place holders:
[API_DIR] in your case: Features/Feature.A.API/
[API_PROJECT] in your case: Feature.A.API
FROM mcr.microsoft.com/dotnet/aspnet:5.0 AS base
WORKDIR /app
EXPOSE 80
FROM mcr.microsoft.com/dotnet/sdk:5.0 AS build
WORKDIR /src
COPY ["src/[API_DIR]/[API_PROJECT].csproj", "[API_DIR]/"]
RUN dotnet restore "[API_DIR]/[API_PROJECT].csproj"
COPY ["src/", "."]
WORKDIR "src/[API_DIR]"
RUN dotnet build "[API_PROJECT].csproj" -c Release -o /app/build
FROM build AS publish
RUN dotnet publish "[API_PROJECT].csproj" -c Release -o /app/publish
FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "[API_PROJECT].dll"]
Run it from Folder which contains the src dir (this is your build context), with:
docker build src/Features/Feature.A.API/Dockerfile
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.
When I start my container, the page starts without styles, scripts, images and other static files - calls to load them return 404.
I would like to say that when I access the app folder, the wwwroot folder exists.
I tested it in my Release folder (with dotnet command). But in Docker it does not work. Yes, I'm using UseStaticFiles in my Startup class.
My Dockerfile is simple, it just runs the app. But I previously built and published the app, and the wwwroot is there.
FROM mcr.microsoft.com/dotnet/core/aspnet:3.1
WORKDIR /app
EXPOSE 80
EXPOSE 443
COPY bin/Release app/
ENTRYPOINT ["dotnet", "app/MyApp.SGC.Site.dll"]
The application runs, but there are many erros:
Can someone help me?
You must run the dotnet publish command so that all the required files are copied into your app folder.
Your release folder only has the dll files for your application so when you copy it into the docker container the wwwroot files are not copied.
If you create a new web app project and tick the Docker support option it will make a dockerfile for you. Create a sample project so you can see the recommended way to containerize your application.
Here is an example that uses the publish command:
FROM mcr.microsoft.com/dotnet/core/aspnet:3.1-buster-slim AS base
WORKDIR /app
EXPOSE 80
EXPOSE 443
FROM mcr.microsoft.com/dotnet/core/sdk:3.1-buster AS build
WORKDIR /src
COPY ["MyApp.SGC.Site/MyApp.SGC.Site.csproj", "MyApp.SGC.Site/"]
RUN dotnet restore "MyApp.SGC.Site/MyApp.SGC.Site.csproj"
COPY . .
WORKDIR "/src/MyApp.SGC.Site"
RUN dotnet build "MyApp.SGC.Site.csproj" -c Release -o /app/build
FROM build AS publish
# publish will copy wwwroot files as well
RUN dotnet publish "MyApp.SGC.Site.csproj" -c Release -o /app/publish
WORKDIR /app/publish
FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "MyApp.SGC.Site.dll"]
For someone using Docker and you are sure that the Container contains your static files but still getting 404.
Check your Dockerfile if you have WORKDIR directive:
FROM mcr.microsoft.com/dotnet/aspnet:6.0
WORKDIR /app # this line
ENV ASPNETCORE_URLS=http://+:5000
COPY --from=build /app/out .
ENTRYPOINT ["dotnet", "YourApp.dll"]
Then in Program.cs (or Startup.cs) make sure the root path starts with "/app":
builder.Services.AddSpaStaticFiles(config => config.RootPath = "/app/wwwroot");
Just add the code below to your ASP.NET Core WebAPI Project File .csproj. It will copy your folder and all your files into your Docker image or Publish folder, depending on which process you are trying to run. Be sure to change the folder name to your own...
<ItemGroup>
<Content Include="MySubFolder\*">
<CopyToPublishDirectory>always</CopyToPublishDirectory>
</Content>
</ItemGroup>
I'm trying to upload my project to a Digital Ocean droplet using docker i'm stuck in this stage, where COPY fails whenever i run docker-compose build.
Dockerfile:
FROM mcr.microsoft.com/dotnet/core/aspnet:3.1-buster-slim AS base
WORKDIR /app
EXPOSE 80
EXPOSE 443
FROM mcr.microsoft.com/dotnet/core/sdk:3.1-buster AS build
WORKDIR /src
COPY ["iCoose.API/iChoose.API.csproj", "iCoose.API/"]
COPY ["iChoose.Business.Entities/iChoose.Business.Entities.csproj", "iChoose.Business.Entities/"]
COPY ["iChoose.Business.Services/iChoose.Business.Services.csproj", "iChoose.Business.Services/"]
COPY ["iChoose.Common.Core/iChoose.Common.Core.csproj", "iChoose.Common.Core/"]
COPY ["iChoose.DataAccess.Data/iChoose.DataAccess.Data.csproj", "iChoose.DataAccess.Data/"]
RUN dotnet restore "iCoose.API/iChoose.API.csproj"
COPY . .
WORKDIR "/src/iCoose.API"
RUN dotnet build "iChoose.API.csproj" -c Release -o /app/build
FROM build AS publish
RUN dotnet publish "iChoose.API.csproj" -c Release -o /app/publish
FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "iChoose.API.dll"]
docker-compose.yml:
#docker-compose
version: '2'
services:
app:
build:
context: ./
dockerfile: Dockerfile
https-portal:
image: steveltn/https-portal:1
ports:
- '80:80'
- '443:443'
links:
- app
restart: always
environment:
DOMAINS: 'domain.com -> http://app:5000'
STAGE: 'production'
When I run the 'docker-compose build' command in the servers terminal it starts building until it gets to the first COPY command, where I get:
ERROR: Service 'app' failed to build: COPY failed: stat /var/lib/docker/tmp/docker-builder987069796/iCoose.API/iChoose.API.csproj: no such file or directory.
I checked the files and there is no directory in that path after the 'tmp' folder, which is empty.
The Dockerfile and docker-compose.yaml files should be right next to sln and csproj file.
When you create a new project in Visual Studio and leave put project file inside the project folder this issue might occure.
Make sure you have sln and csproj in the same folder.
Also, the Dockerfile and 'docker-compose.yaml` in the same folder too.
Deeper answer:
Dockerfile contains instructions for the docker engine on how to create a docker image for your application.
Each line is a layer of docker image.
FROM
COPY
RUN
CMD
All these commands will create a new docker image, which are cache by the engine for next run.
Because these images are Linux based and linux uses cgroup and namespaces to create isolated environment which is the feature on which docker is built. This isolated environment has a special folder which is appearing in the error message.
I am trying to run my ASP.net Core application with docker, but for some reasons each time I try with different approach with the Dockerfile I fail by copying the directory.
What am I doing wrong? I tried the step by step guide in Microsoft web using my own proj but with unsuccess.
The cmd error I recieve:
C:\dev\Dmail\Dmail.API>docker build -t aspnetapp .
Sending build context to Docker daemon 21.79MB
Step 1/18 : FROM mcr.microsoft.com/dotnet/core/aspnet:3.1-buster-slim AS base
---> 47da1e9634dc
Step 2/18 : WORKDIR /app
---> Using cache
---> bf490aa67962
Step 3/18 : EXPOSE 80
---> Using cache
---> d172deff350a
Step 4/18 : FROM mcr.microsoft.com/dotnet/core/sdk:3.1-buster AS build
---> 4a651b73be3d
Step 5/18 : WORKDIR /src
---> Using cache
---> c607b7f04e23
Step 6/18 : COPY ["Dmail.API/Dmail.API.csproj", "Dmail.API/"]
COPY failed: stat /var/lib/docker/tmp/docker-builder531905822/Dmail.API/Dmail.API.csproj: no such file or directory
C:\dev\Dmail\Dmail.API>
Here is my DockerFile:
#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/aspnet: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 ["Dmail.API/Dmail.API.csproj", "Dmail.API/"]
COPY ["Dmail.Core/Dmail.Core.csproj", "Dmail.Core/"]
COPY ["Dmail.Data/Dmail.Data.csproj", "Dmail.Data/"]
RUN dotnet restore "Dmail.API/Dmail.API.csproj"
COPY . .
WORKDIR "/src/Dmail.API"
RUN dotnet build "Dmail.API.csproj" -c Release -o /app/build
FROM build AS publish
RUN dotnet publish "Dmail.API.csproj" -c Release -o /app/publish
FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "Dmail.API.dll"]
So after long time of searching the web for a solution I managed to solve my problem.
First of all the Dockerfile was generated automatically by Visual Studio by pressing add onto the ASP.net project and then Docker Support.
The Visual Studio locate the file inside the project. What I did in order to solve the problem was to move the file as it is to the solution folder which is for me Dmail. For example my files were like this:
Dmail(solution)
Dmail.API(proj)
Dmail.Core(proj)
Dmail.Data(proj)