簡體   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