我在这里使用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


当前回答

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

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

其他回答

您还可以通过设置一个端点来解决这个问题,该端点使用netcat(使用docker-wait脚本)等待服务启动。我喜欢这种方法,因为在docker-compose中仍然有一个干净的命令部分。Yml,你不需要添加docker特定的代码到你的应用程序:

version: '2'
services:
  db:
    image: postgres
  django:
    build: .
    command: python manage.py runserver 0.0.0.0:8000
    entrypoint: ./docker-entrypoint.sh db 5432
    volumes:
      - .:/code
    ports:
      - "8000:8000"
    depends_on:
      - db

然后docker-entrypoint.sh:

#!/bin/sh

postgres_host=$1
postgres_port=$2
shift 2
cmd="$@"

# wait for the postgres docker to be running
while ! nc $postgres_host $postgres_port; do
  >&2 echo "Postgres is unavailable - sleeping"
  sleep 1
done

>&2 echo "Postgres is up - executing command"

# run the command
exec $cmd

这在官方docker文档中有记载。

PS:你应该在docker实例中安装netcat,如果这是不可用的。要做到这一点,请在Docker文件中添加以下内容:

RUN apt-get update && apt-get install netcat-openbsd -y 

不建议用于严重的部署,但这里实际上是一个“等待x秒”命令。

在docker-compose 3.4版中,healthcheck添加了一条start_period指令。这意味着我们可以做到以下几点:

docker-compose.yml:

version: "3.4"
services:
  # your server docker container
  zmq_server:
    build:
      context: ./server_router_router
      dockerfile: Dockerfile

  # container that has to wait
  zmq_client:
    build:
      context: ./client_dealer/
      dockerfile: Dockerfile
    depends_on:
      - zmq_server
    healthcheck:
      test: "sh status.sh"
      start_period: 5s

status.sh:

#!/bin/sh

exit 0

这里发生的情况是,5秒后调用healthcheck。这将调用status.sh脚本,该脚本总是返回“No problem”。 我们只是让zmq_client容器在启动前等待5秒!

注意:重要的是你有版本:“3.4”。如果。4不在那里,docker-compose会抱怨。

我猜docker的人真的想让我们用自己映像中的代码来等待服务。我仍然想在docker-compose.yml中配置等待的服务。如果您愿意使用入口点脚本,这里有一种方法。

使用图像中包含的wait-for-it工具将此循环添加到入口点脚本中。我正在使用https://github.com/vishnubob/wait-for-it/。如果不传递任何服务,循环将不执行任何操作。

for service in "$@"; do
    echo "$0: wait for service $service"
    if ! wait-for-it "$service"; then
        echo "$0: failed on service $service"
        exit 1
    fi
done

在docker-compose.yml中为容器传递所需的服务:

    command: ["my-data-svc:5000"]

这依赖于docker命令作为参数传递给入口点脚本的行为。您可能会认为我在这里滥用了docker命令的意图。我不会死在山上的,这对我很有用。

在本土,这是不可能的。另请参阅此特性请求。

到目前为止,您需要在容器CMD中执行此操作,直到所有所需的服务都在那里。

在Dockerfiles CMD中,你可以引用你自己的启动脚本来启动你的容器服务。在你开始之前,你需要等待一个依赖的选项,比如:

Dockerfile

FROM python:2-onbuild
RUN ["pip", "install", "pika"]
ADD start.sh /start.sh
CMD ["/start.sh"]

start.sh

#!/bin/bash
while ! nc -z rabbitmq 5672; do sleep 3; done
python rabbit.py

也许你也需要在Dockerfile中安装netcat。我不知道python映像上预装了什么。

有一些工具提供了易于使用的等待逻辑,用于简单的tcp端口检查:

等待它 dockerize

对于更复杂的等待:

goss -解释博客

下面是主容器在开始响应ping时等待worker的例子:

version: '3'
services:
  main:
    image: bash
    depends_on:
     - worker
    command: bash -c "sleep 2 && until ping -qc1 worker; do sleep 1; done &>/dev/null"
    networks:
      intra:
        ipv4_address: 172.10.0.254
  worker:
    image: bash
    hostname: test01
    command: bash -c "ip route && sleep 10"
    networks:
      intra:
        ipv4_address: 172.10.0.11
networks:
  intra:
    driver: bridge
    ipam:
      config:
      - subnet: 172.10.0.0/24

但正确的方法是使用healthcheck(>=2.1)。