繁体   English   中英

无法从 NET Core 2.2 Web API 连接到 docker sql server

[英]Can't connect to docker sql server from NET Core 2.2 Web API

在收集结合 docker 编写 .NET Core Web API 的知识时,我遇到了一个无法解决的错误。 我已经在互联网上进行了研究,但不知何故,提供的解决方案都不适合我。

我有一个名为Catalog.API的 Web 服务(类似于 Microsoft 的 eShopOnContainers 项目),其中有一个名为CatalogController的控制器。

这是控制器的代码:

using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Catalog.API.Models;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;

namespace Catalog.API.Controllers
{
    [ApiController]
    [Route("api/[controller]")]
    public class CatalogController : ControllerBase
    {
        private readonly CatalogItemContext _context;

        public CatalogController(CatalogItemContext context)
        {
            _context = context;
        }

        public async Task<List<CatalogItem>> GetItemsAsync()
        {
            var items = await _context.CatalogItems.Where(model => model.Id < 10).ToListAsync();
            return items;
        }
    }
}

如您所见,我只有一种方法可以从外部数据库中返回 id 小于 10 的所有项目。

数据库添加到Startup.cs

namespace Catalog.API
{
    public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddDbContext<CatalogItemContext>(builder =>
            {
                builder.UseSqlServer(Configuration.GetConnectionString("Default"));
            });

        services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            else
            {
                // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
                app.UseHsts();
            }

            app.UseHttpsRedirection();
            app.UseMvc();
        }
    }
}

appsettings.json看起来像这样:

{
  "Logging": {
    "LogLevel": {
      "Default": "Warning"
    }
  },
  "AllowedHosts": "*",
  "ConnectionStrings": {
    "Default": "Server=localhost,1433;Initial Catalog=Test.Services.CatalogDb;User Id=sa;Password=Pass@word" 
  }
}

为了构建这个 Web 服务,我创建了一个从docker-compose.yml调用docker-compose.yml

FROM mcr.microsoft.com/dotnet/core/aspnet:2.2 AS base
WORKDIR /app
EXPOSE 80

FROM mcr.microsoft.com/dotnet/core/sdk:2.2 AS build
WORKDIR /src

COPY src/Services/Catalog/Catalog.API/Catalog.API.csproj /src/csproj-files/

WORKDIR ./csproj-files
RUN dotnet restore

WORKDIR /src

COPY . .
WORKDIR /src/src/Services/Catalog/Catalog.API/
RUN dotnet publish -c Release -o /app

FROM build AS publish

FROM base as final
WORKDIR /app
COPY --from=publish /app .
ENTRYPOINT ["dotnet", "Catalog.API.dll"]

docker-compose.yml如下所示:

version: '3.4'

services:

  sqldata:
    ports:
      - 1433:1433
    image: mcr.microsoft.com/mssql/server:2017-latest-ubuntu
    environment:
      - ACCEPT_EULA=Y
      - SA_PASSWORD=Pass@word

  catalog.api:
    ports:
      - 80:80
    build:
      context: .
      dockerfile: src/Services/Catalog/Catalog.API/Dockerfile
    depends_on:
      - sqldata

如前所述,除了 Catalog.API Web 服务之外,我还在 docker 容器中运行 SQL Server 数据库。 出于开发目的,我使用 localhost 或我的机器 ip 作为主机地址( localhost192.168.2.101 )从 DataGrip 连接到此 SQL Server。 两种方式都可以正常工作,我可以在 DataGrip 内部建立连接而不会出现问题。

我的问题是我无法从我的CatalogController的 docker 容器内部连接到 SQL Server,在 localhost:80 上运行。 通常,当我调用localhost:80/api/catalog ,我应该从数据库中取出所有项目(请参阅开头的控制器),但不知何故,我收到此错误:

失败:Microsoft.EntityFrameworkCore.Database.Connection[20004]
使用与服务器 'localhost,1433' 上的数据库 'Test.Services.CatalogDb' 的连接时发生错误。
System.Data.SqlClient.SqlException (0x80131904):建立与 SQL Server 的连接时发生与网络相关或特定于实例的错误。 服务器未找到或无法访问。 验证实例名称是否正确以及 SQL Server 是否配置为允许远程连接。 (提供程序:TCP 提供程序,错误:40 - 无法打开与 SQL Server 的连接)

在 System.Data.SqlClient.SqlInternalConnectionTds..ctor(DbConnectionPoolIdentity identity, SqlConnectionString connectionOptions, SqlCredential credential, Object providerInfo, String newPassword, SecureString newSecurePassword, Boolean redirectedUserInstance, SqlConnectionString userConnectionOptions, SessionData reconnectSessionData, Boolean applyTransient accessTokenHandling)
在 System.Data.SqlClient.SqlConnectionFactory.CreateConnection(DbConnectionOptions options, DbConnectionPoolKey poolKey, Object poolGroupProviderInfo, DbConnectionPool pool, DbConnection owningConnection, DbConnectionOptions userOptions)
在 System.Data.ProviderBase.DbConnectionFactory.CreatePooledConnection(DbConnectionPool pool, DbConnection owningObject, DbConnectionOptions options, DbConnectionPoolKey poolKey, DbConnectionOptions userOptions)
在 System.Data.ProviderBase.DbConnectionPool.CreateObject(DbConnection owningObject, DbConnectionOptions userOptions, DbConnectionInternal oldConnection)
在 System.Data.ProviderBase.DbConnectionPool.UserCreateRequest(DbConnection owningObject, DbConnectionOptions userOptions, DbConnectionInternal oldConnection)
在 System.Data.ProviderBase.DbConnectionPool.TryGetConnection(DbConnection owningObject, UInt32 waitForMultipleObjectsTimeout, Boolean allowCreate, Boolean onlyOneCheckConnection, DbConnectionOptions userOptions, DbConnectionInternal& connection)
在 System.Data.ProviderBase.DbConnectionPool.WaitForPendingOpen()
--- 从上一个抛出异常的位置开始的堆栈跟踪结束 ---

在 Microsoft.EntityFrameworkCore.Storage.RelationalConnection.OpenDbConnectionAsync(Boolean errorsExpected, CancellationToken cancelationToken) ClientConnectionId:00000000-0000-0000-0000-000000000000

我已经尝试使用多个 ips(本地主机,我的机器 ip + docker inspect 中的 ip),但没有一个工作正常。

Server=192.168.2.101,1433;Initial Catalog=Test.Services.CatalogDb;User Id=sa;Password=Pass@word

我愿意接受一切可以解决我的问题的帮助。 提前致谢。

SQL Server 实例不在本地主机上。 在 Web 应用的上下文中,localhost 是运行 Web 应用的容器,它与 SQL Server 所在的容器不同。

使用 Docker Compose 时,服务名称以主机名结尾,这意味着您可以简单地连接到sqldata,1433

添加服务名称而不是 IP 有效,但是每当我使用“dotnet ef migrations add xyz”和“dotnet ef database update”迁移数据库时,我都会收到错误消息。 它说,找不到或无法访问服务器.. 所以现在我可以连接,但不能使用 dotnet ef。

主机名仅在运行 docker 容器的 vlan 内有效,这与您的台式机所在的 vlan 不同。要访问 SQL Server 容器,您必须将docker container exec到其中一个容器中并运行命令从那里( sqldata主机名将存在的地方)或者您必须使用容器的 IP 地址,您可以通过运行docker container ls来获取容器 id (guid),然后运行docker inspect {container id} IP 地址将在生成的 JSON 的NetworkSettings部分中。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM