Docker Compose дождитесь контейнера X перед запуском Y
Я использую rabbitmq и простой пример python из здесь
вместе с Докером-сочинять. Моя проблема заключается в том, что мне нужно дождаться полного запуска rabbitmq. Из того, что я искал до сих пор, я не знаю, как ждать с контейнером x ( в моем случае worker), пока не будет запущен y (rabbitmq).
Я нашел это blogpost, где он проверяет, если другой узел онлайн.
Я также нашел это команду docker:
ждать
использование: докер ждать контейнер [контейнер...]
блокируйте контейнер до тех пор, пока он не остановится, а затем распечатайте его код выхода.
ожидание остановки контейнера, возможно, не то, что я ищу, но если
возможно ли использовать эту команду внутри docker-compose.в формате YML ?
Мое решение до сих пор состоит в том, чтобы подождать несколько секунд и проверить порт, но это способ достичь этого?. Если я не буду ждать, я получу ошибка.
docker-compose.в формате YML
worker:
build: myapp/.
volumes:
- myapp/.:/usr/src/app:ro
links:
- rabbitmq
rabbitmq:
image: rabbitmq:3-management
python привет образец (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:
сценарий оболочки или ожидание внутри вашей программы, возможно, является возможным решением. Но увидев это вопрос Я ищу команду или функцию docker/docker-compose себя.
они упоминают решение для реализации проверки состояния здоровья, которое может быть лучшим вариантом. Открытое tcp-соединение не означает, что ваша служба готова или может оставаться готовой. В дополнение к этому мне нужно изменить мою точку входа в моем dockerfile.
поэтому я надеюсь на ответ с помощью команд docker-compose на борту, которые, надеюсь, будут иметь место, если они закончат эту проблему.
Обновление Марта 2016
есть предложение для обеспечения встроенного способа определения того, является ли контейнер "живым". Так что docker-compose может использовать его в ближайшем будущем.
Обновление Июня 2016
похоже, что проверка здоровья будет встроенный в настройки в версии 1.12.0
Обновление Januar 2017
Я нашел решение docker-compose см.:
Docker Compose дождитесь контейнера X перед запуском Y
10 ответов:
наконец-то найдено решение с помощью метода docker-compose. Поскольку docker-compose File format 2.1 вы можете определить healthchecks.
Я сделал это в пример проекта вам нужно установить хотя бы докер 1.12.0+. Мне тоже нужно было расширить RabbitMQ-management Dockerfile, потому что curl не установлен на официальном образе.
теперь я проверяю, доступна ли страница управления RabbitMQ-контейнером. Если завиток заканчивается 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 (версия 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
изначально это пока невозможно. Смотрите также это запрос.
до сих пор вам нужно сделать это в ваших контейнерах
CMD
ждать, пока все необходимые услуги.на
Dockerfile
sCMD
вы можете обратиться к своему собственному сценарию запуска, который обертывает запуск службы контейнеров. Прежде чем начать его, вы ждете зависимости один например: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
вероятно, вам нужно установить netcat в вашем
Dockerfile
как хорошо. Я не знаю, что предварительно установлено на образе python.есть несколько инструментов, которые обеспечивают простую в использовании логику ожидания, для простых проверок портов tcp:
для более сложных ожидания:
используя
restart: unless-stopped
илиrestart: always
может решить эту проблему.Если работник
container
останавливается, когда rabbitMQ не готов, он будет перезапущен, пока он не будет готов.
совсем недавно они добавили
depends_on
характеристика.Edit:
начиная с версии compose 2.1+ вы можете использовать
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 web также создаст и запустит db и redis.
Примечание: как я понимаю, хотя это устанавливает порядок, в котором загружаются контейнеры. Это не гарантирует, что служба внутри контейнера действительно загрузилась.
например, вы postgres контейнер может быть. Но сама служба 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"
вы также можете решить эту проблему, установив конечную точку, которая ждет службы, чтобы быть с помощью netcat (с помощью докер-ждать сценарий). Мне нравится этот подход, так как у вас все еще есть чистый в своем
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= postgres_port= 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
это в настоящее время задокументировано в официальном докер документации.
PS: вы следует установить
netcat
в вашем экземпляре docker, если это недоступно. Для этого добавьте это в вашDocker
file:RUN apt-get update && apt-get install netcat-openbsd -y
есть готовая к использованию утилита под названием"докер-ждать " это может быть использовано для ожидания.
для контейнера начните приказывать пользу
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"
основываясь на этом сообщении в блоге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
закончит работу.