私は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を待つ
最後に、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
本来はそれは不可能です。こちら feature request もご覧ください。
これまでのところ、必要なサービスがすべて揃うまで待つために、コンテナ内でこれを行う必要がありますCMD
。
Dockerfile
s 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ポートチェックのために、使いやすい待機ロジックを提供するツールがいくつかあります。
より複雑な待機の場合:
restart: unless-stopped
またはrestart: always
を使用すると、この問題を解決できる可能性があります。
RabbitMQの準備ができていないときにワーカーcontainer
が停止した場合、それが完了するまで再起動されます。
ごく最近、彼らは 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サービス自体はまだコンテナ内で初期化されているかもしれません。
コマンドオプションに追加することもできます。
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"
コンテナ発注用
depends_on:
前回のコンテナ起動待ちスクリプト用
entrypoint: ./wait-for-it.sh db:5432
この記事は役に立ちます https://docs.docker.com/compose/startup-order/
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"
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
待機に使用できる " docker-wait "と呼ばれるすぐに使えるユーティリティがあります。
このブログ記事に基づいて 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
は作業を終了します。
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などの再起動ポリシーを指定する:常にダウンタイムを回避する
深刻な配備にはお勧めできませんが、これは基本的に "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は文句を言います。
代替ソリューションの1つは、Kubernetesのようなコンテナオーケストレーションソリューションを使用することです。 Kubernetesは他のコンテナが起動する前に最後まで実行されるinitコンテナをサポートしています。ここでは、SQL Server 2017 Linuxコンテナーの例を見つけることができます。ここで、APIコンテナーはinitコンテナーを使用してデータベースを初期化します。
https://www.handsonarchitect.com/2018/08/understand-kubernetes-object-init.html
これは、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)を使うことです。
さまざまな方法を試してみましたが、この単純さが好きでした: 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 _ を参照してください。