นักเทียบท่าเขียนรอภาชนะ X ก่อนเริ่ม Y


325

ฉันกำลังใช้ rabbitmq และตัวอย่างงูเหลือมง่ายๆจากที่นี่ พร้อมกับนักเทียบท่าเขียน ปัญหาของฉันคือฉันต้องรอให้ rabbitmq เริ่มต้นอย่างเต็มที่ จากสิ่งที่ฉันค้นหาจนถึงตอนนี้ฉันไม่รู้ว่าจะรอด้วย container x (ใน case case ของฉัน) จนกว่า y (rabbitmq) จะเริ่มขึ้น

ฉันพบบล็อกนี้ที่เขาตรวจสอบว่าโฮสต์อื่น ๆ ออนไลน์อยู่หรือไม่ ฉันก็พบคำสั่งนักเทียบท่านี้:

รอ

การใช้งาน: นักเทียบท่ากำลังรอ CONTAINER [CONTAINER ... ]

บล็อกจนกว่าคอนเทนเนอร์จะหยุดจากนั้นพิมพ์รหัสออก

การรอให้ตู้คอนเทนเนอร์หยุดนั้นอาจไม่ใช่สิ่งที่ฉันกำลังมองหา แต่ถ้าเป็นเช่นนั้นเป็นไปได้ไหมที่จะใช้คำสั่งนั้นใน docker-compose.yml วิธีแก้ปัญหาของฉันคือรอสักครู่และตรวจสอบพอร์ต แต่นี่เป็นวิธีที่จะทำให้สำเร็จหรือไม่ ถ้าฉันไม่รอฉันได้รับข้อผิดพลาด

นักเทียบท่า-compose.yml

worker:
    build: myapp/.
    volumes:
    - myapp/.:/usr/src/app:ro

    links:
    - rabbitmq
rabbitmq:
    image: rabbitmq:3-management

