godockerfilechromedp

Golang chromedp dockerfile


I have a golang code that uses chromedp to connect to the user's local chrome here is my code:

package main

import (
    "context"
    "fmt"
    "log"
    "os"
    "time"

    "github.com/chromedp/chromedp"
    "github.com/gin-gonic/gin"
)

func main() {
    Api := gin.Default()

    Api.GET("api/jwt", func(c *gin.Context) {
        opts := append(chromedp.DefaultExecAllocatorOptions[:],
            chromedp.Flag("headless", false),
            chromedp.Flag("disable-gpu", true),
            chromedp.Flag("no-sandbox", true),
            chromedp.Flag("disable-dev-shm-usage", true),
            chromedp.Flag("disable-browser-side-navigation", true),
            chromedp.Flag("disable-infobars", true),
            chromedp.Flag("disable-extensions", true),
            chromedp.Flag("disable-notifications", true),
            chromedp.Flag("disable-default-apps", true),
            chromedp.Flag("disable-background-timer-throttling", true),
            chromedp.Flag("disable-backgrounding-occluded-windows", true),
            chromedp.Flag("disable-renderer-backgrounding", true),
        )

        allocCtx, cancel := chromedp.NewExecAllocator(context.Background(), opts...)
        defer cancel()

        ctx, cancel := chromedp.NewContext(allocCtx)
        defer cancel()

        var localStorageData string // Declaração da variável localStorageData

        err := chromedp.Run(ctx,
            chromedp.Navigate("https://csonlinetenant.b2clogin.com/csonlinetenant.onmicrosoft.com/oauth2/v2.0/authorize"),
            chromedp.Sleep(5*time.Second),
            chromedp.WaitVisible(`#fgh`),
            chromedp.SendKeys(`#fghfg`, "fghfgh"),
            chromedp.SendKeys(`#xcvxcv`, "xcxcvcxv"),
            chromedp.Click(`#thgh`, chromedp.ByID),
            chromedp.Sleep(5*time.Second),
            chromedp.Click(`dfgd`, chromedp.ByID),
            chromedp.Sleep(15*time.Second),
            chromedp.EvaluateAsDevTools(`localStorage.getItem('c')`, &localStorageData),
        )
        if err != nil {
            log.Printf("Error: %v", err)
            return
        }

        fmt.Println("Bearer", localStorageData)

        // Restante do código...

        c.JSON(200, gin.H{
            "Success": localStorageData,
        })
    })

    listenAddr := os.Getenv("LISTEN")

    if val, ok := os.LookupEnv("FUNCTIONS_CUSTOMHANDLER_PORT"); ok {
        listenAddr = ":" + val
    }
    if listenAddr == "" {
        listenAddr = ":8080"
    }

    Api.Run(listenAddr)
}

so i made a dockerfile which contains what i need for my clients to use this application (i installed chrome and built my golang in the image)

dockerfile:

FROM golang:1.20 AS build-stage

WORKDIR /app

# Instale as dependências do Chrome
RUN wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | apt-key add - \
    && echo "deb http://dl.google.com/linux/chrome/deb/ stable main" >> /etc/apt/sources.list.d/google.list
RUN apt-get update && apt-get -y install google-chrome-stable
RUN chrome &


COPY go.mod go.sum ./
RUN go mod download

COPY *.go ./

RUN CGO_ENABLED=0 GOOS=linux go build -o /dockergo

# Run the tests in the container
FROM build-stage AS run-test-stage
RUN go test -v ./...

# Deploy the application binary into a lean image
FROM gcr.io/distroless/base-debian11 AS build-release-stage

WORKDIR /

COPY --from=build-stage /dockergo /dockergo

EXPOSE 8080

USER nonroot:nonroot

ENTRYPOINT ["/dockergo"]

the image builds successfully and without a headache but when testing the docker image in my local I get this error:

 Error: exec: "google-chrome": executable file not found in $PATH

what does this error mean? that my chrome is not running? how can i run it?


Solution

  • The Chrome browser is installed in the build-stage only. It's not available in the final image that is created by the build-release-stage.

    I tried to install Chrome with this Dockerfile:

    # Deploy the application binary into a lean image
    FROM gcr.io/distroless/base-debian11 AS build-release-stage
    
    RUN wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | apt-key add - \
        && echo "deb http://dl.google.com/linux/chrome/deb/ stable main" >> /etc/apt/sources.list.d/google.list
    RUN apt-get update && apt-get -y install google-chrome-stable
    RUN chrome &
    

    But it failed with this message:

    ...
    Step 2/4 : RUN wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | apt-key add -     && echo "deb http://dl.google.com/linux/chrome/deb/ stable main" >> /etc/apt/sources.list.d/google.list
     ---> Running in 7596202a5684
    failed to create shim task: OCI runtime create failed: runc create failed: unable to start container process: exec: "/bin/sh": stat /bin/sh: no such file or directory: unknown
    

    I think you have to choose another base image on which it is easy to install Chrome. A better alternative is to use chromedp/headless-shell as the base image. This image contains Chrome's headless shell, which is very small. The demo Dockerfile below also shows compiling the test binary first and then run the test in the chromedp/headless-shell image:

    FROM golang:1.20.5-buster AS build-stage
    
    WORKDIR /app
    
    COPY go.mod go.sum ./
    RUN go mod download
    
    COPY . .
    
    RUN CGO_ENABLED=0 go build -o dockergo
    # Build the test binary
    RUN CGO_ENABLED=0 go test -c -o dockergo.test
    
    # Run the tests in the container
    FROM chromedp/headless-shell:114.0.5735.199 AS run-test-stage
    
    WORKDIR /app
    # Copy other files that is needed to run the test (testdata?).
    COPY . .
    COPY --from=build-stage /app/dockergo.test ./dockergo.test
    RUN /app/dockergo.test -test.v
    
    # Deploy the application binary into a lean image
    FROM chromedp/headless-shell:114.0.5735.199 AS build-release-stage
    
    COPY --from=build-stage /app/dockergo /dockergo
    
    EXPOSE 8080
    
    ENTRYPOINT ["/dockergo"]