Home > Blockchain >  Connecting a Docker Web App to a SQL Server instance that is also running in Docker
Connecting a Docker Web App to a SQL Server instance that is also running in Docker

Time:05-04

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"
},
  • Related