Docker容器上传到gcp cloud-run,核心web api app无效

问题描述 投票:1回答:1

尝试使用dotnet核心webapi项目上传docker镜像。

云运行的一个要求是它正在侦听端口8080。

我相信我这样做但是当我在推送到容器注册表之后创建一个云运行服务时,GCP回来了:

“容器无法启动。无法启动,然后侦听PORT环境变量定义的端口。此修订的日志可能包含更多信息。”

本地我在8080上有红隼监听。也有8080上的容器列表。但是当我推动任何一个时,我得到了启动消息的失败......?有任何建议或尝试这样做?

@wlhee Here is the LOG from cloud run:

2019-04-13T05:24:53.462592ZHosting environment: Production
2019-04-13T05:24:53.462657ZContent root path: /app
2019-04-13T05:24:53.462678ZNow listening on: http://[::]:80
2019-04-13T05:24:53.462697ZApplication started. Press Ctrl+C to shut down.
2019-04-13T05:28:48.973934834ZContainer terminated by the container manager on signal 9.

"Container failed to start. Failed to start and then listen on the port defined by the PORT environment variable. Logs for this revision might contain more information."

~DOCKER文件

FROM mcr.microsoft.com/dotnet/core/aspnet:2.2-stretch-slim AS base
WORKDIR /app
ENV ASPNETCORE_URLS=http://+:8080
EXPOSE 8080

FROM mcr.microsoft.com/dotnet/core/sdk:2.2-stretch AS build
WORKDIR /src
COPY ["simplecore.csproj", "simplecore/"]
RUN dotnet restore "simplecore/simplecore.csproj"
COPY . .
WORKDIR "/src/simplecore"
RUN dotnet build "simplecore.csproj" -c Release -o /app

FROM build AS publish
RUN dotnet publish "simplecore.csproj" -c Release -o /app

FROM base AS final
WORKDIR /app
COPY --from=publish /app .
ENTRYPOINT ["dotnet", "simplecore.dll"]
~ HERE IS MY MAIN FROM CORE APP

public static void Main(string[] args)
        {
            //CreateWebHostBuilder(args).Build().Run();

            var host = new WebHostBuilder()
            .UseKestrel()
            .UseContentRoot(Directory.GetCurrentDirectory())
            //.UseIISIntegration()
            .UseStartup<Startup>()
            .UseUrls("http://0.0.0.0:8080/")
            .Build();

            host.Run();

        }
docker google-cloud-platform asp.net-core-webapi google-cloud-run
1个回答
1
投票

以下解决方案适合我:

在Dockerfile中修改行

FROM base AS final
WORKDIR /app
COPY --from=publish /app .
ENTRYPOINT ["dotnet", "simplecore.dll"]

通过添加ENV

FROM base AS final
ENV ASPNETCORE_URLS=http://*:${PORT}
WORKDIR /app
COPY --from=publish /app .
ENTRYPOINT ["dotnet", "simplecore.dll"]

添加运行状况控制器以侦听根路由:

[Route("/")]
[ApiController]
public class HealthController : ControllerBase
{

    [HttpGet]
    public ActionResult<IEnumerable<string>> Get()
    {
        return Ok();
    }
}

在Program.cs中配置Kestrel来侦听PORT环境变量:

    public static IWebHostBuilder CreateWebHostBuilder(string[] args)
    {
        var port = Environment.GetEnvironmentVariable("PORT");

        return WebHost.CreateDefaultBuilder(args)
            .UseStartup<Startup>()
            .UseKestrel()
            .ConfigureKestrel((context, options) =>
            {
                options.Listen(IPAddress.IPv6Any, Convert.ToInt32(port));
            });
    }

最后在Startup.cs中添加一个默认路由:

app.UseMvc(routes => 
{
    routes.MapRoute("default", "{controller=Health}/{action=Get}");
});

重建和部署


0
投票

IJB的答案是现实并且为我们工作,但在我们的例子中我们使用的是ASP.NET Core 3.0,因此我们必须稍微修改Program.cs:

public static IHostBuilder CreateHostBuilder(string[] args) =>
            Host.CreateDefaultBuilder(args)
                .ConfigureWebHostDefaults(webBuilder =>
                {
                    webBuilder.UseStartup<Startup>()
                        .ConfigureKestrel(options =>
                        {
                            var port = Convert.ToInt32(Environment.GetEnvironmentVariable("PORT") ?? "80");
                            options.Listen(IPAddress.Any, port);
                        });
                });
    }

