代码之家  ›  专栏  ›  技术社区  ›  eldios1981

Docker ASP.NET核心容器在MySQL容器之后启动

  •  1
  • eldios1981  · 技术社区  · 6 年前

    我有一个带asp.net内核的docker容器和一个带mysql的容器。现在我需要等待asp.net核心容器,因为mysql容器已经准备好了(两个容器都是从docker compose.yml开始的)。

    有点像 https://github.com/jwilder/dockerize ,wait-for-it.sh或wait-for似乎不适用于ASP.NET核心容器。

    有人知道怎么解决这个问题吗?

    更新

    这是我的档案:

    FROM microsoft/aspnetcore-build:2.0 AS build-env
    WORKDIR /app
    
    # Copy csproj and restore as distinct layers
    COPY *.csproj ./
    RUN dotnet restore test.csproj
    
    # Copy everything else and build
    COPY . ./
    RUN dotnet publish -c Release -o out test.csproj
    
    
    
    # Build runtime image
    FROM microsoft/aspnetcore:2.0
    WORKDIR /app
    COPY ./entrypoint.sh ./app/
    RUN chmod +x ./app/entrypoint.sh
    CMD /bin/bash ./app/entrypoint.sh
    
    COPY --from=build-env /app/out .
    ENTRYPOINT ["dotnet", "test.dll"]
    

    这是我的入口点.sh:

    #!/bin/bash
    
    set -e
    run_cmd="dotnet run --server.urls http://*:80"
    
    until dotnet ef database update; do
    >&2 echo "SQL Server is starting up"
    sleep 1
    done
    
    >&2 echo "SQL Server is up - executing command"
    exec $run_cmd
    

    如果我用docker compose启动容器,就会得到错误消息:

    Unhandled Exception: System.FormatException: Value for switch '/app/entrypoint.sh' is missing.
    test          |    at Microsoft.Extensions.Configuration.CommandLine.CommandLineConfigurationProvider.Load()
    test          |    at Microsoft.Extensions.Configuration.ConfigurationRoot..ctor(IList`1 providers)
    test          |    at Microsoft.Extensions.Configuration.ConfigurationBuilder.Build()
    test          |    at Microsoft.AspNetCore.Hosting.WebHostBuilder.BuildCommonServices(AggregateException& hostingStartupErrors)
    test          |    at Microsoft.AspNetCore.Hosting.WebHostBuilder.Build()
    test          |    at test.Program.Main(String[] args) in /app/Program.cs:line 19
    

    如何将entrypoint和cmd/bin/bash./app/entrypoint.sh命令合并到一个文件中。我想我需要运行dotnet应用程序的entrypoint和entrypoint.sh的cmd来等待数据库容器。有没有办法让两个人都跑?

    2 回复  |  直到 6 年前
        1
  •  1
  •   BookOfGreg    6 年前

    https://docs.docker.com/compose/aspnet-mssql-compose/

    Docker文档列出了如何通过entrypoint.sh轮询数据库连接来让ASP.NET容器等待其数据库。

    #!/bin/bash
    
    set -e
    run_cmd="dotnet run --server.urls http://*:80"
    
    until dotnet ef database update; do
    >&2 echo "SQL Server is starting up"
    sleep 1
    done
    
    >&2 echo "SQL Server is up - executing command"
    exec $run_cmd
    
        2
  •  0
  •   Felix K.    5 年前

    而不是有一个推迟dotnet应用程序启动的脚本 从外面 您还可以检查并等待来自 在内部 您的dotnet应用程序。

    在下面,您可以看到 host.Run() 推迟到 waitForDb() 返回。

    在下面的示例中,我将检查sql db(在docker容器中运行)是否已经在名为 DbHealthChecker (实际上,整个方法 waitForDb 可以提供专门服务)。此健康检查程序使用 this stackoverflow thread 检查数据库是否正在运行。

    public class Program
    {
      public static void Main(string[] args)
      {
        var host = CreateWebHostBuilder(args).Build();
    
        Task.Run(async () => {
          using (var scope = host.Services.CreateScope())
          {
            var services = scope.ServiceProvider;
    
            await waitForDb(services);
    
            // ... other initializations, e.g. seeding db ...
          }
        }).Wait();
    
        host.Run();
      }
    
      private static async Task waitForDb(IServiceProvider services)
      {
        // create your own connection checker here
        // see https://stackoverflow.com/questions/19211082/testing-an-entity-framework-database-connection
    
        var healthChecker = services.GetRequiredService<DbHealthChecker>();
        var maxAttemps = 12;
        var delay = 5000;
    
        for (int i = 0; i < maxAttemps; i++) {
          if (healthChecker.isConnected()) {
            return;
          }
          await Task.Delay(delay);
        }
    
        // after a few attemps we give up
        throw new HttpException(503);
      }
    }