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?
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
).