My SQL Server databases are running fine as Docker containers and I am able to connect in SSMS, however when my web app attempts to connect to these SQL Server instances it fails. See exception error below:
EPiServer.Framework.Initialization.InitializationEngine[0]
Initialize action failed for 'Initialize on class EPiServer.Data.DataInitialization, EPiServer.Data, Version=12.4.2.0, Culture=neutral, PublicKeyToken=- - - -'
Microsoft.Data.SqlClient.SqlException (0x80131904): A network-related or instance-specific error occurred while establishing a connection to SQL Server. The server was not found or was not accessible. Verify that the instance name is correct and that SQL Server is configured to allow remote connections. (provider: TCP Provider, error: 40 - Could not open a connection to SQL Server: Could not open a connection to SQL Server)
You can see my docker-compose
file below:
version: "3.9"
services:
sql-commerce:
container_name: "sql-commerce"
image: mcr.microsoft.com/azure-sql-edge
environment:
- ACCEPT_EULA=Y
- SA_PASSWORD=Passw0rd123!
- DB_NAME=commerce
ports:
- '1433:1433'
volumes:
- ./databases_project/files/data/commerce:/var/opt/mssql/data
sql-cms:
container_name: "sql-cms"
image: mcr.microsoft.com/azure-sql-edge
environment:
- ACCEPT_EULA=Y
- SA_PASSWORD=Passw0rd123!
- DB_NAME=cms
ports:
- '8080:1433'
volumes:
- ./databases_project/files/data/cms:/var/opt/mssql/data
web:
build: .
environment:
EcfSqlConnection: "sql-commerce"
EPiServerDB: "sql-cms"
ports:
- '3080:80'
This then speaks to a Dockerfile
in the same level:
FROM mcr.microsoft.com/dotnet/aspnet:5.0 AS base
WORKDIR /app
EXPOSE 80
EXPOSE 443
FROM mcr.microsoft.com/dotnet/sdk:5.0 AS build
WORKDIR /ProjectName
COPY ["Applications/Website.Src/Website.Src.csproj", "Website.Src/"]
RUN dotnet restore "Website.Src/Website.Src.csproj" --source https://api.nuget.org/v3/index.json --source https://nuget.optimizely.com/feed/packages.svc/
COPY . .
WORKDIR "/ProjectName/Applications/Website.Src"
RUN dotnet build "Website.Src.csproj" -c Release -o /app/build
FROM build AS publish
RUN dotnet publish "Website.Src.csproj" -c Release -o /app/publish
FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "Website.Src.dll"]
My connection string looks like the following:
"ConnectionStrings": {
"EcfSqlConnection": "Server=localhost,1433;Database=projectCommerce;User Id=sa;Password=Passw0rd123!;MultipleActiveResultSets=True",
"EPiServerDB": "Server=localhost,8080;Database=projectCms;User Id=sa;Password=Passw0rd123!;MultipleActiveResultSets=True"
},
Any thoughts on where I am going wrong here?
Update
I have attempted to target the sql container names rather than local host in my connection string, however even that fails to connect.
"ConnectionStrings": {
"EcfSqlConnection": "Server=sql-commerce,1433;Database=projectCommerce;User Id=sa;Password=Passw0rd123!;MultipleActiveResultSets=True",
"EPiServerDB": "Server=sql-cms,8080;Database=projectCms;User Id=sa;Password=Passw0rd123!;MultipleActiveResultSets=True"
},
CodePudding user response:
In your docker-compose, each container acts as its own host. When you refer to localhost
in your connection string, the web container sees this as itself, not the host (docker) machine.
You can make things complicated in docker-compose by setting up different networks too, but by default, your containers will all be on the same network. I like to specify a host name for each container, like this:
services:
sql-commerce:
hostname: sql-commerce
container_name: sql-commerce
Then, you can use that name in your connection string.
You might also look at the difference between ports
and expose
if you don't want the sql services open to the host machine - expose
allows you to keep them inside the docker network only. Right now, I think you would need to specify port 1433
for both connections (internal to the docker network) where the second one is only listening on 8080
on the host machine.
CodePudding user response:
You cannot communicate between containers using localhost. Using localhost inside a container will only point to itself.
Docker has a DNS server built in and containers can connect between each other using the container name like you did, but your database names is still wrong in your example, according to your compose file they should be commerce and cms.
"ConnectionStrings": {
"EcfSqlConnection": "Server=sql-commerce,1433;Database=commerce;User Id=sa;Password=Passw0rd123!;MultipleActiveResultSets=True",
"EPiServerDB": "Server=sql-cms,8080;Database=cms;User Id=sa;Password=Passw0rd123!;MultipleActiveResultSets=True"
},