代码之家  ›  专栏  ›  技术社区  ›  Peter Weyand

Golang Docker容器未在Docker Compose中重新启动

  •  0
  • Peter Weyand  · 技术社区  · 5 年前

    我希望能够在连接到rabbitmq失败时重新启动golang docker文件,如下所示:( Docker Compose wait for container X before starting Y 见答案:斯文霍恩伯格)。 不幸的是,我的golang容器将退出,但永远不会重新启动,我不知道为什么。

    Docker compose:

    version: '3.3'
    services:
      mongo:
        image: 'mongo:3.4.1'
        container_name: 'datastore'
        ports:
          - '27017:27017'
      rabbitmq:
        restart: always
        tty: true
        image: rabbitmq:3.7-management-alpine
        hostname: "rabbit"
        ports:
          - "15672:15672" 
          - "5672:5672"
        labels:
          NAME: "rabbitmq"
        volumes:
          - ./rabbitmq-isolated.conf:/etc/rabbitmq/rabbitmq.config
        healthcheck:
          test: ["CMD", "curl", "-f", "http://localhost:15672"]
          interval: 3s
          timeout: 5s
          retries: 20
      api:
        restart: always
        tty: true
        container_name: 'api'
        build: '.'
        working_dir: /go/src/github.com/patientplatypus/project
        ports:
          - '8000:8000'
        volumes:
          - './:/go/src/github.com/patientplatypus/project'
          - './uploads:/uploads'
          - './scripts:/scripts'
          - './templates:/templates'
        depends_on:
          - "mongo"
          - "rabbitmq"
    

    Docker文件:

    FROM golang:latest
    
    WORKDIR /go/src/github.com/patientplatypus/project
    COPY . .
    
    RUN go get github.com/imroc/req
    <...more go gets...>
    RUN go get github.com/joho/godotenv
    
    EXPOSE 8000
    
    ENTRYPOINT  [ "fresh" ]
    

    这是我的golang代码:

    package main
    
    import (
        "fmt"
        "log"
        "os"
        "os/exec"
        "net/http"
    )
    
    func main() {
    
        fmt.Println("Golang server started")
        godotenv.Load()
        fmt.Println("now doing healthcheck on rabbit")
        exec.Command("docker-compose restart api")
        os.Exit(1)
      <...>
    

    这是我的终端输出(兔子呼叫后golang从未重新启动):

    api         | 23:23:00 app         | Golang server started
    api         | 23:23:00 app         | now doing healthcheck on rabbit
    rabbitmq_1  | 
    rabbitmq_1  |   ##  ##
    rabbitmq_1  |   ##  ##      RabbitMQ 3.7.11. Copyright (C) 2007-2019 Pivotal Software, Inc.
    rabbitmq_1  |   ##########  Licensed under the MPL.  See http://www.rabbitmq.com/
    rabbitmq_1  |   ######  ##
    rabbitmq_1  |   ##########  Logs: <stdout>
    <...more rabbit logging...>
    

    我很困惑如何让它发挥作用。我做错了什么?

    编辑:

    这个 exec.Command 然而,它的实施是错误的 os.Exit(1) , log.Fatal log.Panic 退出容器,但容器不会重新启动。还是很困惑。

    0 回复  |  直到 5 年前
        1
  •  5
  •   David Maze    5 年前

    The Docker documentation says:

    重新启动策略仅在容器成功启动后生效。在这种情况下,启动成功意味着容器已启动至少10秒,Docker已开始监控它。这可以防止根本没有启动的容器进入重启循环。

    由于您显示的Go代码基本上是立即退出的,因此它永远不会满足这个10秒的最小规则。

    您可以使用以下命令强制Go等待,直到进程处于活动状态至少10秒 time.After 有点像:

    ch := time.After(10 * time.Second)
    defer (func() { fmt.Println("waiting"); <-ch; fmt.Println("waited") })()
    

    也就是说,创建一个通道,在10秒后接收一个事件,然后在10秒前实际接收它(如果发生了,立即接收,如果没有,等待) main 返回。从玩 https://play.golang.org/p/zGY5jFWbXyk 一个技巧是,在接收到来自通道的信息后,需要有一些可观察的效果,否则它实际上不会等待。