У меня есть следующий докер-сочинять, где мне нужно дождаться, пока служба jhipster-реестр будет запущена и принимает соединения, прежде чем запускать myprogram-приложение.
Я попробовал способ проверки здоровья, следуя официальному документу https://docs.docker.com/compose/compose-file/compose-file-v2/
version: '2.1'
services:
myprogram-app:
image: myprogram
mem_limit: 1024m
environment:
- SPRING_PROFILES_ACTIVE=prod,swagger
- EUREKA_CLIENT_SERVICE_URL_DEFAULTZONE=http://admin:$${jhipster.registry.password}@jhipster-registry:8761/eureka
- SPRING_CLOUD_CONFIG_URI=http://admin:$${jhipster.registry.password}@jhipster-registry:8761/config
- SPRING_DATASOURCE_URL=jdbc:postgresql://myprogram-postgresql:5432/myprogram
- JHIPSTER_SLEEP=0
- SPRING_DATA_ELASTICSEARCH_CLUSTER_NODES=myprogram-elasticsearch:9300
- JHIPSTER_REGISTRY_PASSWORD=53bqDrurQAthqrXG
- EMAIL_USERNAME
- EMAIL_PASSWORD
ports:
- 8080:8080
networks:
- backend
depends_on:
- jhipster-registry:
"condition": service_started
- myprogram-postgresql
- myprogram-elasticsearch
myprogram-postgresql:
image: postgres:9.6.5
mem_limit: 256m
environment:
- POSTGRES_USER=myprogram
- POSTGRES_PASSWORD=myprogram
networks:
- backend
myprogram-elasticsearch:
image: elasticsearch:2.4.6
mem_limit: 512m
networks:
- backend
jhipster-registry:
extends:
file: jhipster-registry.yml
service: jhipster-registry
mem_limit: 512m
ports:
- 8761:8761
networks:
- backend
healthcheck:
test: "exit 0"
networks:
backend:
driver: "bridge"
но я получаю следующую ошибку при запуске docker-compose up:
ERROR: The Compose file './docker-compose.yml' is invalid because:
services.myprogram-app.depends_on contains {"jhipster-registry": {"condition": "service_started"}}, which is an invalid type, it should be a string
Я что-то делаю не так, или эта функция больше не поддерживается? Как добиться такой синхронизации между сервисами?
Обновленная версия
version: '2.1'
services:
myprogram-app:
image: myprogram
mem_limit: 1024m
environment:
- SPRING_PROFILES_ACTIVE=prod,swagger
- EUREKA_CLIENT_SERVICE_URL_DEFAULTZONE=http://admin:$${jhipster.registry.password}@jhipster-registry:8761/eureka
- SPRING_CLOUD_CONFIG_URI=http://admin:$${jhipster.registry.password}@jhipster-registry:8761/config
- SPRING_DATASOURCE_URL=jdbc:postgresql://myprogram-postgresql:5432/myprogram
- JHIPSTER_SLEEP=0
- SPRING_DATA_ELASTICSEARCH_CLUSTER_NODES=myprogram-elasticsearch:9300
- JHIPSTER_REGISTRY_PASSWORD=53bqDrurQAthqrXG
- EMAIL_USERNAME
- EMAIL_PASSWORD
ports:
- 8080:8080
networks:
- backend
depends_on:
jhipster-registry:
condition: service_healthy
myprogram-postgresql:
condition: service_started
myprogram-elasticsearch:
condition: service_started
#restart: on-failure
myprogram-postgresql:
image: postgres:9.6.5
mem_limit: 256m
environment:
- POSTGRES_USER=myprogram
- POSTGRES_PASSWORD=tuenemreh
networks:
- backend
myprogram-elasticsearch:
image: elasticsearch:2.4.6
mem_limit: 512m
networks:
- backend
jhipster-registry:
extends:
file: jhipster-registry.yml
service: jhipster-registry
mem_limit: 512m
ports:
- 8761:8761
networks:
- backend
healthcheck:
test: ["CMD", "curl", "-f", "http://jhipster-registry:8761", "|| exit 1"]
interval: 30s
retries: 20
#start_period: 30s
networks:
backend:
driver: "bridge"
Обновленная версия выдает другую ошибку,
ERROR: for myprogram-app Container "8ebca614590c" is unhealthy.
ERROR: Encountered errors while bringing up the project.
говоря, что контейнер jhipster-registry неисправен, но доступен через браузер. Как я могу исправить команду в проверке работоспособности, чтобы она работала?


