web-dev-qa-db-ja.com

Docker ComposeはYを開始する前にコンテナXを待つ

私はrabbitmqと here からの簡単なpythonサンプルをdocker-composeと一緒に使っています。私の問題は、rabbitmqが完全に起動するのを待つ必要があることです。これまでの検索から、y(rabbitmq)が開始されるまで、コンテナx(私の場合はワーカー)を待つ方法がわかりません。

私はこれを見つけました blogpost 彼は他のホストがオンラインであるかどうかチェックします。私はまたこの dockerコマンドを見つけました

待機

使用法:docker wait CONTAINER [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サンプル(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:

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

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

2015年11月に更新

シェルスクリプトを使用するか、プログラム内で待機することが考えられる解決策です。しかし、これを見てから 問題 docker/docker-compose自体のコマンドや機能を探しています。

彼らは、ヘルスチェックを実施するための解決策について言及しています。 TCP接続が開いているからといって、サービスの準備が整っていたり、準備ができているとは限りません。それに加えて、私は自分のdockerfileの私のエントリポイントを変更する必要があります。

だから私はdocker-compose on boardコマンドで答えを期待しています、彼らがこの問題を終えたらうまくいけばそうなるでしょう。

2016年3月に更新

コンテナが「生きている」かどうかを判断するための組み込みの方法を提供するための 提案 があります。そのため、docker-composeは近い将来それを利用する可能性があります。

2016年6月に更新

バージョン1.12.0では、ヘルスチェックは 統合 dockerになる予定です。

2017年1月に更新

Docker-composeによる解決策が見つかりました: Docker ComposeがYを開始する前にコンテナXを待つ

226
svenhornberg

最後に、docker-composeメソッドによる解決策を見つけました。 docker-composeファイルフォーマット2.1以降、 healthchecks を定義できます。

私はそれをやった サンプルプロジェクト あなたは少なくともdocker 1.12.0+をインストールする必要があります。 curlが公式イメージにインストールされていないので、私も rabbitmq-management Dockerfileを拡張する を必要としました。

今私はrabbitmqコンテナの管理ページが利用可能かどうかテストします。 curlがexitcode 0で終了すると、コンテナアプリ(python pika)が起動され、メッセージをhelloキューに公開します。その今働いている(出力)。

docker-compose(バージョン2.1):

version: '2.1'

services:
  app:
    build: app/.
    depends_on:
      rabbit:
        condition: service_healthy
    links: 
        - rabbit

  rabbit:
    build: rabbitmq/.
    ports: 
        - "15672:15672"
        - "5672:5672"
    healthcheck:
        test: ["CMD", "curl", "-f", "http://localhost:15672"]
        interval: 30s
        timeout: 10s
        retries: 5

出力:

rabbit_1  | =INFO REPORT==== 25-Jan-2017::14:44:21 ===
rabbit_1  | closing AMQP connection <0.718.0> (172.18.0.3:36590 -> 172.18.0.2:5672)
app_1     |  [x] Sent 'Hello World!'
healthcheckcompose_app_1 exited with code 0

Dockerfile(rabbitmq + curl):

FROM rabbitmq:3-management
RUN apt-get update
RUN apt-get install -y curl 
EXPOSE 4369 5671 5672 25672 15671 15672

バージョン3は、 depends_on の条件形式をサポートしなくなりました。だから私はdepends_onから失敗したときに再起動するために移動しました。現在、私のアプリコンテナは、動作するまで2〜3回再起動しますが、それでもエントリポイントを上書きすることなくdocker-compose機能です。

docker-compose(version 3):

version: "3"

services:

  rabbitmq: # login guest:guest
    image: rabbitmq:management
    ports:
    - "4369:4369"
    - "5671:5671"
    - "5672:5672"
    - "25672:25672"
    - "15671:15671"
    - "15672:15672"
    healthcheck:
        test: ["CMD", "curl", "-f", "http://localhost:15672"]
        interval: 30s
        timeout: 10s
        retries: 5

  app:
    build: ./app/
    environment:
      - HOSTNAMERABBIT=rabbitmq
    restart: on-failure
    depends_on:
      - rabbitmq
    links: 
        - rabbitmq
198
svenhornberg

本来はそれは不可能です。こちら feature request もご覧ください。

これまでのところ、必要なサービスがすべて揃うまで待つために、コンテナ内でこれを行う必要があります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ポートチェックのために、使いやすい待機ロジックを提供するツールがいくつかあります。

より複雑な待機の場合:

67
h3nrik

restart: unless-stoppedまたはrestart: alwaysを使用すると、この問題を解決できる可能性があります。

RabbitMQの準備ができていないときにワーカーcontainerが停止した場合、それが完了するまで再起動されます。

34
Toilal

ごく最近、彼らは depends_on機能を追加しました

編集:

Compose version 2.1以降では、これを実現するためにhealthcheckと一緒にdepends_onを使用できます。

ドキュメントから

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を使用できますが、それはサービスが開始されるorderにのみ影響します - それらが依存サービスが開始される前に準備ができている場合ではない。

少なくともバージョン1.6.0が必要です。

使い方は次のようになります。

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

ドキュメントから:

サービス間の依存関係を表現する。これには2つの効果があります。

  • docker-compose upは依存関係の順序でサービスを開始します。次の例では、dbおよびredisはwebの前に起動されます。
  • docker-compose up SERVICEは自動的にSERVICEの依存関係を含みます。次の例では、docker-compose up webもdbとredisを作成して起動します。

注:私が理解しているように、これはコンテナーがロードされる順序を設定しますが、コンテナー内のサービスが実際にロードされることを保証するものではありません。

たとえば、postgres containerが起動しているかもしれません。しかしpostgresサービス自体はまだコンテナ内で初期化されているかもしれません。

28
toast38coza

コマンドオプションに追加することもできます。

command: bash -c "sleep 5; start.sh"

https://github.com/docker/compose/issues/374#issuecomment-156546513

ポートを待つためには、このようなものを使うこともできます。

command: bash -c "while ! curl -s rabbitmq:5672 > /dev/null; do echo waiting for xxx; sleep 3; done; start.sh"

待機時間を増やすには、もう少しハッキングすることができます。

command: bash -c "for i in {1..100} ; do if ! curl -s rabbitmq:5672 > /dev/null ; then echo waiting on rabbitmq for $i seconds; sleep $i; fi; done; start.sh"
14
AmanicA

コンテナ発注用

depends_on:

前回のコンテナ起動待ちスクリプト用

entrypoint: ./wait-for-it.sh db:5432

この記事は役に立ちます https://docs.docker.com/compose/startup-order/

8
quit

restart: on-failureが私のためにトリックをしました。

---
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"
6
Edwin Ikechukwu

Netcatを使用して( docker-wait スクリプトを使用して)サービスが起動するのを待つエンドポイントを設定することによってもこれを解決できます。あなたのdocker-compose.ymlにまだきれいなcommandセクションがあり、アプリケーションに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ドキュメント に文書化されています。

シモンズ:これが利用できない場合、あなたはあなたのdockerインスタンスにnetcatをインストールするべきです。これを行うには、これをDockerファイルに追加します。

RUN apt-get update && apt-get install netcat-openbsd -y 
5
Martijn Jacobs

待機に使用できる " docker-wait "と呼ばれるすぐに使えるユーティリティがあります。

4
Adrian Mitev

このブログ記事に基づいて 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: {}

それから私はrun =>のためにやる:

docker-compose up start_dependencies

rabbitmqサービスはデーモンモードで起動し、start_dependenciesは作業を終了します。

2
Igor Komar

Docker Composeファイルのバージョン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

links の代わりに depends_on を使用したことに注意してください。後者はバージョン3では非推奨です。

動作しますが、障害が発生するたびにドッカーコンテナを再起動するため、理想的なソリューションではない場合があります。

RESTART_POLICY もご覧ください。再起動ポリシーを微調整できます。

運用環境で構成を使用 の場合、実際には再起動ポリシーを使用することがベストプラクティスです。

Restartなどの再起動ポリシーを指定する:常にダウンタイムを回避する

1
Mathieu Gemard

深刻な配備にはお勧めできませんが、これは基本的に "wait x seconds"コマンドです。

docker-composeバージョン3.4では、 start_period命令がhealthcheck に追加されました。これは私たちが以下のことができることを意味します。

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

ここで起こることはhealthcheckが5秒後に呼び出されることです。これはstatus.shスクリプトを呼び出します。このスクリプトは常に "No problem"を返します。 zmq_clientコンテナを起動前に5秒間待機させたばかりです。

注:version: "3.4"があることが重要です。 .4がそこにない場合、docker-composeは文句を言います。

0
NumesSanguis

代替ソリューションの1つは、Kubernetesのようなコンテナオーケストレーションソリューションを使用することです。 Kubernetesは他のコンテナが起動する前に最後まで実行されるinitコンテナをサポートしています。ここでは、SQL Server 2017 Linuxコンテナーの例を見つけることができます。ここで、APIコンテナーはinitコンテナーを使用してデータベースを初期化します。

https://www.handsonarchitect.com/2018/08/understand-kubernetes-object-init.html

0
Nilesh Gule

これは、mainコンテナが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)を使うことです。

0
kenorb

さまざまな方法を試してみましたが、この単純さが好きでした: https://github.com/ufoscout/docker-compose-wait

Docker composeファイルでENV変数を使用して、次のように待機する必要があるサービスホストのリスト(ポートを含む)を送信できるというアイデア。WAIT_HOSTS: postgres:5432, mysql:3306, mongo:27017

次のdocker-compose.ymlファイルがあるとしましょう(repo _ readme _ からコピー/ペースト):

version: "3"

services:

  mongo:
    image: mongo:3.4
    hostname: mongo
    ports:
      - "27017:27017"

  postgres:
    image: "postgres:9.4"
    hostname: postgres
    ports:
      - "5432:5432"

  mysql:
    image: "mysql:5.7"
    hostname: mysql
    ports:
      - "3306:3306"

  mySuperApp:
    image: "mySuperApp:latest"
    hostname: mySuperApp
    environment:
      WAIT_HOSTS: postgres:5432, mysql:3306, mongo:27017

次に、サービスが待機するようにするには、Dockerファイルに次の2行を追加する必要があります(他のサービスの起動を待つ必要があるサービスのDockerfileに)。

ADD https://github.com/ufoscout/docker-compose-wait/releases/download/2.5.0/wait /wait
RUN chmod +x /wait

そのようなサンプルDockerfileの完全な例(やはりプロジェクトrepo _ readme _ から):

FROM Alpine

## Add your application to the docker image
ADD MySuperApp.sh /MySuperApp.sh

## Add the wait script to the image
ADD https://github.com/ufoscout/docker-compose-wait/releases/download/2.5.0/wait /wait
RUN chmod +x /wait

## Launch the wait tool and then your application
CMD /wait && /MySuperApp.sh

考えられる使用方法の詳細については、 _ readme _ を参照してください。

0
Evereq