我们不需要打电话给app.UseMvc(...)。我们确实需要添加一个HealthController,其中只有一个指向路径“/”的GET方法,如IJB的答案所示,下面重申了这一点。

[Route("/")]
    [ApiController]
    public class HealthController : ControllerBase
    {
        [HttpGet]
        public ActionResult<IEnumerable<string>> Get()
        {
            return Ok();
        }
    }

此外,这让我们难以忍受,如果您要部署到Cloud Run,gcloud beta run deploy不会推送Docker镜像,而是重用已部署的镜像。这让我们非常困惑,直到我们意识到它试图部署的Docker镜像有一个旧的图像ID。因此,要部署到Container Registry然后部署到Cloud Run,您需要执行以下操作:

  1. 构建Docker镜像:
docker image build -t my-web-api -t gcr.io/<your project ID here>/my-web-api -f Dockerfile .

您可以将上面的“my-web-api”重命名为您想要的任何内容。

  1. 推送Docker镜像(在此之前,请确保安装gcloud工具并通过键入gcloud auth logingcloud config set project <your project ID here>gcloud auth configure-docker配置Docker):
docker push gcr.io/<your project ID here>/my-web-api:latest

将上面的“my-web-api”替换为您在步骤#1中使用的内容。

  1. 部署到云运行:
gcloud beta run deploy --image gcr.io/<your project ID here>/my-web-api --region us-central1

您需要“区域”参数,因为在撰写本文时,Cloud Run仅在us-central1中可用。

为了使我们的.NET Core 3.0项目能够正确构建和运行,我们还必须修改Dockerfile。我们花了很长时间来解决这个问题,所以希望我们在这里节省了一些时间。使用它作为参考,并将它与为您生成的Dockerfile visual studio进行比较,添加相关部分。这是我们的Dockerfile的完整内容:

FROM mcr.microsoft.com/dotnet/core/aspnet:3.0-buster-slim AS base

# uncomment if you need to deploy a service account JSON file to access Google Cloud resources
#ARG GOOGLE_APPLICATION_CREDENTIALS_FILE
ARG ASPNETCORE_ENVIRONMENT

# uncomment if you need to deploy a service account JSON file
#ENV GOOGLE_APPLICATION_CREDENTIALS="/app/$GOOGLE_APPLICATION_CREDENTIALS_FILE"
ENV ASPNETCORE_ENVIRONMENT=$ASPNETCORE_ENVIRONMENT

# uncomment if you need to deploy a service account JSON file
#COPY "keys/$GOOGLE_APPLICATION_CREDENTIALS_FILE" "/app/"

WORKDIR /app
EXPOSE 80
EXPOSE 443

FROM mcr.microsoft.com/dotnet/core/sdk:3.0-buster AS build
WORKDIR /src
COPY ["<your project name>.csproj", "./"]
RUN dotnet restore "<your project name>.csproj"
COPY . .
WORKDIR "/src/<your project name>"
RUN dotnet build "<your project name>" -c Release -o /app

FROM build AS publish
RUN dotnet publish "<your project name>" -c Release -o /app --self-contained --runtime linux-x64

FROM base AS final
ENV ASPNETCORE_URLS=http://*:${PORT}
WORKDIR /app
COPY --from=publish /app .
ENTRYPOINT ["dotnet", "<your DLL file here>.dll"]

我们必须从容器连接到Google云端存储,因此我们还“注入”了存储在./keys/文件夹中的服务帐户JSON文件(如果这样做,请不要忘记将该文件夹添加到.gitignore或等效文件中) 。我们的构建服务器将根据环境注入正确的文件,如下所示:

docker image build -t my-web-api -t gcr.io/<project ID here>/my-web-api -f <project dir>/Dockerfile --build-arg GOOGLE_APPLICATION_CREDENTIALS_FILE="my-service-acccount.json" --build-arg ASPNETCORE_ENVIRONMENT="Development" .

您也可以按照相同的模式注入其他环境变量。无论如何,希望这可以帮助您解决令人困惑的“容器未能启动”错误。

© www.soinside.com 2019 - 2024. All rights reserved.