I used following docker script to build and run my ASP.NET Web API project on .net 4.6.1 framework.
FROM microsoft/dotnet-framework:4.7.2-sdk AS build
WORKDIR /app
# copy csproj and restore as distinct layers
COPY *.sln .
COPY TestWebAPI/*.csproj ./TestWebAPI/
COPY TestWebAPI/*.config ./TestWebAPI/
RUN nuget restore
# copy everything else and build app
COPY TestWebAPI/. ./TestWebAPI/
WORKDIR /app/TestWebAPI
RUN msbuild /p:Configuration=Release
FROM microsoft/aspnet:4.7.2 AS runtime
WORKDIR /inetpub/wwwroot
COPY --from=build /app/TestWebAPI/. ./
In the first step I am setting app folder as my working directory. But after creating container, I do not see any folder name app on my C:
--To create Image
docker image build --tag testwebapi --file .\Dockerfile .
--To run container
docker container run --detach --publish 80 testwebapi
--To see containers content
docker exec -i -t a1da40af6b3c powershell
Where does docker keep the source code?
You'll find your files in c:\inetpub\wwwroot.
Note that your Dockerfile has two FROM lines:
FROM microsoft/dotnet-framework:4.7.2-sdk AS build
...
FROM microsoft/aspnet:4.7.2 AS runtime
This is using a relatively new Docker feature called multi-stage builds. Basically, only the instructions from the second (and last) stage determine what's copied into the actual image:
WORKDIR /inetpub/wwwroot
COPY --from=build /app/TestWebAPI/. ./
Note that --from=build references the output of first stage - think of it as a temporary image. /inetpub/wwwroot is the WORKDIR of the second stage, so that's where you'll find the files from the final COPY step.
Related
I am trying to dockerize my web API with docker and I have encountered an error MSB1001: Unkown switch. More details can be found in the cmd prompt image
Does anyone know what this means, I've tried to follow up on this in GitHub discussions and posts in StackOverflow.
My Dockerfile:
FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build
WORKDIR C:\Users\Alexa\OneDrive\Desktop\SortIT\Api
# Copy everything
COPY . .
# Restore as distinct layers
RUN dotnet restore "./Api.csproj"
RUN dotnet publish "/Api.csproj" -c release -o ./
# Build runtime image
FROM mcr.microsoft.com/dotnet/aspnet:6.0
COPY --from=build /Api .
ENTRYPOINT ["dotnet", "Api.dll"]
My file directory
There are a number of issues with your Dockerfile. The one giving you the 'unknown switch' is on the publish statement, where you've given the project file name as /Api.csproj. It should be ./Api.csproj.
As others have pointed out, your WORKDIR uses Windows syntax, but you're building a Linux image and should use Linux syntax. I like to use /src as the directory in my build steps.
You publish the project to ./ which means that you'll end up with a directory that contains both your source and the published project. You want to keep them separate, so you can copy only the published project into the final image.
Which those changes, you end up with
FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build
WORKDIR /src
# Copy everything
COPY . .
# Restore as distinct layers
RUN dotnet restore "./Api.csproj"
RUN dotnet publish "./Api.csproj" -c Release -o out
# Build runtime image
FROM mcr.microsoft.com/dotnet/aspnet:6.0
COPY --from=build /src/out .
ENTRYPOINT ["dotnet", "Api.dll"]
I assume you have build context in the folder with Api.csproj file. First - WORKDIR sets the current working directory in the container. It is not a directory on the host system. You start with a directory where you copy source code from the build context to the container. Good name for it /src
FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build
WORKDIR /src # current directory in the container
COPY . . # Copy everything from build context to /src
RUN dotnet restore "Api.csproj"
Note that in order to optimize the build process and use caching, its better to start with copying *.csproj file only and restore dependencies. Because source code changes more often then dependencies of the application.
Next you want to build/publish your application somewhere in a container. Usually you create new directory for that and don't use the system root:
#publish app to folder /publish
RUN dotnet publish "Api.csproj" -c release -o /publish
And the last step - you should copy the published application to the runtime container. Here you set the current directory to the directory where the published application will be located:
FROM mcr.microsoft.com/dotnet/aspnet:6.0
WORKDIR /app #now set the current directory to /app
COPY --from=build /publish . #copy from build stage to /app
And don't forget to expose ports used by your API.
Dockerfile:
FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build
WORKDIR /src
COPY "Api.csproj" .
RUN dotnet restore "Api.csproj"
COPY . .
RUN dotnet publish "Api.csproj" -c release -o /publish
FROM mcr.microsoft.com/dotnet/aspnet:6.0
WORKDIR /app
EXPOSE 80
COPY --from=build /publish .
ENTRYPOINT ["dotnet", "Api.dll"]
I already have my Visual Studio Code attached to my running container. It's a .Net Core WepApi. This is the link for the post I created when struggling to make it work.
The problem, I am facing now, is that despite the fact my VS Code is attached to the container I can't debug any code yet. It keeps saying:
No symbols has been loaded for this document
Which is kind of odd because I can see the pdb files where generated and deploy to the container:
When I attached the Docker Container my VS Code looks like this:
This is the updated docker file I have:
FROM mcr.microsoft.com/dotnet/core/sdk:3.1 AS build-env
WORKDIR /app
# Copy csproj and restore as distinct layers
COPY *.csproj ./
RUN dotnet restore
# Copy everything else and build
COPY . ./
RUN dotnet publish -c Release -o out
###########START NEW IMAGE###########################################
# Build runtime image
FROM mcr.microsoft.com/dotnet/core/aspnet:3.1
#install debugger for NET Core
FROM mcr.microsoft.com/dotnet/core/aspnet:3.1
RUN apt update && \
apt install -y unzip procps && \
curl -sSL https://aka.ms/getvsdbgsh | /bin/sh /dev/stdin -v latest -l /vsdbg
WORKDIR /app
COPY --from=build-env /app/out .
ENTRYPOINT ["dotnet", "BooksApi.dll"]
Has anyone have face a similar problem?
We are trying to build an iot edge module on windows 1809. Our Project folder hierarchy is as follows:
----BaseDir
|---ClassLibrary1
|---ClassLibrary2
|--references ClassLibrary1
|--references ClassLibrary3
|---ClassLibrary3
|--references ClassLibrary4
|--references ClassLibrary1
|---ClassLibrary4
|---OurIOTEdgeModule
|--references ClassLibrary2
Our docker file looks like this:
FROM microsoft/dotnet:2.1-sdk AS build-env
WORKDIR /app
COPY *.csproj ./
COPY ./NuGet.Config ./
RUN dotnet restore
COPY . ./
RUN dotnet publish -c Release -o out
FROM microsoft/dotnet:2.1-runtime-nanoserver-1809
WORKDIR /app
COPY --from=build-env /app/out ./
ENTRYPOINT ["dotnet", "IOTEdgeModule.dll"]
When we build this IOT Edge Module we are not getting any build errors. When we deploy the module on the EDGE device, we are facing the issue.
Our IOTEdgeModule is referencing ClassLibrary2.csproj. ClassLibrary2 inturn is referencing ClassLibrary3.csproj which in turn is referencing ClassLibrary4.csproj. Our IOT Edge module is only able to get the reference of ClassLibrary2.csproj but failing to refer all other dependant *.csprojs.
How to modify the docker file to solve this issue? Suggestions would be much appreciated.
This is not possible with the dockerfiles provided by the IoT Edge templates. The official IoT Edge repo has examples with the same structure. Instead of building inside a docker container, they build outside and only copy the built binaries into the final image. See this example project file and the corresponding Dockerfile:
ARG base_tag=2.1.10-alpine3.7
FROM mcr.microsoft.com/dotnet/core/runtime:${base_tag}
ARG EXE_DIR=.
ENV MODULE_NAME "SimulatedTemperatureSensor.dll"
WORKDIR /app
COPY $EXE_DIR/ ./
# Add an unprivileged user account for running the module
RUN adduser -Ds /bin/sh moduleuser
USER moduleuser
CMD echo "$(date --utc +"[%Y-%m-%d %H:%M:%S %:z]"): Starting Module" && \
exec /usr/bin/dotnet SimulatedTemperatureSensor.dll
Update: There is a solution to a similar issue here.
in about a year ago I remember when we want to run the app in docker for development purpose, we run the app with the dotnet watch run. but in recent updates, the template is creating a publish version and run that one. I agree that it's good for production. but why the development version is gone completely? I searched a lot but couldn't find why this changed happened.
something like this:
FROM microsoft/aspnetcore-build:2.0
# Required inside Docker, otherwise file-change events may not trigger
ENV DOTNET_USE_POLLING_FILE_WATCHER 1
# Set a working dir at least 2 deep. The output and intermediate output folders will be /code/obj and /code/bin
WORKDIR /code/app
# By copying these into the image when building it, we don't have to re-run restore everytime we launch a new container
COPY web.csproj .
COPY NuGet.config .
COPY Directory.Build.props .
RUN dotnet restore
# This will build and launch the server in a loop, restarting whenever a *.cs file changes
ENTRYPOINT dotnet watch run --no-restore
now on each change, we need to publish the app to have a working docker again.
I saw that the debugging works fine in visual studio with this new approach, but I'm confused about how the visual studio is able to attach to the container and do remote debugging. and more surprise I am about how visual studio is able to debug an application that is published in release mode?
but now it look like this:
FROM microsoft/dotnet:2.2-aspnetcore-runtime AS base
WORKDIR /app
EXPOSE 80
EXPOSE 443
FROM microsoft/dotnet:2.2-sdk AS build
WORKDIR /src
COPY ["MyProject.csproj", "MyProject"]
COPY ["MyProject.Common.csproj", "MyProject.Common"]
RUN dotnet restore "MyProject.csproj"
COPY . .
WORKDIR "/src/MyProject"
RUN dotnet build "MyProject.csproj" -c Release -o /app
FROM build AS publish
RUN dotnet publish "MyProject.csproj" -c Release -o /app
FROM base AS final
WORKDIR /app
COPY --from=publish /app .
ENTRYPOINT ["dotnet", "MyProject.dll"]
Stating the obvious but in case: dotnet watch waits for file changes and then recompiles without you needing to restart manually.
It's still possible to use dotnet watch but you don't get any advantages in a container situation when your copying files. As the copying of the files takes place at the container build time and copies them to a source location inside the image and thus any changes to your code base won't be reflected when the container is running even if your using dotnet watch.
If you want to use dotnet watch look into mounting the source directory as a volume inside the container :)
You can use something like the following:
docker run --rm -it -p < port >:< port > -v ~/< sourcedirectory >:/< destination >/ -w /< destination >/aspnetapp mcr.microsoft.com/dotnet/core/sdk:3.0 dotnet watch run
The -v flag stands for volume if that wasn't obvious. If you wish to add a volume to a Dockerfile you can read about Dockerfile & Volumes here. And dotnet watch here. And Docker volumes specifically here. And lastly I found the in my history where I got the docker run command from.
I'm new in docker and I have a problem I can't deal with. I created .net core MVC application and this app is supposed to work on raspberry pi, so I dockerized my app on raspberry on HypriotOS and everything is good, but some images from wwwroot (default static files folder) is not Found (404). In wwwroot folder I have some css, js and images files and css, js and few images are available, but few .png files no. I don't have idea why.
.net core version is 2.2
I tired add line VOLUME ["/wwwroot"] in my Dockerfile
in Startup.Configure() method I have line app.UseStaticFiles();
My Dockerfile
FROM mcr.microsoft.com/dotnet/core/sdk:2.2 AS build
WORKDIR /app
# copy csproj and restore as distinct layers
COPY *.csproj ./
RUN dotnet restore
# copy everything else and build app
COPY . ./
RUN dotnet publish -c Release -o out
FROM mcr.microsoft.com/dotnet/core/aspnet:2.2 AS runtime
WORKDIR /app
COPY --from=build /app/out .
ENTRYPOINT ["dotnet", "TestApp.dll"]
Commands to build and run Docker image:
docker build -t testapp .
docker run -p 8080:80 --name testapp testapp
Dockerize passes correctly, no errors. The application is accessible from the outside, everything works, but some graphics are not displayed (404 Not Found).
Check your .dockerignore file for anything that might match the missing files/path. That's what fixed this for me.