Загрузка контейнера Docker в gcp cloud-run с основным приложением web api не работает - PullRequest
2 голосов
/ 13 апреля 2019

Попытка загрузить образ докера с помощью проекта dotnet core webapi.

Требование запуска в облаке заключается в том, что он прослушивает порт 8080.

Я верю, что я делаю это, но когда ясоздайте облачную службу после отправки в реестр контейнеров. GCP возвращается с:

"Не удалось запустить контейнер. Не удалось запустить и затем прослушать порт, определенный переменной среды PORT. Журналы для этой ревизии могут содержатьбольше информации. "

Локально у меня есть прослушивание kestrel на 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 FILE

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();

        }

Ответы [ 2 ]

1 голос
/ 16 апреля 2019

У меня сработало следующее решение:

В 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 голосов
/ 24 мая 2019

Ответ 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, который он пытался развернуть, имел старый идентификатор образа. Поэтому для развертывания в Registry Container, а затем для 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 tools и сконфигурировали Docker, введя gcloud auth login, gcloud config set project <your project ID here>, gcloud auth configure-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

Вам нужен параметр "region", потому что на момент написания этого документа Cloud Run доступен только в us-central1.

Для того, чтобы наш проект .NET Core 3.0 был правильно собран и запущен, нам также пришлось изменить Dockerfile. Нам потребовалось много времени, чтобы понять это, так что, надеюсь, мы сэкономили вам немного времени здесь. Используйте его в качестве справочного материала и сравните его с визуальной студией Dockerfile, созданной для вас, добавив соответствующие фрагменты. Вот наш 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 Cloud Storage из нашего контейнера, чтобы мы также «внедрили» файл JSON служебной учетной записи, который мы сохранили в папке ./keys/ (если вы это сделаете, не забудьте добавить эту папку в .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" .

Вы можете следовать той же схеме, чтобы вводить и другие переменные окружения. В любом случае, надеюсь, что это поможет вам решить сбивающую с толку ошибку «Не удалось запустить контейнер».

...