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

I want to be able to restart a golang docker file on failure to connect to rabbitmq as outined here: (Docker Compose wait for container X before starting Y see answer by: svenhornberg). Unfortunately my golang container will exit but never restart and I don't know why.

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 file:

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" ]

Here is my golang code:

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

And here is my terminal output (golang never restarts after rabbit called):

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

I'm very confused on how to get this to work. What am I doing wrong?

EDIT:

The exec.Command was incorrectly implemented, however os.Exit(1), log.Fatal, and log.Panic exit the container, but the container does not restart. Still confused.

douan4359
douan4359 啊,我看到了注意:在以(版本3)撰写文件以群集模式部署堆栈时,将忽略此选项。请改用restart_policy。我认为这种情况不适用。
一年多之前 回复
dongmao3131
dongmao3131 我不确定我是否理解这个问题。我使用docker-composeup--build,我的每个容器都带有标签,如您在上面看到的那样,并带有restart:always。
一年多之前 回复
duai0935
duai0935 您究竟如何调用docker-compose?(某些调用会导致重新启动:被忽略。)
一年多之前 回复
dsfdsfsdf45489
dsfdsfsdf45489 我更新了帖子。
一年多之前 回复
dsyak22488
dsyak22488 永远不要忽略错误。您的exec.Command调用错误
一年多之前 回复

1个回答

The Docker documentation says:

A restart policy only takes effect after a container starts successfully. In this case, starting successfully means that the container is up for at least 10 seconds and Docker has started monitoring it. This prevents a container which does not start at all from going into a restart loop.

Since the Go code you show exits basically immediately, it never meets this 10-second-minimum rule.

You can force Go to wait until the process has been alive a minimum of 10 seconds by using time.After somewhat like:

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

That is, create a channel that will receive an event after 10 seconds, and then actually receive it (immediately if it's happened, waiting if not) before main returns. From playing with https://play.golang.org/p/zGY5jFWbXyk, the one trick is that there needs to be some observable effect after receiving from the channel or else it doesn't actually wait.

dongqiu3254
dongqiu3254 感谢您的挖掘,可以重新启动,非常有用。 我认为最简单的方法是在主程序开始时测试与兔子uri的连接,并在10秒钟的错误睡眠中进行测试。 谢谢!
一年多之前 回复
Csdn user default icon
上传中...
上传图片
插入图片
抄袭、复制答案,以达到刷声望分或其他目的的行为,在CSDN问答是严格禁止的,一经发现立刻封号。是时候展现真正的技术了!
立即提问