หลามสวัสดีตัวอย่าง (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"]

อัปเดตพฤศจิกายน 2558 :

เชลล์สคริปต์หรือการรออยู่ในโปรแกรมของคุณอาจเป็นทางออกที่เป็นไปได้ แต่หลังจากเห็นปัญหานี้ฉันกำลังมองหาคำสั่งหรือคุณสมบัติของนักเทียบท่า / นักเทียบท่าเขียนตัวเอง

พวกเขากล่าวถึงวิธีแก้ปัญหาสำหรับการตรวจสุขภาพซึ่งอาจเป็นตัวเลือกที่ดีที่สุด การเชื่อมต่อ tcp แบบเปิดไม่ได้หมายความว่าบริการของคุณพร้อมหรืออาจยังคงพร้อมใช้งาน นอกจากนั้นฉันต้องเปลี่ยนจุดเริ่มต้นใน dockerfile ของฉัน

ดังนั้นฉันหวังว่าจะได้คำตอบด้วยคำสั่ง docker-compose บนบอร์ดซึ่งหวังว่าจะเป็นเช่นนั้นหากพวกเขาทำปัญหานี้เสร็จ

อัปเดตมีนาคม 2559

มีข้อเสนอสำหรับการจัดเตรียมวิธีในตัวเพื่อตรวจสอบว่าคอนเทนเนอร์เป็น "ชีวิต" ดังนั้นนักแต่งเพลงอาจจะใช้มันในอนาคตอันใกล้

อัปเดตมิถุนายน 2559

ดูเหมือนว่า Healthcheck จะถูกรวมเข้ากับนักเทียบท่าในเวอร์ชั่น 1.12.0

อัปเดตมกราคม 2560

ฉันพบวิธีแก้ปัญหาDocker-Composeดู: Docker Compose รอคอนเทนเนอร์ X ก่อนเริ่ม Y


2
การใช้ healthchecks in ได้รับการคัดค้านใน docker-compose 2.3 เพื่อกระตุ้นให้ระบบกระจายความผิดพลาด ดู: docs.docker.com/compose/startup-order
Kmaid

คำตอบ:


284

ในที่สุดก็พบวิธีการแก้ปัญหาด้วยวิธีการเขียนนักเทียบท่า ตั้งแต่รูปแบบไฟล์นักเทียบท่า-เขียน 2.1 คุณสามารถกำหนดhealthchecks

ฉันทำมันในโครงการตัวอย่างที่ คุณต้องติดตั้งอย่างน้อยนักเทียบท่า 1.12.0+ ฉันยังต้องการที่จะขยาย Dockerfile การจัดการ rabbitmqเพราะไม่ได้ติดตั้ง curl ในภาพอย่างเป็นทางการ

ตอนนี้ฉันทดสอบว่าหน้าการจัดการของ rabbitmq-container นั้นมีอยู่หรือไม่ หาก curl เสร็จสิ้นด้วย exitcode 0 แอพคอนเทนเนอร์ (python pika) จะเริ่มต้นและเผยแพร่ข้อความเพื่อรอคิว ตอนนี้มันทำงาน (เอาท์พุท)

นักเทียบท่าเขียน (เวอร์ชั่น 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 ไม่สนับสนุนรูปแบบเงื่อนไขของdependent_onอีกต่อไป ดังนั้นฉันย้ายจาก depend_on เพื่อเริ่มต้นใหม่เมื่อล้มเหลว ตอนนี้ที่เก็บแอปของฉันจะเริ่มต้นใหม่ 2-3 ครั้งจนกว่าจะใช้งานได้ แต่ก็ยังคงเป็นคุณสมบัตินักเขียนนักเทียบท่าโดยไม่เขียนทับจุดเข้าใช้งาน

นักเทียบท่าเขียน (รุ่น 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

6
@svenhornberg pingใช้ ICMP ดังนั้นจึงไม่รองรับพอร์ต TCP อาจncจะทดสอบพอร์ต TCP น่าจะดีกว่าที่จะใช้psql -h localhost -p 5432และค้นหาบางสิ่งบางอย่าง
Matt

36
"ขึ้นอยู่กับ" ถูกลบออกในรุ่น 3 docs.docker.com/compose/compose-file/#dependson
nha

48
@nha ดูเหมือนว่าconditionรูปแบบdepends_onจะถูกลบออก แต่depends_onตัวเองยังคงอยู่ใน v3
akivajgordon

14
วิธี healthchecks ยังสามารถใช้ในการสั่งควบคุมการเริ่มต้นถ้าdepends_onมีconditionได้รับการลบหรือไม่
ฟรานซ์

42
ยากที่จะเชื่อความเจ็บปวดเช่นนี้ยังคง
npr

71

อย่างที่เป็นไปไม่ได้เลย ดูเพิ่มเติมที่คำขอคุณสมบัตินี้

จนถึงตอนนี้คุณต้องทำเช่นนั้นในตู้คอนเทนเนอร์CMDเพื่อรอจนกว่าจะมีบริการที่จำเป็นทั้งหมด

ในสิ่งDockerfileที่CMDคุณสามารถอ้างถึงสคริปต์เริ่มต้นของคุณเองที่ wraps เริ่มต้นบริการตู้คอนเทนเนอร์ของคุณ ก่อนที่คุณจะเริ่มคุณจะต้องรออย่างใดอย่างหนึ่งเช่น:

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เช่นกัน ฉันไม่ทราบว่าสิ่งที่ติดตั้งไว้ในภาพหลาม

มีเครื่องมือบางอย่างที่ให้ตรรกะการรอที่ใช้งานง่ายสำหรับการตรวจสอบพอร์ต tcp อย่างง่าย:

สำหรับการรอที่ซับซ้อนมากขึ้น:


คุณช่วยอธิบายความหมายของ CMD ได้ไหม? นี่หมายความว่าโปรแกรมของฉันต้องทำเช่นเดียวกับที่ฉันทำกับการตรวจสอบพอร์ตหรือไม่? หรือคุณหมายถึง CMD เฉพาะจากเช่น linux สำหรับสิ่งนี้?
svenhornberg

ขอบคุณสำหรับการอธิบายฉัน upvote คำตอบของคุณ แต่ฉันคิดว่าการร้องขอคุณสมบัติที่จะเกิดขึ้นจะเป็นคำตอบที่ถูกต้องสำหรับคำถามของฉันดังนั้นฉันจึงปล่อยให้มันยังไม่ได้ตอบ
svenhornberg

44

การใช้restart: unless-stoppedหรือrestart: alwaysอาจแก้ปัญหานี้

หากผู้ปฏิบัติงานcontainerหยุดทำงานเมื่อ rabbitMQ ยังไม่พร้อมจะเริ่มต้นใหม่จนกว่าจะเป็น


3
ฉันชอบโซลูชันนี้สำหรับกรณีนี้ แต่ใช้ไม่ได้กับคอนเทนเนอร์ที่ไม่ออกเมื่อหนึ่งในกระบวนการย่อยที่ทำงานล้มเหลว ตัวอย่างเช่นคอนเทนเนอร์ Tomcat จะยังคงทำงานต่อไปแม้ว่า servlet Java ที่รันจะไม่สามารถเชื่อมต่อกับเซิร์ฟเวอร์ฐานข้อมูลได้ ที่ได้รับภาชนะ Docker ทำให้ภาชนะ servlet เช่น Tomcat ส่วนใหญ่ไม่จำเป็น
Derek Mahar

@DerekMahar หากคุณมีเว็บแอพพลิเคชั่นบนจาวาที่ทำหน้าที่โทรเฉพาะส่วนที่เหลือคุณจะใช้อะไรแทน Jetty / Tomcat?
JoeG

2
@ JoeG ฉันหมายถึง Tomcat คอนเทนเนอร์ servlet ที่สามารถโฮสต์แอปพลิเคชันจำนวนมากไม่ได้ฝัง Tomcat นักเทียบท่าสร้างอดีตส่วนใหญ่ไม่จำเป็นในขณะที่ทำให้หลังได้รับความนิยมมากขึ้นสำหรับ microservices เช่น
Derek Mahar

35

ค่อนข้างเร็ว ๆ นี้พวกเขาได้เพิ่มคุณลักษณะdepends_on

แก้ไข:

ตั้งแต่การเขียนเวอร์ชัน 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 

จากเอกสาร:

แสดงการพึ่งพาระหว่างบริการซึ่งมีสองลักษณะพิเศษ:

  • นักเทียบท่าแต่งจะเริ่มให้บริการในการพึ่งพา ในตัวอย่างต่อไปนี้ db และ redis จะเริ่มต้นก่อนเว็บ
  • นักเทียบท่าแต่ง SERVICE จะรวมการพึ่งพาของ SERVICE โดยอัตโนมัติ ในตัวอย่างต่อไปนี้เว็บประกอบนักเทียบท่าจะสร้างและเริ่มต้น db และ redis

หมายเหตุ:ตามที่ฉันเข้าใจแม้ว่าจะกำหนดลำดับการโหลดคอนเทนเนอร์ ไม่รับประกันว่าบริการที่อยู่ในคอนเทนเนอร์ได้โหลดจริง

ตัวอย่างเช่นคุณโพสต์เกรซคอนเทนเนอร์อาจหมดแล้ว แต่เซอร์วิส postgres เองอาจยังคงกำลังเตรียมใช้งานภายในคอนเทนเนอร์


10
dnephin wrote: depend_on สั่งซื้อเท่านั้น การหน่วงเวลาการเริ่มต้นของคอนเทนเนอร์อื่นจริง ๆ แล้วจะต้องมีวิธีการตรวจสอบเมื่อกระบวนการเสร็จสิ้นการเริ่มต้นเอง
svenhornberg

15
"เวอร์ชัน 3 ไม่รองรับแบบฟอร์มเงื่อนไขอีกต่อไปdepends_on" docs.docker.com/compose/compose-file/#dependson
akauppi

depends_onไม่รอจนกว่าภาชนะจะอยู่ในreadyสถานะ (สิ่งที่สามารถหมายถึงในกรณีของคุณ) มันจะรอจนกว่าคอนเทนเนอร์จะอยู่ในสถานะ 'กำลังทำงาน'
htyagi

19

คุณสามารถเพิ่มไปยังตัวเลือกคำสั่งเช่น

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"

13

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"

12

สำหรับการสั่งซื้อคอนเทนเนอร์เริ่มใช้

depends_on:

สำหรับการรอคอนเทนเนอร์ก่อนหน้าให้เริ่มใช้สคริปต์

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

บทความนี้จะช่วยให้คุณ https://docs.docker.com/compose/startup-order/


5
@svenhornberg ในความคิดเห็นลิงก์คุณไม่มีคำอธิบายเกี่ยวกับคุณสมบัติ wait-for-it.sh
ออกจาก

7

นอกจากนี้คุณยังสามารถแก้ปัญหานี้ได้โดยการตั้งค่าจุดปลายทางที่รอให้บริการเพิ่มขึ้นโดยใช้ netcat (ใช้สคริปต์นักเทียบท่ารอ ) ฉันชอบวิธีการนี้เนื่องจากคุณยังมีcommandส่วนที่สะอาดอยู่ในตัวdocker-compose.ymlและคุณไม่จำเป็นต้องเพิ่มรหัสเฉพาะนักเทียบท่าลงในแอปพลิเคชันของคุณ:

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

นี้เป็นเอกสารในปัจจุบันอย่างเป็นทางการในเอกสารนักเทียบท่า

PS: คุณควรติดตั้งnetcatในอินสแตนซ์นักเทียบท่าหากยังไม่พร้อมใช้งาน โดยเพิ่มสิ่งนี้ลงในDockerไฟล์ของคุณ:

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

4

มียูทิลิตีที่พร้อมใช้งานที่เรียกว่า " นักเทียบท่ารอ " ที่สามารถใช้รอได้


1
ขอบคุณ แต่มันเป็นเพียงเชลล์สคริปต์ดังนั้นจึงเป็นเหมือนคำตอบ h3nrik หรือรออยู่ข้างในหลาม มันไม่ได้เป็นคุณสมบัติของนักเทียบท่าเขียนเอง ขอให้คุณดูในgithub.com/docker/compose/issues/374พวกเขาวางแผนที่จะใช้เฮลช์เช็คซึ่งจะเป็นวิธีที่ดีที่สุด การเชื่อมต่อ tcp แบบเปิดไม่ได้หมายความว่าบริการของคุณพร้อมหรืออาจยังคงพร้อมใช้งาน นอกจากนั้นฉันต้องเปลี่ยนจุดเริ่มต้นใน dockerfile ของฉัน
svenhornberg

3

พยายามหลายวิธี แต่ชอบความเรียบง่ายของสิ่งนี้: https://github.com/ufoscout/docker-compose-wait

แนวคิดที่คุณสามารถใช้ ENV vars ในไฟล์เขียนนักเทียบท่าเพื่อส่งรายการโฮสต์บริการ (ที่มีพอร์ต) ซึ่งควรจะเป็น "คอย" เช่นนี้: 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

ถัดไปเพื่อให้บริการต้องรอคุณจะต้องเพิ่มสองบรรทัดต่อไปนี้ใน Dockerfiles ของคุณ (ใน 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


ฉันกำลังมองหาคำตอบที่คล้ายกัน ฉันมักจะทำงานกับhub.docker.com/r/dadarek/wait-for-dependenciesเนื่องจากใช้ netcat อยู่ด้านล่าง สิ่งที่คุณให้มาคือสนิม ไม่สามารถแสดงความคิดเห็นกับคุณภาพของคุณ แต่สำหรับฉันไม่มีเลเยอร์เพิ่มเติมเป็นมืออาชีพแน่นอน
Filip Malczak

1
ฉันขอแนะนำอย่างยิ่งในเรื่องของความปลอดภัย คุณกำลังเรียกใช้งานได้โดยพลการจากไฮเปอร์ลิงก์ ทางออกที่ดีกว่าคือการทำสิ่งเดียวกันกับสคริปต์แบบคงที่ซึ่งคัดลอกไปยังรูปภาพด้วย COPY
Paul K

@PaulK แน่นอนเป็นที่เข้าใจได้ว่าการรันอะไรก็ตามจากไฮเปอร์ลิงก์นั้นไม่ปลอดภัย แต่เป็นเพียงการสาธิตด้านบนวิธีทำให้https://github.com/ufoscout/docker-compose-waitไลบรารีทำงานได้ :) วิธีที่คุณใช้ไลบรารีนั้นไม่เปลี่ยนคำตอบที่คุณสามารถใช้ประโยชน์ได้บ้าง การรักษาความปลอดภัยเป็นหัวข้อที่ซับซ้อนและถ้าเราไปไกลเราควรตรวจสอบสิ่งที่ห้องสมุดกำลังทำอยู่ข้างในต่อไปแม้ว่าเราจะคัดลอกมัน :) ดีกว่าที่จะเจาะจงมากขึ้นในความคิดเห็นของคุณเช่น: "ฉันขอแนะนำอย่างยิ่งต่อการใช้ห้องสมุด จากไฮเปอร์ลิงก์ " หวังว่าคุณจะเห็นด้วยขอบคุณสำหรับคำใบ้!
Evereq

2

อ้างอิงจากโพสต์บล็อกนี้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: {}

จากนั้นฉันจะเรียกใช้ =>:

docker-compose up start_dependencies

rabbitmqบริการจะเริ่มในโหมด daemon start_dependenciesจะทำงานให้เสร็จ


แล้วทำแบบสอบถามผ่าน"curl", "-f", "http://localhost:15672"ที่คุณต้องการติดตั้งmanagementปลั๊กอินและใช้ healthcheck ที่เลิกใช้แล้ว - คำตอบที่ดีที่สุด ตัวอย่างการทำงานง่าย ๆ พร้อมการตรวจสอบผ่านnc- downvote ฮ่า, โอเค ...
อิกอร์โคมาร์

คำตอบไม่ได้ใช้คุณสมบัติ docker แบบดั้งเดิมมันไม่เกี่ยวข้องหากคุณใช้ curl, nc หรือเครื่องมืออื่น ๆ ในขณะที่! nc เหมือนกันกับที่โพสต์แล้วในคำตอบอื่น ๆ
svenhornberg

1
คุณสมบัตินักเทียบท่าพื้นเมือง: 1. docs.docker.com/compose/startup-order 2. github.com/docker/compose/issues/5007 3. github.com/docker/compose/issues/374
Igor Komar

1
@IgorKomar ขอบคุณชายคุณช่วยชีวิตฉันไว้! : 3 ฉันใช้กลไกเดียวกันเกือบทั้งหมดในการตรวจสอบว่าเซิร์ฟเวอร์ mysql พร้อมใช้งานก่อนที่จะเริ่มใช้งานจริง ;) ฉันกำลังผ่านคำสั่งคล้ายกับdocker-compose run --name app-test --rm "app" bash -l -c 'echo Waiting for mysql service start... && while ! nc -z db-server 3306; do sleep 1; done && echo Connected! && /bin/bash /script/ci_tests.sh'
TooroSan

1

ในเวอร์ชัน 3 ของไฟล์ Docker Compose คุณสามารถใช้RESTART ได้ได้

ตัวอย่างเช่น:

นักเทียบท่า-compose.yml

worker:
    build: myapp/.
    volumes:
    - myapp/.:/usr/src/app:ro
    restart: on-failure
    depends_on:
    - rabbitmq
rabbitmq:
    image: rabbitmq:3-management

โปรดทราบว่าฉันใช้depend_onแทนการเชื่อมโยงเนื่องจากหลังเลิกใช้ในเวอร์ชัน 3

แม้ว่ามันจะใช้งานได้ แต่มันอาจไม่ใช่วิธีแก้ปัญหาในอุดมคติตั้งแต่คุณรีสตาร์ทคอนเทนเนอร์นักเทียบท่าทุกครั้งที่เกิดข้อผิดพลาด

ลองดูRESTART_POLICYด้วยเช่นกัน มันช่วยให้คุณปรับแต่งนโยบายการรีสตาร์ท

เมื่อคุณใช้ Compose ในการผลิตเป็นแนวปฏิบัติที่ดีที่สุดในการใช้นโยบายการรีสตาร์ท:

การระบุนโยบายการเริ่มต้นใหม่เช่นเริ่มใหม่: เสมอเพื่อหลีกเลี่ยงการหยุดทำงาน


0

หนึ่งในวิธีการแก้ปัญหาทางเลือกคือการใช้วิธีการแก้ปัญหา orchestration ภาชนะเช่น Kubernetes Kubernetes มีการสนับสนุนสำหรับคอนเทนเนอร์ init ซึ่งทำงานจนเสร็จสมบูรณ์ก่อนคอนเทนเนอร์อื่นสามารถเริ่มต้นได้ คุณสามารถหาตัวอย่างได้ที่นี่ด้วยคอนเทนเนอร์ SQL Server 2017 Linux ที่ซึ่งคอนเทนเนอร์ API ใช้คอนเทนเนอร์ init เพื่อเริ่มต้นฐานข้อมูล

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


0

นี่คือตัวอย่างที่mainคอนเทนเนอร์รอ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

ไม่แนะนำสำหรับการปรับใช้ที่ร้ายแรง แต่นี่เป็นคำสั่ง "wait x seconds"

ด้วยdocker-composeรุ่นการเรียนการสอนได้รับการเพิ่ม หมายความว่าเราสามารถทำสิ่งต่อไปนี้:3.4start_periodhealthcheck

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สคริปต์ซึ่งจะส่งคืน "ไม่มีปัญหา" เสมอ เราเพิ่งทำzmq_clientตู้คอนเทนเนอร์รอ 5 วินาทีก่อนเริ่ม!

หมายเหตุ: version: "3.4"มันเป็นสิ่งสำคัญที่คุณมี ถ้า.4ไม่มีอยู่นักเทียบท่านั้นก็จะบ่น


1
ในฐานะที่เป็นโซลูชั่นไร้เดียงสา "รอ 5s" คนนี้ค่อนข้างฉลาด ฉันอยากโหวต แต่ฉันจะไม่ทำอย่างนี้เพราะมันใช้ไม่ได้กับการตั้งค่าแบบแยง ๆ และฉันกลัวว่าบางคนจะดูจำนวนโหวตแทนที่จะอ่านอย่างระมัดระวัง ถึงกระนั้นฉันก็อยากจะพูดว่า "ผู้ชายนั่นเก่ง";)
Filip Malczak

PS สำหรับคำตอบที่ซับซ้อนยิ่งขึ้นดูคำตอบของ Evereq
Filip Malczak

นั่นไม่ใช่สิ่งที่start_periodทำ การกำหนดค่าดังกล่าวหมายความว่ามีช่วงเวลาผ่อนผันที่การตรวจสุขภาพที่ล้มเหลวจะไม่นับเป็นการลองใหม่ หากประสบความสำเร็จเร็วก็ถือว่ามีสุขภาพที่ดี หลังจากช่วงเวลาเริ่มต้นความล้มเหลวจะถูกนับเป็นความพยายามอีกครั้ง ดูdocs.docker.com/engine/reference/builder/#healthcheck
Capi Etheriel

-4

ฉันเพิ่งมี 2 ไฟล์เขียนและเริ่มหนึ่งก่อนและสองในภายหลัง สคริปต์ของฉันดูเหมือนว่า:

#!/bin/bash
#before i build my docker files
#when done i start my build docker-compose
docker-compose -f docker-compose.build.yaml up
#now i start other docker-compose which needs the image of the first
docker-compose -f docker-compose.prod.yml up

นี่ไม่ใช่การฝึกฝนที่ดี คุณไม่สามารถส่งมอบโซลูชันที่ประกอบด้วย conatiners หลายคนจากหนึ่งไฟล์เขียนแล้ว
juergi
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.