除非从容器手动启动应用程序,否则 go 不会从容器写入文件

go does not write file from container unless application is manually started from container

我写了一个小的 golang 应用程序。它做了两件事:

此应用程序位于 docker 容器内。你可以看到的记录器是我的,只是一个练习。申请开始。如果我卷曲 http://localhost:5000 我可以看到“Ciao, mondo!”。但是记录器没有启动。奇怪的是,如果我进入容器,我 运行 手动应用程序。记录器开始记录。我认为这可能是权限问题。

这里是 docker-compose.

version: "3.9"
services:
    app:
        container_name: 'go_docker_app'
        build:
            dockerfile: Dockerfile
            context: .
        volumes:
            - ./logs:/app/logs
            - .:/opt/app/api
        ports:
            - "5000:5000"

这里是main.go文件

package main

import (
        "fmt"
        "net/http"
        "time"
        "github.com/sensorario/gol"
)

func main() {
    http.HandleFunc("/", HelloServer);
    http.ListenAndServe(":5000", nil);

    go forever()
    select{}
}

func HelloServer(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintf(w, "Ciao, mondo!");
}

func forever() {
    l := gol.NewCustomLogger("/app");
    for {
        l.Info(fmt.Sprintf("%v+\n", time.Now()));
        time.Sleep(time.Second)
    }
}

这里是 Dockerfile

我尝试了更多的解决方案。例如从 Dockerfile 创建 logger.log。我不认为是权限问题,因为我没有错误。

FROM golang:1.17-alpine
RUN mkdir -p /app/logs
ADD . /app
WORKDIR /app
RUN go get -d -v ./...
RUN go install -v ./...
RUN go build -o /application
EXPOSE 5000
RUN touch /app/logs/logger.log
CMD ["/application"]

这是由你的 goroutine 之前的 运行 ListenAndServe 引起的。 go forever()从不执行,所以不会输出任何日志文件。

The strange thing is that if I go into the container, and I run the application by hand. The logger start to log.

我假设您在 运行 容器上执行,其中您的应用程序的一个实例已经 运行 所以 Port 5000 已经被占用。您没有任何错误处理,因此它会跳过它并转到 forever() 函数。不需要空 select{},因为 ListenAndServe 会“阻止”程序:很好的解释

func main() {

    go forever()
    http.HandleFunc("/", HelloServer);

    // added error validating
    err := http.ListenAndServe(":5000", nil);
    log.Fatal(err)

    // or shorter version
    // log.Fatal(http.ListenAndServe(":5000", nil))

}