Search code examples
google-app-enginedeploymentgcloud

Gcloud app deploy - problems with .net HelloWorld


I am on the learning curve for gcloud app deploy. I have been struggling with running the .net HelloWorld example code from this location:

https://github.com/GoogleCloudPlatform/dotnet-docs-samples/tree/master/appengine/flexible/HelloWorld

The example runs fine on a desktop when I start it with Visual Studio. But, I can't get past the step of running using "gcloud app deploy" from a cmd window. Below are details of two runs, first as an out-of-the-box, and second as after adding a doocker file.

Is anyone else able to run the HelloWorld example as is with the current version of gcloud sdk?

Thanks for your help,

Bob

Here is the gcloud version info:

gcloud --version
Google Cloud SDK 299.0.0
bq 2.0.58
core 2020.06.26
gsutil 4.51

RUN 1

Here is the tail end of the gcloud output after a fresh install of gcloud sdk, and a fresh clone of /dotnet-docs-samples/...

...
Step #0: Status: Downloaded newer image for gcr.io/gcp-runtimes/aspnetcorebuild@sha256:f5552a5efdaf278a3124ea10fd1c9636b09fc9f98f9e620cbd71279797576b3f
Step #0: gcr.io/gcp-runtimes/aspnetcorebuild@sha256:f5552a5efdaf278a3124ea10fd1c9636b09fc9f98f9e620cbd71279797576b3f
Step #0: No .deps.json file found for the app
Finished Step #0
ERROR
ERROR: build step 0 "gcr.io/gcp-runtimes/aspnetcorebuild@sha256:f5552a5efdaf278a3124ea10fd1c9636b09fc9f98f9e620cbd71279797576b3f" failed: step exited with non-zero status: 1
------------------------------------------------------------------------------------------------------------------------

ERROR: (gcloud.app.deploy) Cloud build failed. Check logs at https://console.cloud.google.com/cloud-build/builds/44677e0d-0fcb-4460-907b-835cbf621f5e?project=704308180369 Failure status: UNKNOWN: Error Response: [2] Build failed; check build logs for details

RUN 2

After some searching around, I found a suggestion to switch to using a custom runtime, and a docker file. So I made two changes, one in the app.yaml file, and adding the docker file.

Here is the app.yaml file.

runtime: custom
env: flex

# This sample incurs costs to run on the App Engine flexible environment. 
# The settings below are to reduce costs during testing and are not appropriate
# for production use. For more information, see:
# https://cloud.google.com/appengine/docs/flexible/python/configuring-your-app-with-app-yaml
manual_scaling:
  instances: 1
resources:
  cpu: 1
  memory_gb: 4
  disk_size_gb: 10

env_variables:
  # The __ in My__Greeting will be translated to a : by ASP.NET.
  My__Greeting: Hello AppEngine!

readiness_check:
  app_start_timeout_sec: 600


Here is the Dockerfile. The file came from this location:

https://github.com/dotnet/dotnet-docker/blob/50e95cd9af6458ce0db21e6ec952e29c3ee1fadf/2.1/aspnet/alpine3.10/amd64/Dockerfile
ARG REPO=mcr.microsoft.com/dotnet/core/runtime-deps
FROM $REPO:2.1-alpine3.10

# Install ASP.NET Core
ENV ASPNETCORE_VERSION 2.1.15

RUN wget -O aspnetcore.tar.gz https://dotnetcli.azureedge.net/dotnet/aspnetcore/Runtime/$ASPNETCORE_VERSION/aspnetcore-runtime-$ASPNETCORE_VERSION-linux-musl-x64.tar.gz \
    && aspnetcore_sha512='4a6ab78abc08c3e02c948de0af5fd324269785adad1b4e17bb849025ab280b7b8216cb48da5d480270cf3d596b342cedd4dc77eeaae82151fea44816e3856c69' \
    && echo "$aspnetcore_sha512  aspnetcore.tar.gz" | sha512sum -c - \
    && mkdir -p /usr/share/dotnet \
    && tar -zxf aspnetcore.tar.gz -C /usr/share/dotnet \
    && rm aspnetcore.tar.gz \
    && ln -s /usr/share/dotnet/dotnet /usr/bin/dotnet


