I am trying to run my application in docker while also creating a SQL Server.
It does not seem to connect to my SQL Server and I get the following error:
Unhandled exception. 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)
This is how my docker-compose file looks like.
version: '3.7'
services:
musicapi:
build:
context: .
ports:
- 80:80
environment:
Authentication:Enabled: 'true'
restart: always
depends_on:
- testdb
testdb:
image: mcr.microsoft.com/mssql/server:2017-latest
ports:
- "1433:1433"
environment:
TZ: Europe/Amsterdam
ACCEPT_EULA: "y"
SA_PASSWORD: Password01
volumes:
- mssql_data:/var/opt/mssql/data
restart: always
volumes:
mssql_data:
And my Dockerfile:
FROM mcr.microsoft.com/dotnet/aspnet:6.0-alpine AS base
WORKDIR /app
EXPOSE 80
FROM mcr.microsoft.com/dotnet/sdk:6.0 as build
WORKDIR /src
COPY . .
RUN dotnet restore
RUN dotnet build -c Release
RUN dotnet publish -c Release -o ./out
FROM base AS final
WORKDIR /app
COPY --from=build /src/out .
# The following 2 lines are required for solving:
# "Globalization Invariant Mode is not supported" error.
RUN apk add --no-cache icu-libs
ENV DOTNET_SYSTEM_GLOBALIZATION_INVARIANT=false
ENTRYPOINT ["dotnet", "Test.Api.dll"]
My connection string looks like this:
"ConnectionStrings":
{
"DefaultConnection":
"Server=localhost,1433;Database=test.db;User ID=sa;Password=Password01;TrustServerCertificate=True;"
}
What am I doing wrong?
Each container is a separate network entity, so when your connection string specifies Server=localhost, that means that the database is in the same container as your application.
On the Docker network that docker-compose creates, the containers can talk to each other using the service names as the host names. In your case, the database container can be reached using the host name testdb.
So you connection string should be
Server=testdb,1433;Database=test.db;User ID=sa;Password=Password01;TrustServerCertificate=True;
Related
I have an asp.net webApi application and using redis stack as the main database. I was able to connect to the database and perform operations normally till I made a docker image from my application and tried to run it on docker. The application cannot connect to the redis stack even that I have changed "localhost" to the "container name" and set it as an environment variable in my docker-compose file. Here is my code to connect and my docker-compose file for reference.
Connection to Redis Stack Code (Using Redis OM Package):
builder.Services.AddSingleton(new RedisConnectionProvider(builder.Configuration[Environment.GetEnvironmentVariable("REDIS_CONNECTION_STRING", EnvironmentVariableTarget.Process)]));
builder.Services.AddHostedService<IndexCreationService>();
Dockerfile
FROM mcr.microsoft.com/dotnet/aspnet:6.0 AS base
WORKDIR /app
EXPOSE 80
EXPOSE 443
FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build
WORKDIR /src
COPY ["API/API.csproj", "API/"]
COPY ["Core/Core.csproj", "Core/"]
COPY ["Persistence/Persistence.csproj", "Persistence/"]
COPY ["Service/Service.csproj", "Service/"]
RUN dotnet restore "API/API.csproj"
COPY . .
WORKDIR "/src/API"
RUN dotnet build "API.csproj" -c Release -o /app/build
FROM build AS publish
RUN dotnet publish "API.csproj" -c Release -o /app/publish
FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "API.dll"]
Docker-compose.yaml
version: '3.7'
services:
redis:
image: redis/redis-stack
container_name: redis
volumes:
- db-data:/data/redis
ports:
- "6379:6379"
- "8001:8001"
restart: unless-stopped
networks:
- course-network
CourseService:
image: dexam/course-service
container_name: course-service
volumes:
- course-service-data:/data/course_service
ports:
- "443:443"
environment:
- REDIS_CONNECTION_STRING=redis://redis:6379
restart: unless-stopped
depends_on:
- "redis"
links:
- "redis"
networks:
- course-network
volumes:
db-data:
course-service-data:
networks:
course-network:
driver: bridge
The error message I get:
Unhandled exception. StackExchange.Redis.RedisConnectionException: It was not possible to connect to the redis server(s). Error connecting right now. To allow this multiplexer to continue retrying until it's able to connect, use abortConnect=false in your connection string or AbortOnConnectFail=false; in your code. at StackExchange.Redis.ConnectionMultiplexer.ConnectImpl(ConfigurationOptions configuration, TextWriter log) in //src/StackExchange.Redis/ConnectionMultiplexer.cs:line 1162
at StackExchange.Redis.ConnectionMultiplexer.Connect(ConfigurationOptions configuration, TextWriter log) in //src/StackExchange.Redis/ConnectionMultiplexer.cs:line 1028
at Redis.OM.RedisConnectionProvider..ctor(String connectionString)
at Program.$(String[] args) in /src/API/Program.cs:line 17
Can anyone spot the problem?
It looks like there's a bit of confusion in whether you're pulling your connection string out of your environment or configuration:
builder.Services.AddSingleton(new RedisConnectionProvider(builder.Configuration[Environment.GetEnvironmentVariable("REDIS_CONNECTION_STRING", EnvironmentVariableTarget.Process)]));
This line doesn't really make sense, you are trying to pull a configuration variable from your appsettings file whose name is the VALUE of your REDIS_CONNECTION_STRING environment variable (which you've set in the docker-compose as redis://redis:6379) - this is most likely coming up as an empty string and hence, failing to parse-correctly and connect - the default behavior when Redis OM encounters an empty string in the config is to connect to redis://localhost:6379, since there's no redis instance there it will fail like the way you've shown.
You're looking for 1 of two things
You want to pull the connection string out of the environment variable, if you change that line to the following, given your docker-compose file, this ought to just work
builder.Services.AddSingleton(new RedisConnectionProvider(Environment.GetEnvironmentVariable("REDIS_CONNECTION_STRING", EnvironmentVariableTarget.Process)));
You really do want to pull the connection string out of the configuration, this is valid, but you'll want to make sure that you are setting the connection string in your configuration before you build the image:
builder.Services.AddSingleton(new RedisConnectionProvider(builder.Configuration["REDIS_CONNECTION_STRING"]));
Both methods are valid, but they won't play nice together which is why you're getting a bit of heartburn here.
Currently I am doing a project with ASP.NET Core 5.0 and using EF (Entity Framework) with Docker containers which I am trying to connect to SQL Server, but for some reason when trying to migrate all of the changes to SQL it does not get the Connection String.
Stepping through on debug I found that the value was populated.
In this Image, the connectionString property does contain the connection string from my secrets.json file
This Image, I've been trying to run migrations but I get an error
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: 0 - No connection could be made because the target machine actively refused it.
This is my docker file that was generated with my project
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 /src
COPY ["CreateRandomDatabaseEntries.API/CreateRandomDatabaseEntries.API.csproj", "CreateRandomDatabaseEntries.API/"]
RUN dotnet restore "CreateRandomDatabaseEntries.API/CreateRandomDatabaseEntries.API.csproj"
COPY . .
WORKDIR "/src/CreateRandomDatabaseEntries.API"
RUN dotnet build "CreateRandomDatabaseEntries.API.csproj" -c Release -o /app/build
FROM build AS publish
RUN dotnet publish "CreateRandomDatabaseEntries.API.csproj" -c Release -o /app/publish
FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "CreateRandomDatabaseEntries.API.dll"]
My project can communicate with my SQL Server with the creation of a docker compose project
version: '3.4'
services:
createrandomdatabaseentries.api:
image: ${DOCKER_REGISTRY-}createrandomdatabaseentriesapi
build:
context: .
dockerfile: CreateRandomDatabaseEntries.API/Dockerfile
ms-sql-server:
image: mcr.microsoft.com/mssql/server:2019-latest
environment:
ACCEPT_EULA: "Y"
SA_PASSWORD: "MyPassword"
volumes:
- ./data/mssql:/var/opt/mssql3
ports:
- '1433:1433'
expose:
- 1433
This Image shows the Connected Services are configured.
Trying to edit the SQL Server Database string and saving and then editing again does not retain value passed.
I am using Visual Studio 2019 Version 16.11.8 at the moment
The question:
How can I setup my package manager console to run the update-database or migrations to the docker container that I can experiment with more Database features through entity framework.
I have a container deploying a WEB API in ASP.NET Core trying to connect to the SQL Server database. I am running Windows 10 with Docker Desktop.
I can successfully connect to the Docker container with SQL Server from SQL Server Management Studio and my ASP.NET Core app (without container).
But when I run my ASP.NET Core inside the container, I've got an error:
fail: Microsoft.AspNetCore.Server.Kestrel[13]
Connection id "0HMCRFGHIEO1Q", Request id "0HMCRFGHIEO1Q:00000002": An unhandled exception was thrown by the application.
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)
at Microsoft.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInAction)
...
docker-compose for the SQL Server:
sqlserver:
image: mcr.microsoft.com/mssql/server:2019-latest
ports:
- 1433:1433
volumes:
- my-volume:/var/opt/mssql
environment:
SA_PASSWORD: "StrongPassword"
ACCEPT_EULA: "Y"
docker-compose for the WEB API:
web_api:
build:
dockerfile: WebApi/Dockerfile
ports:
- 5000:80
depends_on:
- sqlserver
Dockerfile for the WEB API:
FROM mcr.microsoft.com/dotnet/aspnet:5.0 AS base
WORKDIR /app
EXPOSE 80
FROM mcr.microsoft.com/dotnet/sdk:5.0 AS build
WORKDIR /src
COPY ["WebApi/WebApi.csproj", "WebApi/"]
RUN dotnet restore "WebApi/WebApi.csproj"
COPY . .
WORKDIR "/src/WebApi"
RUN dotnet build "WebApi.csproj" -c Release -o /app/build
FROM build AS publish
RUN dotnet publish "WebApi.csproj" -c Release -o /app/publish
FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "WebApi.dll"]
The connection string to SQL Server:
"ConnectionStrings": {
"SqlConnectionString": "Server=192.168.0.108,1433;Database=myDb;User Id=sa;Password=StrongPassword;"
}
By default, containers are connected to the bridge driver. To access sqlserver from ASP.NET, you must use the container name of the sqlserver in connection string. Like this.
"ConnectionStrings": {
"SqlConnectionString": "Server=sqlserver,1433;Database=myDb;User Id=sa;Password=StrongPassword;"
}
For more network details you can run the cmd command below.
docker network inspect bridge
Sorry, It was my fail:(
I just forgot that docker-compose up -d command doesn't rebuild Docker images.
I removed all images, and run the command again.
With the configurations above it works fine for me!
command for inspect bridge helped a lot:
docker network inspect bridge
i have Windows development machine to run Visual studio and docker desktop on it. so i tried to connect from one container with asp.net core app to another with ms sql running
i used host.docker.internal as Data source in my connection string and it worked fine
I have some issues trying to dockerize the web app I have written(ResumePostingService).
I have a Dockerfile for my application and one for my database as well as an Init sql file to create the database some tables and insert some data.
I also have a docker-compose file.
I have watched quite a few tutorials on the subject but every time I see something different and I get a different kind of error.
The latest error I am getting after the docker-compose up command when I go to localhost:8080 on my browser is the following:
InvalidOperationException: Unable to resolve service for type 'ResumePostingService.Models.ResumePostingServiceDatabaseContext' while attempting to activate 'ResumePostingService.Pages.LoginModel'.
Can anyone help me on what I am doing wrong?
Dockerfile(app)
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
# Build runtime image
FROM mcr.microsoft.com/dotnet/core/aspnet:3.1
WORKDIR /app
COPY --from=build-env /app/out .
ENTRYPOINT ["dotnet", "ResumePostingService.dll"]
docker-compose.yml
version: '3.8'
services:
db:
build: ./Db
volumes:
- data-volume:/var/lib/db
app:
build:
context: .
dockerfile: Dockerfile
ports:
- '8080:80'
depends_on:
- db
volumes:
data-volume:
Dockerfile(db)
FROM mysql:8.0.21
COPY *.sql /docker-entrypoint-initdb.d
ENV MYSQL_ROOT_PASSWORD myEpicPass
EXPOSE 3306
My connection string on the appsettings.json file
"Default": "server=127.0. 0.1;user=root;password=myEpicPass;port=3306;database=ResumePostingServiceDB"
The command I use to connect to the db inside Startup.cs
services.AddTransient(_ => new MySqlConnection(Configuration["ConnectionStrings:Default"]));
You need to change 127.0.0.1 to the service name (like in compose file), in your case it's db, so the connection string should look like this:
"Default": "server=db;user=root;password=myEpicPass;port=3306;database=ResumePostingServiceDB"
More information about networking in docker-compose: https://docs.docker.com/compose/networking/
I am quite new when it comes to RabbitMQ and I am working on a POC to run a C# solution that's using RabbitMQ in a docker container.
I managed to write the docker-compose.yml, dockerfile and run RabbitMQ. However, my solution cannot reach the RabbitMQ host. I think I might be missing some configuration but I cannnot tell what.
docker-compose.yml
version: '3.4'
services:
rabbit-sender:
image: rabbit-sender
container_name: rabbit-sender
build:
context: ../SenderRabitMQ
dockerfile: debug.Dockerfile
env_file: common.env
networks:
- rabbitPoc
expose:
- "80"
rabbit-receiver:
image: rabbit-receiver
container_name: rabbit-receiver
build:
context: ../ReceiveRabitMQ
dockerfile: debug.Dockerfile
env_file: common.env
networks:
- rabbitPoc
expose:
- "80"
rabbitmq:
image: rabbitmq:3.7.15
hostname: rabbitmq
build:
context: rabbit
dockerfile: debug.Dockerfile
ports:
- "5672:5672"
- "15672:15672"
volumes:
- "./enabled_plugins:/etc/rabbitmq/enabled_plugins"
debug.Dockerfile
Install RabbitMQ
FROM ubuntu:14.04.1
CMD docker pull dockerfile/rabbitmq
CMD docker build -t="dockerfile/rabbitmq" github.com/dockerfile/rabbitmq
FROM dotnet-core-sdk-2.1-debug:latest AS build-env
WORKDIR /app
# Copy csproj and restore as distinct layers
COPY SenderRabitMQ/SenderRabitMQ.csproj SenderRabitMQ/
RUN dotnet restore SenderRabitMQ/SenderRabitMQ.csproj
# Copy everything else and build
COPY ./ ./
RUN dotnet publish SenderRabitMQ/SenderRabitMQ.csproj -c Debug -o out --no-restore
# Build runtime image
FROM dotnet-core-aspnet-2.1-debug:latest
WORKDIR /app
COPY --from=build-env /app/SenderRabitMQ/out .
ENTRYPOINT ["dotnet", "SenderRabitMQ.dll"]
RUN command
docker run --hostname myrabbit rabbitmq:3
Connecting to RabbitMQ
var factory = new ConnectionFactory() { HostName = "myrabbit:5672" , DispatchConsumersAsync = true };
This is the error received when running the RabbitSender that's supposed to post a message to the queue.
rabbit-sender | Unhandled Exception:
RabbitMQ.Client.Exceptions.BrokerUnreachableException: None of the
specified endpoints were reachable ---> System.AggregateException:
One or more errors occurred. (Connection failed) --->
RabbitMQ.Client.Exceptions.ConnectFailureException: Connection
failed --->
System.Net.Internals.SocketExceptionFactory+ExtendedSocketException:
Connection refused 127.0.0.1:5672
Your docker compose sets the RabbitMQ service host name to be rabbitmq and not myrabbit (which is what you're trying to connect to). Try this instead:
var factory = new ConnectionFactory() { HostName = "rabbitmq", port = 5672 , DispatchConsumersAsync = true };
You also will need the Dockerfile rabbitmq section to be on the same network as the other services:
rabbitmq:
image: rabbitmq:3.7.15
hostname: rabbitmq
build:
context: rabbit
dockerfile: debug.Dockerfile
ports:
- "5672:5672"
- "15672:15672"
networks:
- rabbitPoc
volumes:
- "./enabled_plugins:/etc/rabbitmq/enabled_plugins"
Hope that helps!
You should use
HostName = "http://host.docker.internal:5672"
or
HostName = "host.docker.internal:5672"
instead of
HostName = "myrabbit:5672"
The reason is:
The host has a changing IP address (or none if you have no network
access). From 18.03 onwards our recommendation is to connect to the
special DNS name host.docker.internal, which resolves to the internal
IP address used by the host. This is for development purpose and will
not work in a production environment outside of Docker Desktop for
Windows.
https://docs.docker.com/docker-for-windows/networking/
In docker container,the place where you are making a connection to locally setup rabbitmq, you need to give the host as following
host.docker.internal
It will work.