I just upgraded my Web API application to .NET core 3.0, all works fine when running in debug mode in IIS Express, but context does not respond when running in docker container either on server or in VS debug. No error thrown, just never responds.
I tried deploying an updated image to server which is where I first noticed the issue. I then tried running as docker in vs to debug. I have updated all NuGet packages and set frameworks to .NET Core 3.0 or .NET Standard 2.1. I have inspected the context connection string in debug and it appears to be correct. I rolled back to an earlier image using .NET core 2.2 and all worked as expected using the same startup parameters. I created a test method that does not use context and it returns correct values on server and in VS docker debug. I tried changing the method to use synchronous call to context, but no change in behavior. The test database is very small, only 3 records in the table being queried.
public async Task<List<SendingSystemInfoResponse>> getSendingSystemInfoList()
{
try
{
return await _context.EmailSendingSystem.Where(m => !m.Deleted && m.Active == true).Select(m => new SendingSystemInfoResponse
{
SystemId = m.EmailSendingSystemId,
SystemName = m.Title,
SystemDescription = m.Description
}).ToListAsync();
}
catch (Exception ex)
{
_logger.LogError(ex, string.Format("EmailDataAccess: Exception retrieving EmailSendingSystem List"));
throw;
}
}
If there were an error connecting to the SQL Server, or if the SQL request timed out, I would expect to hit the catch block code, but this never happens.
Here is the content of the docker file, I'm not sure if my targets for base and build images are correct. They seem to work, but might be the cause of my issue.
FROM mcr.microsoft.com/dotnet/core/aspnet:3.0 AS base
WORKDIR /app
EXPOSE 80
FROM mcr.microsoft.com/dotnet/core/sdk:3.0-buster AS build
WORKDIR /src
COPY ["EmailAutomation.API/EmailAutomation.API.csproj", "EmailAutomation.API/"]
COPY ["EmailAutomation.API/NuGet.Config", "/src"]
RUN dotnet restore "EmailAutomation.API/EmailAutomation.API.csproj"
COPY . .
WORKDIR "/src/EmailAutomation.API"
RUN dotnet build "EmailAutomation.API.csproj" -c Release -o /app
FROM build AS publish
RUN dotnet publish "EmailAutomation.API.csproj" -c Release -o /app
FROM base AS final
WORKDIR /app
COPY --from=publish /app .
ENTRYPOINT ["dotnet", "EmailAutomation.API.dll"]
------Update----- So, I've been working on this off and on today, and have a little more info that might help someone point me in the right direction. I created a simple test Web API project with an EF connection to SQL Server running on my local PC using .NET core 3.0 and the latest NuGet packages, and enabled TCP/IP connections to SQL Server running locally. I was able to get it to connect to the database and return values.
Next, I created a copy of the test database on my local SQL Server. This also worked, the Web API in the original question running in Docker connected and returned data. I then changed the connection string to point back to the test SQL Server and the process hangs in the same spot with no error. Next, I tested it with the connection still pointed to the test SQL Server but running in IIS Express rather than Docker. Again, everything worked as expected.
I then tried running the previous release docker image which uses .NET Core 2.2, and it also returned data from the test SQL Server.
What could be the reason that I can not connect via IP to the test SQL Server using .NET Core 3.0 in Docker when all other combinations work just fine.
------Update 2----- I created the necessary database for my new simple test Web API project on the Test SQL Server, and changed the simple Web API project connection string. This new, clean, simple, .NET Core 3 project also did not connect to the Test SQL Server when running as Docker, but worked fine when running on IIS Express. It also worked fine when running in Docker but connecting to my local DB by IP.
Something has changed with .NET Core 3 in Docker that is stopping it from connecting to the external database server. Anybody have any ideas on what I need to do to resolve this?
--UPDATE 3 ----- Thanks to MATT! After reading Matt's response, I wasn't able to get the RUN commands to work within the docker file, but changing my base image to bionic did work. I have also been working with Microsoft support who also pointed me to the link that Matt provided. Maybe I just didn't place the RUN commands in the right location, so if anyone can provide a sample docker file using the RUN commands to resolve this issue, I would be grateful. Here is an updated docker file from a simple test project:
FROM mcr.microsoft.com/dotnet/core/aspnet:3.0-bionic AS base
WORKDIR /app
EXPOSE 80
FROM mcr.microsoft.com/dotnet/core/sdk:3.0-buster 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/build
FROM build AS publish
RUN dotnet publish "WebApplication1.csproj" -c Release -o /app/publish
FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "WebApplication1.dll"]
---Final Update -----
I tried the RUN commands in the docker file again, but got it right this time. Here is that version of the docker file.
FROM mcr.microsoft.com/dotnet/core/aspnet:3.0-buster-slim AS base
WORKDIR /app
RUN sed -i 's/DEFAULT@SECLEVEL=2/DEFAULT@SECLEVEL=1/g' /etc/ssl/openssl.cnf
RUN sed -i 's/DEFAULT@SECLEVEL=2/DEFAULT@SECLEVEL=1/g' /usr/lib/ssl/openssl.cnf
EXPOSE 80
FROM mcr.microsoft.com/dotnet/core/sdk:3.0-buster 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/build
FROM build AS publish
RUN dotnet publish "WebApplication1.csproj" -c Release -o /app/publish
FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "WebApplication1.dll"]
I believe the issue you're running into is documented here: https://github.com/dotnet/SqlClient/issues/222. As you said, something did change with .NET Core 3 because those Docker images are based on Debian Buster by default. Buster is configured to use 1.2 as the minimum TLS protocol, a change from the previous version (see https://www.debian.org/releases/stable/amd64/release-notes/ch-information.en.html#openssl-defaults).
This can be temporarily fixed by adding the following to the Dockerfile:
RUN sed -i 's/MinProtocol = TLSv1.2/MinProtocol = TLSv1/g' /etc/ssl/openssl.cnf
RUN sed -i 's/MinProtocol = TLSv1.2/MinProtocol = TLSv1/g' /usr/lib/ssl/openssl.cnf
This is not a great solution because it is essentially downgrading the version of TLS. The better long-term solution is to enable TLS 1.2 on the SQL Server (see https://support.microsoft.com/en-us/help/3135244/tls-1-2-support-for-microsoft-sql-server).