документация предполагает, что в файлах Docker Compose версии 2, в частности, depends_on: может быть списком строк или отображением, где ключи являются именами служб, а значения - условиями. Для служб, для которых у вас нет (или необходимости) проверки работоспособности, существует условие service_started.
depends_on:
# notice: these lines don't start with "-"
jhipster-registry:
condition: service_healthy
myprogram-postgresql:
condition: service_started
myprogram-elasticsearch:
condition: service_started
В зависимости от того, насколько вы контролируете свою программу и ее библиотеки, еще лучше, если вы можете организовать запуск службы без обязательной доступности ее зависимостей (эквивалентно, чтобы она работала, если ее зависимости умирают во время работы службы) , а не использовать опцию depends_on:. Вы можете вернуть ошибку HTTP 503 Service Unavailable, например, если база данных не работает. Другая часто полезная стратегия - немедленно выйти, если ваши зависимости недоступны, но использовать установка, например restart: on-error, чтобы попросить оркестратор перезапустить службу.
Хорошо, предыдущая ошибка исчезла. Я обновил вопрос с вашим исправлением, но используемая команда, похоже, не работает. Как мне сделать так, чтобы curl возвращал 0 (я прочитал его, но это не так), если jhipser-registry: 8761 запущен?
Справочная страница curl имеет довольно исчерпывающий список кодов выхода; Документы Docker HEALTHCHECK предлагает curl -f http://localhost/ || exit 1 в качестве типичной проверки работоспособности (для этого требуется, чтобы в вашем образе был установлен curl).
этот ответ больше не актуален. из документов: Version 3 no longer supports the condition form of depends_on
Это снова актуально. Из docker-compose 1.27.0 он поддерживает стандарт COMPOSE_SPEC для v3, который включает condition для depends_on, см. примечания к выпуску
Хотя вы уже получили ответ, следует отметить, что то, чего вы пытаетесь достичь, сопряжено с некоторыми неприятными рисками.
В идеале сервис должен быть самодостаточным и достаточно умным, чтобы повторить попытку и дождаться появления зависимостей (до того, как произойдет сбой). В противном случае вы будете больше подвержены риску распространения одного сбоя на другие службы. Также учтите, что перезагрузка системы, в отличие от ручного запуска, может игнорировать порядок зависимостей.
Если сбой одной службы приводит к отказу всей вашей системы, у вас может быть инструмент, чтобы перезапустить все снова, но было бы лучше иметь службы, которые сопротивляются этому случаю.
Обновитесь до версии 3+.
Следуйте документы версии 3:
There are several things to be aware of when using
depends_on:
depends_ondoes not wait for db and redis to be “ready” before starting web - only until they have been started.
If you need to wait for a service to be ready, see Controlling startup order for more on this problem and strategies for solving it.
Version 3 no longer supports the condition form ofdepends_on.
Thedepends_onoption is ignored when deploying a stack in swarm mode with a version 3 Compose file.
Я бы подумал об использовании параметра restart_policy для настройки вашего myprogram-приложение для перезапуска, пока jhipster-реестр не будет включен и принимать соединения:
restart_policy:
condition: on-failure
delay: 3s
max_attempts: 5
window: 60s
Хотя docker делает поддерживает зависимости запуска, они официально рекомендуют обновить логику запуска вашего приложения, чтобы проверить наличие внешних зависимостей и повторить попытку. Это имеет множество преимуществ для надежных приложений, которые могут перезапускаться в дикой природе на лету, в дополнение к обходу состояния гонки в docker compose up.
wait-for-it.shРекомендуемый подход от докеров в соответствии с их документами на Управление порядком запуска и завершения работы в Compose - загрузить wait-for-it.sh, который принимает domain:port для опроса, а затем выполняет следующий набор команд в случае успеха.
version: "2"
services:
web:
build: .
ports:
- "80:8000"
depends_on:
- "db"
command: ["./wait-for-it.sh", "db:5432", "--", "python", "app.py"]
db:
image: postgres
Примечание: это требует переопределения команды запуска образа, поэтому убедитесь, что вы знаете, что нужно передать, чтобы сохранить четность запуска по умолчанию.
depends_on - service_healthy (устарело 3+)Исторически вы могли определить healthcheck (все еще хорошая практика), а затем установить условие для depends_on на service_healthy, однако это условное отклонение зависит от устаревшего в версии 3.0.
version: '3.0'
services:
php:
build:
context: .
dockerfile: tests/Docker/Dockerfile-PHP
depends_on:
redis:
condition: service_healthy
redis:
image: redis
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 1s
timeout: 3s
retries: 30
Лучший подход, который я нашел, - это проверить желаемый порт в точке входа. Это можно сделать разными способами, например: wait-for-it, но мне нравится использовать это решение, которое является кроссплатформенным между изображениями apline и bash и не загружает пользовательские скрипты с GitHub:
Установите netcat-openbsd (работает с apt и apk). Затем в точке входа (работает как с #!/bin/bash, так и с #!/bin/sh):
#!/bin/bash
wait_for()
{
echo "Waiting $1 seconds for $2:$3"
timeout $1 sh -c 'until nc -z $0 $1; do sleep 0.1; done' $2 $3 || return 1
echo "$2:$3 available"
}
wait_for 10 db 5432
wait_for 10 redis 6379
Вы также можете превратить это в однострочник, если не хотите ничего печатать.