Is this dockerfile creating a corrupted image? - docker

I am trying to run a dotnet core Web Api application on a docker container on Windows 10
This is the project structure on the left side of the image. The Dockerfile is one level up the .csproj file, so its something like this.
/WebApi {Root folder}
- WebApi {folder container the WEbApi.csproj and other files folders}
- Dockerfile
- .dockerignore
- WebApi.sln
This the Dockerfile contents
FROM mcr.microsoft.com/dotnet/aspnet:3.1 AS base
WORKDIR /app
EXPOSE 80
EXPOSE 443
# Copy csproj and restore as distinct layers
FROM mcr.microsoft.com/dotnet/sdk:3.1 AS build
COPY WebApi/*.* src/
RUN dotnet restore src/WebApi.csproj
RUN dotnet build "src/WebApi.csproj" -c Release -o /app/build
# publish the project
FROM build AS publish
RUN dotnet publish src/WebApi.csproj -c Release -o /app/out
# Build runtime image
FROM base AS final
WORKDIR /app
COPY --from=publish /app/out .
ENTRYPOINT ["dotnet", "WebApi.dll"]
I build the image using this docker build -t webapi-img . in the same folder that has the Dockerfile.
This is the build log
Then I run the container using docker run -p 8090:8071 --name webpi-cntr webapi-img which gives the following output
info: Microsoft.Hosting.Lifetime[0]
Now listening on: http://[::]:8071
info: Microsoft.Hosting.Lifetime[0]
Application started. Press Ctrl+C to shut down.
info: Microsoft.Hosting.Lifetime[0]
Hosting environment: Production
info: Microsoft.Hosting.Lifetime[0]
Content root path: /app
The container runs but when I try to access the service on the host machine using http://localhost:8090/WeatherForecast, I get a 404 error.
When I access the container CLI and run the curl command using the port of the application I get no response as you can see in the screenshot below
Back on the host when I telnet localhost 8090, the telnet client connects to the port.
It looks like the container is running correctly and the mapping has also happened correctly. My assumption is that the core dotnet app is not running correctly, but I don't know what could be causing that or any ways to probe this further. Any pointers?
PS: I am using Dockerfile because I want to take this project later to an AWS ECS container via CDK and using a pipeline. Not sure if I can use docker compose there, but thats for later.

You should add EXPOSE 8071 to your Dockerfile so that your container exposes that port.

The problem was in this line
COPY WebApi/*.* src/
This was only copying the files in the root folder and not the folder which had the controllers. This is why on compiling, it was not able to find the path, /WeatherForecast but was standing up the server anyways.
The correction to the line that got everything working was ...
COPY WebApi/** src/

Related

I cannot open my docker container in my browser?

I've created an image on my local with my IdentityServer project.
Simply , I did build my dockerfile using
docker build -t identityserver .
DOCKERFILE
FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build-env
WORKDIR /app
COPY /IdentityServer/*.csproj ./
RUN dotnet restore
COPY /IdentityServer ./
RUN dotnet publish -c Release -o out
FROM mcr.microsoft.com/dotnet/aspnet:6.0
WORKDIR /app
COPY --from=build-env /app/out .
ENTRYPOINT ["dotnet", "IdentityServer.dll"]
Then after the build, I did run the image in the container
docker run -d -p 5443:5443 <image_id>
THE PROBLEM IS:
I'm trying to connect with the container using https://localhost:5443 but it doesn't work. The site cannot be reach. It is not existing. I've tried to look on the logs (see below) except that I think it runs in a production environment. I pretty sure it is one to fix because I'm just running in my local. But why can't I even find the page in the browser?
info: Microsoft.Hosting.Lifetime[14]
Now listening on: http://[::]:80
info: Microsoft.Hosting.Lifetime[0]
Application started. Press Ctrl+C to shut down.
info: Microsoft.Hosting.Lifetime[0]
Hosting environment: Production
info: Microsoft.Hosting.Lifetime[0]
Content root path: /app/
because your application is running on 80 port inside container.
Now listening on: http://[::]:80
you should map your local 5443 port to container 80 port.
docker run -d -p 5443:80 <image_id>

ASP.NET Core + Docker not accessible on specified port

It is impossible for me to access container with ASP.NET Core 3.1 application running inside.
Goal is to run application in container on port 5000. When I'm running it locally using standard VS profile I navigate to http://localhost:5000/swagger/index.html in order to load swaggerUI. I would like to achieve same thing using docker.
Steps to reproduce my issue:
Add dockerfile with exposed 5000 port and ENV ASPNETCORE_URLS variable:
FROM mcr.microsoft.com/dotnet/core/aspnet:3.1 AS base
WORKDIR /app
ENV ASPNETCORE_URLS=http://+:5000
EXPOSE 5000
FROM mcr.microsoft.com/dotnet/core/sdk:3.1 AS build
WORKDIR /src
COPY ["myapp/myapp.csproj", "myapp/"]
RUN dotnet restore "myapp/myapp.csproj"
COPY . .
WORKDIR "/src/myapp/"
RUN dotnet build "myapp.csproj" -c Release -o /app/build
FROM build AS publish
RUN dotnet publish "myapp.csproj" -c Release -o /app/publish
FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "myapp.dll"]
Build image
docker build -t myapp .
Run docker image:
docker run myapp -p 5000:5000
Running commands above with specific docker file results in this:
[21:28:42 INF] Starting host.
[21:28:42 INF] Now listening on: http://[::]:5000
[21:28:42 INF] Application started. Press Ctrl+C to shut down.
[21:28:42 INF] Hosting environment: Production
[21:28:42 INF] Content root path: /app
However, I can't access container using http://localhost:5000/swagger/index.html because of ERR_CONNECTION_REFUSED -> This site can't be reached.
I did get into container to check if host is running for sure, using:
docker exec -it containerId /bin/bash
cd /app
dotnet myapp.dll
what resulted in following error:
Unable to start Kestrel.
System.IO.IOException: Failed to bind to address http://[::]:5000: address already in use.
Conclusion is that port inside the container is used, application is alive, it's just not accessible from outside.I don't know how to get inside of it.
Please point me into right direction.
UPDATE
Issue is solved, answer is posted below. However explanation why it was needed and how it works would be nice!
To solve the issue I had to manually add "--server.urls" to entrypoint like shown below:
ENTRYPOINT ["dotnet", "myapp.dll", "--server.urls", "https://+:5000"]
I solved the same issue in the following way:
Added the following in appsettings.json to force Kestrel to listen to port 80.
"Kestrel": {
"EndPoints": {
"Http": {
"Url": "http://+:80"
}
}
}
Exposed the port in dockerfile
ENV ASPNETCORE_URLS=http://+:80
EXPOSE 80
ENTRYPOINT ["dotnet", "EntryPoint.dll"]
Ran the container using the below command.
docker run -p 8080:80 <image-name>:<tag>
The app exposed on http://localhost:8080/

Dockerizing .Net Core Service with default gRPC service template is not working

I have created a .net core 3.1 grpc project using Visual Studio(VS) template and added docker support (targe:Linux os) to it.
With the sayhello code already in the template, I ran it with VS IDE and it worked fine and given the http default page.
However when we run it with docker build and docker run commands in console, the console shows its listening and the container is running. however service is not accessible and the error received is site cant be reached.
I have grabbed and issued the build and run commands from the VS container tools output window, still the service is not accessible nor the default page is shown. Has anyone came across the same issue, any help would be much appreciated.
Docker file
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 "GrpcService2.csproj" .
RUN dotnet restore "GrpcService2.csproj"
COPY . .
RUN ls -R
WORKDIR "/src"
RUN dotnet build "GrpcService2.csproj" -c Release -o /app/build
FROM build AS publish
RUN dotnet publish "GrpcService2.csproj" -c Release -o /app/publish
FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "GrpcService2.dll"]
Maybe you have to look up the port that's exposed by docker. See the docker dashboard. I haven't found out how to configure a fix port. At the moment at each start of the service a new port is taken by docker...

Why can i not find MSBuild in multi solution asp.net-core application within a docker container

I am trying to contain my asp.net-core application into a docker container. As I use the Microsoft-secret-store for saving credentials, I need to run a dotnet user-secrets command withing my container. The application needs to read these credentials when starting, so I have to run the command prior to starting my application. When trying to do that in my Dockerfile I get the error:
---> Running in 90f974a06d83
Could not find a MSBuild project file in '/app'. Specify which project to use with the --project option.
I tried building my application first and then building a container with the already build dll, but that gave me the same error. I also tried connecting to the container with ENTRYPOINT ["/bin/bash"] and then looking around in the container. It seems that the /app folder that gets created does not have the .csproj files included. Im not sure if that could be an error.
My Dockerfile
FROM mcr.microsoft.com/dotnet/core/sdk:2.2 AS base
WORKDIR /app
EXPOSE 80
EXPOSE 443
FROM mcr.microsoft.com/dotnet/core/sdk:2.2-stretch AS build
WORKDIR /src
COPY ["Joinme.Facade/Joinme.Facade.csproj", "Joinme.Facade/"]
COPY ["Joinme.Domain/Joinme.Domain.csproj", "Joinme.Domain/"]
COPY ["Joinme.Business/Joinme.Business.csproj", "Joinme.Business/"]
COPY ["Joinme.Persistence/Joinme.Persistence.csproj", "Joinme.Persistence/"]
COPY ["Joinme.Integration/Joinme.Integration.csproj", "Joinme.Integration/"]
RUN dotnet restore "Joinme.Facade/Joinme.Facade.csproj"
COPY . .
WORKDIR "/src/Joinme.Facade"
RUN dotnet build "Joinme.Facade.csproj" -c Release -o /app
FROM build AS publish
RUN dotnet publish "Joinme.Facade.csproj" -c Release -o /app
FROM base AS final
WORKDIR /app
COPY --from=publish /app .
RUN dotnet user-secrets set "jwt:secret" "some_password"
ENTRYPOINT ["dotnet", "Joinme.Facade.dll"]
My expected results are that the secret gets set, so I can start the container without it crashing.
Plain and simple: the operation is failing because at this stage, there is no *.csproj file(s), which the user-secrets command requires. However, this is not what you should be doing anyways for a few reasons:
User secrets are not for production. You can just as easily, or in fact more easily, set an environment variable here instead, which doesn't require dotnet or the SDK.
ENV jwt:secret some_password
You should not actually be storing secrets in your Dockerfile, as that goes into your source control, and is exposed as plain text. Use Docker secrets, or an external provider like Azure Key Vault.
You don't want to build your final image based on the SDK, anyways. That's going to make your container image huge, which means both longer transfer times to/from the container registry and higher storage/bandwidth costs. Your final image should be based on the runtime, or even something like alpine, if you publish self-contained (i.e. keep it as small as possible).

Hosted a .net core api on windows server 2016 docker container, on invoking docker start, status is Exited (2147516566) instead of UP

I want to run multiple instances of .net core API on windows server 2016 using windows docker container. I am able to create image and container successfully, but on invoking docker start the container are not running Up instead it exited with code (2147516566).
Here is my docker file content which is in published API directory
FROM mcr.microsoft.com/dotnet/core/runtime:2.2-nanoserver-sac2016
COPY / app/
ENTRYPOINT ["dotnet", "app/MyAPI.dll"]
I didn't spend long on it, but I didn't have good luck running binaries I built myself. The docker add in for visual studio always performs the build inside a container. I have adapted to this. Here is an example Dockerfile I have anonymized. Hopefully I didn't break anything:
# Base image for running final product
FROM mcr.microsoft.com/dotnet/core/sdk:2.2-nanoserver-sac2016 AS base
WORKDIR /app
EXPOSE 80
EXPOSE 443
# build asp.net application
FROM mcr.microsoft.com/dotnet/core/sdk:2.2-nanoserver-sac2016 AS build
WORKDIR /src
COPY ["Test.Docker.Windows/Test.Docker.Windows.csproj", "Test.Docker.Windows/"]
RUN dotnet restore "Test.Docker.Windows/Test.Docker.Windows.csproj"
COPY . .
WORKDIR "/src/Test.Docker.Windows"
RUN dotnet build "Test.Docker.Windows.csproj" -c Release -o /app
FROM build AS publish
RUN dotnet publish "Test.Docker.Windows.csproj" -c Release -o /app
FROM base AS final
WORKDIR /app
COPY --from=publish /app .
# startup.bat contains dotnet test.Docker.Windows.dll
CMD ./startup.bat

Resources