Reputation: 1489
I decided it was time for learning docker and for this I have an asp.net core api project that runs perfectly on IIS express. This project is a simple REST API. The goal here is to set a basic get entry point, check if it works on IIS Express and then create a Dockerfile in order to deploy my app. I post the question because I tried to find out response on web and stackoverflow.
For this I already have a basic startup class:
namespace app.rest
{
public class Startup
{
private readonly string ConnectionString;
public IConfiguration Configuration { get; }
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public void ConfigureServices(IServiceCollection services)
{
services.AddScoped<AppService, AppServiceImpl>();
services.AddScoped<ApiEntryPointService, ApiEntryPointServiceImpl>();
services.AddControllers();
services.AddSwaggerGen(c =>
{
c.SwaggerDoc("v1", new OpenApiInfo { Title = "WebApplication", Version = "v1" });
});
services.AddMvc();
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseSwagger();
app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "WebApplication v1"));
}
else
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
// app.UseHttpsRedirection();
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
}
}
A Program class that have been automatically implemented on project creation.
namespace app.rest
{
public class Program
{
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
}
}
And a simple controller :
namespace app.rest.Controllers
{
[Route("api/[controller]")]
[ApiController]
public class AppController
{
// GET api/<AppController>/5
[HttpGet]
public string Get()
{
return "Hello World";
}
}
}
this works fine when I use IIS Express and I can see my hello world. My dockerfile can build the image and i can even run it.
Here is my Dockerfile :
FROM mcr.microsoft.com/dotnet/sdk:5.0 AS base
WORKDIR /appSource
EXPOSE 5000
FROM mcr.microsoft.com/dotnet/sdk:5.0 AS build
WORKDIR /appBuild
# Copy csproj and restore as distinct layers
COPY *.sln .
COPY *.csproj .
#RUN mkdir /tmp/build/
#COPY . /tmp/build
#RUN find /tmp/build -name *.csproj
RUN dotnet restore app.rest.csproj --verbosity detailed
# Copy everything else and build
COPY . .
WORKDIR /appBuild/app.rest
RUN dotnet build "../app.rest.csproj" -c Release -o /appSource --no-restore
FROM build AS publish
WORKDIR /appBuild/app.rest
RUN dotnet publish "../app.rest.csproj" -c Release -o /appSource
FROM base AS final
WORKDIR /appSource
COPY --from=publish /appSource .
ENTRYPOINT ["dotnet", "app.rest.dll"]
TO build the image I simply type :
docker build --pull -t app.rest .
And as I expose the port 5000, I launch a docker run command and bind ports (if i understood correctly what i'm doing):
docker run -d -p 5000:5000 -it app.rest
I checked logs and there's no particular issues:
warn: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[60]
Storing keys in a directory 'C:\Users\ContainerUser\AppData\Local\ASP.NET\DataProtection-Keys' that may not be persisted outside of the c]0;C:\Program Files\dotnet\dotnet.exeontainer. Protected data will be unavailable when container is destroyed.
info: Microsoft.Hosting.Lifetime[0]
Now listening on: http://localhost:5000
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: C:\appSource
I should be able to connect to this api with this URL: http://localhost:5000/api/App Unfortunatelly it's not the case.
Upvotes: 1
Views: 1427
Reputation: 686
Your run-time docker image is the sdk one. Usually the sdk image is only used for building the artefacts (i.e. compilation and publishing). Instead, try using the Microsoft run-time image equivalent mcr.microsoft.com/dotnet/aspnet:5.0
.
So,
...
FROM mcr.microsoft.com/dotnet/aspnet:5.0 AS base
...
FROM base AS final
WORKDIR /appSource
COPY --from=publish /appSource .
EXPOSE 5000
ENTRYPOINT ["dotnet", "app.rest.dll"]
This might fix your problem. When I tried to run one of my own from the sdk image it wouldn't respond to http requests.
Upvotes: 2
Reputation: 1489
Here is the solution I finally implemented and which works:
FROM mcr.microsoft.com/dotnet/sdk:5.0 AS build
WORKDIR /source
# copy csproj and restore as distinct layers
COPY *.sln .
COPY *.csproj ./
RUN dotnet restore
# copy everything else and build app
COPY /. ./
WORKDIR /source
RUN dotnet publish -c release -o /app --no-restore
# final stage/image
FROM mcr.microsoft.com/dotnet/aspnet:5.0
WORKDIR /app
COPY --from=build /app ./
ENTRYPOINT ["dotnet", "app.rest.dll"]
Solving issue at 3 in the morning helps to find solutions... Here comes the inspiration.
https://github.com/dotnet/dotnet-docker/tree/main/samples/aspnetapp
Upvotes: 0