我有这个合成文件:

version: "3"
services:
  app:
    build: .
    ports:
      - 8080:8080
    volumes:
      - "./:/src"
    healthcheck:
      test: ["CMD-SHELL", "curl -f http://localhost:8080/fail-health-check || exit 1"]
      interval: 5s
      timeout: 5s
      retries: 1
    command: ["go", "run", "main.go"]

文档文件:

FROM golang:1.21 as builder

WORKDIR /src

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

当我运行Docker Compose时,应用程序的运行状况判断一直在运行.我希望容器退出,但出现启动容器失败的错误.

golang 码main.go

package main

import (
    "fmt"
    "log"

    "github.com/labstack/echo/v4"
    "github.com/labstack/echo/v4/middleware"
)

func main() {
  r := echo.New()
  r.Use(middleware.Logger())
  
  fmt.Println("start http server on port 8080")
  if err := r.Start(":8080"); err != nil {
    log.Fatal(err)
  }
}

在这里登录应用程序:

test_healthcheck_go_app-app-1  | {"time":"2023-11-14T04:08:42.450751594Z","id":"","remote_ip":"127.0.0.1","host":"localhost:8080","method":"GET","uri":"/fail-health-check","user_agent":"curl/7.88.1","status":404,"error":"code=404, message=Not Found","latency":26375,"latency_human":"26.375µs","bytes_in":0,"bytes_out":24}

docker ps个yields

CONTAINER ID   IMAGE                         COMMAND            CREATED          STATUS                      PORTS                    NAMES
ff389f13ab1d   test_healthcheck_go_app-app   "go run main.go"   48 seconds ago   Up 46 seconds (unhealthy)   0.0.0.0:8080->8080/tcp   test_healthcheck_go_app-app-1

推荐答案

我希望容器退出,但出现启动容器失败的错误.

  1. 您的应用程序不知道它是在容器中运行的.
  2. 您的主进程(go run main.go)正在作为PID 1运行,您需要停止它才能退出容器,并且它是受保护的.

了解这两个事实后,您有几种可能性:

  1. 将坞站CLI安装在容器内.然后将您的坞站套接字映射到您的容器中并运行docker stop.将套接字映射到容器中意味着存在安全问题--请谨慎操作.

  2. 运行类似于ps -afx | grep go | awk '{print $1}' | xargs kill -9(kudos到this answer)的东西,即在您的healthcheck中,它可能看起来像curl -f http://localhost:8080/fail-health-check || (ps -afx | grep go | awk '{print $1}' | xargs kill -9)

  3. 但在我看来,你真正想要的是一个容器编排系统,就像Kubernetes一样.这可能是一种矫枉过正的建议,也可能不是.这取决于你对你的项目的计划.无论如何,它将帮助您更有力地管理您的运行容器.

如果您想产生错误,这取决于您使用的日志(log)驱动程序.使用syslog驱动程序,Docker容器将日志(log)写入/var/log/syslog.所以在退出之前,你可能想要echo "Error text"/var/log/syslog.

Go相关问答推荐

Go汇编器命名为Constants

使用Gorm创建自定义连接表

GORM没有从 struct 创建完整的表,如何修复?

创建使用逗号而不是加号分隔OU的CSR

通过渠道和goroutines增值1000倍

确定果朗CSV行中的字节数

如何在 zap 记录器库中使用自定义时间函数

如何创建在responseWriter.Write 上返回错误的http.ResponseWriter 模拟实例?

Golang Fiber Render - 将数据发送到多个布局

如何测试光纤参数

尽管存在 WaitGroup,Goroutines 似乎被打断了

Golang代码判断第一个词是否可以从第二个词形成

确保 Go 1.20 编译时的严格可比性?

有没有什么方法可以在不使用 if/else 的情况下在 Golang 中处理 nil 指针?

不能在 *gorm.db 而不是 gorm.db 上使用 WithContext(ctx) 方法

在 Golang 中,如何将接口作为泛型类型与 nil 进行比较?

Golang SSH客户端错误无法验证,try 的方法[无公钥],没有支持的方法

Go 导入范围查找 protobuf 类型

gopls 为 github.com/Shopify/sarama 返回错误gopls: no packages returned: packages.Load error

如何断言类型是指向golang中接口的指针