我希望能够在无法连接到Rabbitmq时重新启动golang docker文件,如以下所述:(Docker Compose wait for container X before starting Y参见答案:svenhornberg)。 不幸的是,我的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在调用Rabbit之后永远不会重新启动):
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 :(得分:4)
The Docker documentation says:
重新启动策略仅在容器成功启动后才生效。在这种情况下,成功启动意味着该容器已启动至少10秒钟,并且Docker已开始对其进行监视。这样可以防止根本无法启动的容器进入重启循环。
由于您显示的Go代码基本上会立即退出,因此它永远不会满足此至少10秒的规则。
您可以通过使用time.After来强迫Go等待至少10秒,直到该过程还存在:
ch := time.After(10 * time.Second)
defer (func() { fmt.Println("waiting"); <-ch; fmt.Println("waited") })()
也就是说,创建一个通道,该通道将在10秒后接收事件,然后在main
返回之前实际接收该事件(如果发生,立即接收,如果没有发生,则等待)。从玩https://play.golang.org/p/zGY5jFWbXyk开始,一个窍门是从频道接收到一些效果之后就需要观察到,否则它实际上并没有等待。