Here is the tail end of the run using the docker file.

...
  },
  "handlers": [
    {
      "script": {
        "scriptPath": "PLACEHOLDER"
      },
      "urlRegex": ".*"
    }
  ],
  "manualScaling": {
    "instances": 1
  },
  "resources": {
    "cpu": 1.0,
    "diskGb": 10,
    "memoryGb": 0.5
  },
  "runtime": "vm"
}"
DEBUG: Operation [apps/solitairesupport/operations/a41d48d9-6fc8-422b-84b6-1e18b3a70162] not complete. Waiting to retry.
Updating service [default] (this may take several minutes).../DEBUG: Operation [apps/solitairesupport/operations/a41d48d9-6fc8-422b-84b6-1e18b3a70162] not complete. Waiting to retry.
Updating service [default] (this may take several minutes)...-DEBUG: Operation [apps/solitairesupport/operations/a41d48d9-6fc8-422b-84b6-1e18b3a70162] not complete. Waiting to retry.

[MANY LINES REMOVED HERE]

Updating service [default] (this may take several minutes)...-DEBUG: Operation [apps/solitairesupport/operations/a41d48d9-6fc8-422b-84b6-1e18b3a70162] not complete. Waiting to retry.
Updating service [default] (this may take several minutes).../DEBUG: Operation [apps/solitairesupport/operations/a41d48d9-6fc8-422b-84b6-1e18b3a70162] complete. Result: {
    "done": true,
    "error": {
        "code": 9,
        "message": "\nApplication startup error! Code: APP_CONTAINER_CRASHED\n"
    },
    "metadata": {
        "@type": "type.googleapis.com/google.appengine.v1.OperationMetadataV1",
        "insertTime": "2020-07-03T17:06:36.191Z",
        "method": "google.appengine.v1.Versions.CreateVersion",
        "target": "apps/solitairesupport/services/default/versions/20200703t100554",
        "user": "xxxx@gmail.com"
    },
    "name": "apps/solitairesupport/operations/a41d48d9-6fc8-422b-84b6-1e18b3a70162"
}
Updating service [default] (this may take several minutes)...failed.
DEBUG: (gcloud.app.deploy) Error Response: [9]
Application startup error! Code: APP_CONTAINER_CRASHED
Traceback (most recent call last):
  File "...AppData\Local\Google\Cloud SDK\google-cloud-sdk\lib\googlecloudsdk\calliope\cli.py", line 983, in Execute
    resources = calliope_command.Run(cli=self, args=args)
  File "...\Local\Google\Cloud SDK\google-cloud-sdk\lib\googlecloudsdk\calliope\backend.py", line 807, in Run
    resources = command_instance.Run(args)
  File "...\Local\Google\Cloud SDK\google-cloud-sdk\lib\surface\app\deploy.py", line 117, in Run
    default_strategy=flex_image_build_option_default))
  File "...\Local\Google\Cloud SDK\google-cloud-sdk\lib\googlecloudsdk\command_lib\app\deploy_util.py", line 651, in RunDeploy
    ignore_file=args.ignore_file)
  File "...\Local\Google\Cloud SDK\google-cloud-sdk\lib\googlecloudsdk\command_lib\app\deploy_util.py", line 437, in Deploy
    extra_config_settings)
  File "...\Local\Google\Cloud SDK\google-cloud-sdk\lib\googlecloudsdk\api_lib\app\appengine_api_client.py", line 208, in DeployService
    poller=done_poller)
  File "...\Local\Google\Cloud SDK\google-cloud-sdk\lib\googlecloudsdk\api_lib\app\operations_util.py", line 314, in WaitForOperation
    sleep_ms=retry_interval)
  File "...\Local\Google\Cloud SDK\google-cloud-sdk\lib\googlecloudsdk\api_lib\util\waiter.py", line 264, in WaitFor
    sleep_ms, _StatusUpdate)
  File "...\Local\Google\Cloud SDK\google-cloud-sdk\lib\googlecloudsdk\api_lib\util\waiter.py", line 326, in PollUntilDone
    sleep_ms=sleep_ms)
  File "...\Local\Google\Cloud SDK\google-cloud-sdk\lib\googlecloudsdk\core\util\retry.py", line 229, in RetryOnResult
    if not should_retry(result, state):
  File "...\Local\Google\Cloud SDK\google-cloud-sdk\lib\googlecloudsdk\api_lib\util\waiter.py", line 320, in _IsNotDone
    return not poller.IsDone(operation)
  File "...\Local\Google\Cloud SDK\google-cloud-sdk\lib\googlecloudsdk\api_lib\app\operations_util.py", line 183, in IsDone
    encoding.MessageToPyValue(operation.error)))
