我在这里使用rabbitmq和一个简单的python示例 和docker-compose一起。我的问题是我需要等待rabbitmq完全启动。从我搜索到目前为止,我不知道如何等待容器x(在我的case worker)直到y (rabbitmq)启动。

我发现了一篇他检查另一个主机是否在线的博客文章。 我还发现了这个docker命令:

等待 用法:docker wait CONTAINER[容器…] 阻塞直到容器停止,然后打印它的退出代码。

等着一个集装箱停下来也许不是我想要的,但如果 是否可以在docker-compose。yml中使用这个命令? 到目前为止,我的解决方案是等待几秒钟并检查端口,但这是实现这一点的方法吗?如果我不等待,就会得到一个错误。

docker-compose.yml

worker:
    build: myapp/.
    volumes:
    - myapp/.:/usr/src/app:ro

    links:
    - rabbitmq
rabbitmq:
    image: rabbitmq:3-management

Python hello sample (rabbit.py):

import pika
import time

import socket

pingcounter = 0
isreachable = False
while isreachable is False and pingcounter < 5:
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    try:
        s.connect(('rabbitmq', 5672))
        isreachable = True
    except socket.error as e:
        time.sleep(2)
        pingcounter += 1
    s.close()

if isreachable:
    connection = pika.BlockingConnection(pika.ConnectionParameters(
            host="rabbitmq"))
    channel = connection.channel()

    channel.queue_declare(queue='hello')

    channel.basic_publish(exchange='',
                          routing_key='hello',
                          body='Hello World!')
    print (" [x] Sent 'Hello World!'")
    connection.close()

Dockerfile for worker:

FROM python:2-onbuild
RUN ["pip", "install", "pika"]

CMD ["python","rabbit.py"]

2015年11月更新:

在程序中使用shell脚本或等待可能是一种解决方案。但是在看到这个问题后,我正在寻找docker/docker-compose本身的命令或功能。

他们提到了实现运行状况检查的解决方案,这可能是最佳选择。一个开放的tcp连接并不意味着你的服务已经准备好或可能保持准备状态。除此之外,我需要改变我的入口点在我的dockerfile。

因此,我希望通过docker-compose on board命令得到一个答案,如果他们完成了这个问题,就有希望出现这种情况。

2016年3月更新

有人提议提供一种内置的方法来确定容器是否“活”。因此,docker-compose在不久的将来可能会得到应用。

2016年6月更新

健康检查似乎将在1.12.0版本集成到docker中

2017年1月更新

我找到了一个docker-compose解决方案,见: Docker在启动Y之前撰写等待容器X


当前回答

使用restart: unless-stopped或restart: always可以解决这个问题。

如果工作容器在rabbitMQ还没有准备好时停止,它将被重新启动,直到它准备好。

其他回答

在Docker撰写文件的版本3中,您可以使用RESTART。

例如:

docker-compose.yml

worker:
    build: myapp/.
    volumes:
    - myapp/.:/usr/src/app:ro
    restart: on-failure
    depends_on:
    - rabbitmq
rabbitmq:
    image: rabbitmq:3-management

注意,我使用了depends_on而不是links,因为后者在版本3中已弃用。

尽管它可以工作,但它可能不是理想的解决方案,因为每次失败都要重新启动docker容器。

再看一下RESTART_POLICY。它允许您微调重启策略。

当你在生产环境中使用Compose时,最好使用restart策略:

指定像restart: always这样的重启策略以避免停机

最近他们添加了depends_on特性。

编辑:

从撰写版本2.1+到版本3,你可以使用depends_on结合healthcheck来实现这一点:

从文档中可以看出:

version: '2.1'
services:
  web:
    build: .
    depends_on:
      db:
        condition: service_healthy
      redis:
        condition: service_started
  redis:
    image: redis
  db:
    image: redis
    healthcheck:
      test: "exit 0"

2.1版本之前

您仍然可以使用depends_on,但是它只影响服务启动的顺序——如果它们在依赖的服务启动之前就准备好了,则不会影响服务。

它似乎至少需要1.6.0版本。

用法应该是这样的:

version: '2'
services:
  web:
    build: .
    depends_on:
      - db
      - redis
  redis:
    image: redis
  db:
    image: postgres 

从文档中可以看出:

表达服务之间的依赖关系,这有两个效果: Docker-compose up将按依赖顺序启动服务。在下面的例子中,db和redis会在web之前启动。 docker-compose up SERVICE会自动包含SERVICE的依赖项。在下面的例子中,docker-compose up web也将创建并启动db和redis。

注意:据我所知,尽管这确实设置了容器装载的顺序。它不保证容器内的服务已经实际加载。

例如,您的postgres容器可能已经启动。但是postgres服务本身可能仍然在容器中进行初始化。

在尝试了几种方法之后,在我看来,最简单和最优雅的选择是使用jwilder/dockerize实用程序映像(@Henrik Sachse提到过,但他没有给出具体的示例)及其-wait标志。这是一个简单的例子,在启动我的应用程序之前,我需要一个RabbitMQ准备好:

version: "3.8"
services:
  # Start RabbitMQ.
  rabbit:
    image: rabbitmq

  # Wait for RabbitMQ to be joinable.
  check-rabbit-started: 
    image: jwilder/dockerize:0.6.1
    depends_on:
      - rabbit
    command: 'dockerize -wait=tcp://rabbit:5672'
  
  # Only start myapp once RabbitMQ is joinable.
  myapp:
    image: myapp:latest
    depends_on:
      - check-rabbit-started

基于这篇博客文章https://8thlight.com/blog/dariusz-pasciak/2016/10/17/docker-compose-wait-for-dependencies.html

我配置了docker-compose。Yml如下所示:

version: "3.1"

services:
  rabbitmq:
    image: rabbitmq:3.7.2-management-alpine
    restart: always
    environment:
      RABBITMQ_HIPE_COMPILE: 1
      RABBITMQ_MANAGEMENT: 1
      RABBITMQ_VM_MEMORY_HIGH_WATERMARK: 0.2
      RABBITMQ_DEFAULT_USER: "rabbitmq"
      RABBITMQ_DEFAULT_PASS: "rabbitmq"
    ports:
      - "15672:15672"
      - "5672:5672"
    volumes:
      - data:/var/lib/rabbitmq:rw

  start_dependencies:
    image: alpine:latest
    links:
      - rabbitmq
    command: >
      /bin/sh -c "
        echo Waiting for rabbitmq service start...;
        while ! nc -z rabbitmq 5672;
        do
          sleep 1;
        done;
        echo Connected!;
      "

volumes:
  data: {}

然后执行for run =>:

Docker-compose start_dependencies

Rabbitmq服务将以daemon模式启动,start_dependencies将完成工作。

重启:失败 这招对我有用吗

---
version: '2.1'
services:
  consumer:
    image: golang:alpine
    volumes:
      - ./:/go/src/srv-consumer
    working_dir: /go/src/srv-consumer
    environment:
      AMQP_DSN: "amqp://guest:guest@rabbitmq:5672"
    command: go run cmd/main.go
    links:
          - rabbitmq
    restart: on-failure

  rabbitmq:
    image: rabbitmq:3.7-management-alpine
    ports:
      - "15672:15672"
      - "5672:5672"