dockergonpmgoogle-app-engine

Install a NPM module in docker image and run it with golang app, using Google App Engine flex


I'm trying to install a NPM module in docker image and run it with golang app (flex), using Google App Engine.

main.go:

package main

import (
    "fmt"
    "os"
    "os/exec"
)

func main() {
    cmd := exec.Command("rettiwt", "help")
    output, err := cmd.CombinedOutput()
    if err != nil {
        // fmt.Println("Error:", err)
        if err.Error() == "exec: \"rettiwt\": executable file not found in $PATH" {
            // Print $PATH
            fmt.Println("PATH:", os.Getenv("PATH"))
            // Print the contents of /usr/local/bin
            files, err := os.ReadDir("/usr/local/bin")
            if err != nil {
                panic(err)
            }
            fmt.Println("Contents of /usr/local/bin:", files)
        }
        panic(err)
    }
    fmt.Println("Output:", string(output))
}

Dockerfile:

FROM golang:1.22

RUN apt-get update && apt-get install -y nodejs npm

RUN npm install -g rettiwt-api

ENV PATH="/usr/local/bin:$PATH"

WORKDIR /app

COPY . .

RUN go build -o app

CMD ["./app"]

app.yaml:

runtime: go
env: flex
service: rettiwt
manual_scaling:
  instances: 1
runtime_config:
  operating_system: "ubuntu22"
  runtime_version: "1.22"

And I'm getting the following errors from gcloud app deploy command:

...
Updating service [rettiwt] (this may take several minutes)...failed.
ERROR: (gcloud.app.deploy) Error Response: [9] An internal error occurred while processing task /app-engine-flex/flex_await_healthy/flex_await_healthy>2024-11-05T23:50:55.210Z5706.xa.0: PATH: /layers/google.go.build/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
Contents of /usr/local/bin: []
panic: exec: "rettiwt": executable file not found in $PATH

goroutine 1 [running]:
main.main()
    /workspace/main.go:24 +0x116

According to the output, it seems like $PATH is fine, but /usr/local/bin is empty.

When I try building docker image locally:

docker build -t my-rettiwt-app .
docker run -it my-rettiwt-app rettiwt help

It works perfectly fine, and rettiwt is indeed in /usr/local/bin:

docker > ls -la /usr/local/bin                      
total 12
drwxr-xr-x 1 root root 4096 Oct 31 05:30 .
drwxr-xr-x 1 root root 4096 Sep 28 01:34 ..
lrwxrwxrwx 1 root root   43 Oct 31 05:30 rettiwt -> ../lib/node_modules/rettiwt-api/dist/cli.js

Is there some behavioral difference between Google App Engine's container & local container?


Solution

  • Figured it out by myself.

    The problem is that, in app.yaml, runtime: go will use a pre-built image, instead of the provided Dockerfile.

    So, the solution will simply be:

    runtime: custom
    

    Just note: To use custom runtime, you have to specify flex environment (env: flex).