googlecloudsdk.api_lib.app.operations_util.OperationError: Error Response: [9]
Application startup error! Code: APP_CONTAINER_CRASHED

ERROR: (gcloud.app.deploy) Error Response: [9]
Application startup error! Code: APP_CONTAINER_CRASHED


Solution

  • Ok, I'm familiar with Google Cloud Platform but not (now) as familiar with .NET.

    I'm using Linux (!) and Cloud Shell:

    gcloud alpha cloud-shell ssh
    

    I cloned the repo and made no other changes to it.

    I am able to run the project locally and test it:

    dotnet run
    

    and, from another shell:

    curl localhost:8080
    Hello World!
    

    NOTE it's unstated (perhaps obvious) but you must dotnet run (better dotnet publish) to create the ./bin/Debug directory.

    I created a project, set up billing, created an app engine app:

    PROJECT="[[YOUR-PROJECT-ID]]"
    BILLING="[[YOUR-BILLING-ID]]"
    REGION="[[YOUR-REGION]]"
    
    gcloud projects create ${PROJECT}
    gcloud beta billing projects link ${PROJECT} --billing-account=${BILLING}
    gcloud app create --project=${PROJECT} --region=${REGION}
    

    Then, per documentation:

    dotnet publish
    

    The contents of ./bin/Debug/netcoreapp2.1/publish:

         56 Jul  6 16:23 appsettings.json
        544 Jul  6 16:23 app.yaml
     223992 Jul  6 16:27 HelloWorld.deps.json
       8192 Jul  6 16:27 HelloWorld.dll
       1708 Jul  6 16:27 HelloWorld.pdb
        213 Jul  6 16:27 HelloWorld.runtimeconfig.json
        516 Jul  6 16:30 web.config
    

    NOTE contains app.yaml and HelloWorld.deps.json

    Then:

    gcloud app deploy ./bin/Debug/netcoreapp2.1/publish/app.yaml \
    --project=${PROJECT}
    

    And:

    ENDPOINT=$(\
      gcloud app describe \
      --project=${PROJECT} \
      --format="value(defaultHostname)")
    
    curl ${ENDPOINT}
    Hello AppEngine!
    

    Then, in the ./appengine/flexible/HelloWorld directory, I created Dockerfile:

    FROM mcr.microsoft.com/dotnet/core/sdk:2.1 AS builder
    WORKDIR /source
    
    COPY *.sln .
    COPY *.csproj .
    RUN dotnet restore
    
    COPY . .
    RUN dotnet publish -c release -o /app --no-restore
    
    FROM mcr.microsoft.com/dotnet/core/aspnet:2.1
    WORKDIR /app
    COPY --from=builder /app ./
    ENTRYPOINT ["dotnet", "HelloWorld.dll"]
    

    NOTE using this as a guide.

    NOTE I downgraded to 2.1 (rather than 3.1) to avoid a dotnet build error but that's due to my unfamiliarity with the runtime(s).

    I changed Program.cs to force the use of :8080:

    public static IWebHost BuildWebHost(string[] args) =>
        WebHost.CreateDefaultBuilder(args)
            .UseStartup<Startup>()
            .UseUrls("http://0.0.0.0:8080")
            .Build();
    }
    

    I revised app.yaml to use custom runtime:

    runtime: custom
    env: flex
    

    Then:

    gcloud app deploy --project=${PROJECT}
    

    Works.