source

도커 구성 Y를 시작하기 전에 컨테이너 X 대기

manycodes 2023. 8. 14. 22:58
반응형

도커 구성 Y를 시작하기 전에 컨테이너 X 대기

저는 여기서 rabbitmq와 간단한 python 샘플을 도커 컴포지와 함께 사용하고 있습니다.나의 문제는 rabbitmq가 완전히 시작될 때까지 기다려야 한다는 것입니다.지금까지 검색한 결과 y(rabbitmq)가 시작될 때까지 컨테이너 x(나의 경우 작업자)를 가지고 기다리는 방법을 모르겠습니다.

나는 그가 다른 호스트가 온라인 상태인지 확인하는 이 블로그 게시물을 발견했습니다.다음 도커 명령도 찾았습니다.

잠깐만요.

용도: 도커 대기 컨테이너 [컨테이너...]

컨테이너가 멈출 때까지 차단한 다음 종료 코드를 인쇄합니다.

컨테이너가 중지되기를 기다리는 것은 제가 찾고 있는 것이 아닐 수도 있지만, 그렇다면 도커-compose.yml 내에서 해당 명령을 사용할 수 있습니까?지금까지 제 해결책은 몇 초 정도 기다렸다가 포트를 확인하는 것인데, 이 방법이 이를 달성하는 방법인가요?기다리지 않으면 오류가 발생합니다.

도커-docker.yml

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

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

python hello 샘플 (계속)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()

작업자의 도커 파일:

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

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

2015년 11월 업데이트:

셸 스크립트 또는 프로그램 내부에서 대기하는 것이 가능한 해결책일 수 있습니다.그러나 이 문제를 보고 도커/도커 합성 자체의 명령 또는 기능을 찾고 있습니다.

그들은 건강 점검을 구현하기 위한 해결책을 언급하는데, 이것은 최선의 선택일 수도 있습니다.tcp 연결이 열려 있다고 해서 서비스가 준비되었거나 준비 상태를 유지할 수 있는 것은 아닙니다.또한 도커 파일에서 진입점을 변경해야 합니다.

그래서 저는 도커-컴포지 온보드 명령어로 답변을 기대하고 있는데, 그들이 이 문제를 끝내면 그렇게 되기를 바랍니다.

2016년 3월 업데이트

컨테이너가 "활성" 상태인지 확인할 수 있는 내장된 방법을 제공하는 제안이 있습니다.그래서 도커 컴포지트는 가까운 미래에 그것을 사용할 수 있을 것입니다.

2016년 6월 업데이트

버전 1.12.0에서는 상태 점검이 도커에 통합될 것으로 보입니다.

2017년 1월 업데이트

도커 합성 솔루션을 찾았습니다. 다음을 참조하십시오.도커 구성 Y를 시작하기 전에 컨테이너 X 대기

마침내 도커 합성 방법으로 해결책을 찾았습니다.도커 합성 파일 형식 2.1이므로 상태 검사를 정의할 수 있습니다.

도커 1.12.0+ 이상을 설치해야 하는 예제 프로젝트에서 실행했습니다.공식 이미지에 컬이 설치되어 있지 않기 때문에 rabbitmq-management Docker 파일도 확장해야 했습니다.

이제 rabbitmq-container의 management page를 사용할 수 있는지 테스트합니다.종료 코드 0으로 컬이 완료되면 컨테이너 앱(python pika)이 시작되고 hello 큐에 메시지를 게시합니다.이제 작동합니다(출력).

도커 모듈(버전 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

도커 파일(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번 다시 시작되지만 진입점을 덮어쓰지 않고 도커 합성 기능입니다.

도커 모듈(버전 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

최근에 그들은 이 기능을 추가했습니다.

편집:

까지 사용할 수 .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가 웹보다 먼저 시작됩니다.
  • 도커 합성 서비스는 자동으로 서비스의 종속성을 포함합니다.다음 예제에서는 도커 합성 웹도 db 및 redis를 만들고 시작합니다.

참고: 제가 이해한 바로는, 이것은 컨테이너가 적재되는 순서를 설정합니다.컨테이너 내부의 서비스가 실제로 로드되었음을 보장하지는 않습니다.

예를 들어 postgres 컨테이너가 작동 중일 수 있습니다.그러나 postgres 서비스 자체가 여전히 컨테이너 내에서 초기화 중일 수 있습니다.

기본적으로, 그것은 아직 가능하지 않습니다.기능 요청도 참조하십시오.

지금까지 당신은 당신의 컨테이너에서 그것을 할 필요가 있습니다.CMD필요한 서비스가 모두 제공될 때까지 기다립니다.

Dockerfiles CMD컨테이너 서비스 시작을 마무리하는 자체 시작 스크립트를 참조할 수 있습니다.시작하기 전에 다음과 같은 종속 항목을 기다립니다.

도커 파일

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뿐만 아니라.나는 파이썬 이미지에 무엇이 미리 설치되어 있는지 모릅니다.

간단한 tcp 포트 검사를 위해 사용하기 쉬운 대기 논리를 제공하는 몇 가지 도구가 있습니다.

더 복잡한 대기의 경우:

용사를 합니다.restart: unless-stopped또는restart: always이 문제를 해결할 수 있습니다.

If workercontainer토끼가 잡히면 멈춥니다.MQ가 준비되지 않았습니다. 준비될 때까지 다시 시작됩니다.

에만 다른 서비스(예: 데이터 등가 성공적으로 , 다른서스예성완시경경는작서우려하를비스입션력이만에우레료데가된터, 마이비그로으이공적예▁if입),▁only▁success력),docker-compose버전 1.29는 이를 위한 내장 기능과 함께 제공됩니다.service_completed_successfully.

depends_on:
  <service-name>:
    condition: service_completed_successfully

사양에 따름:

service_completed_successfully합니다.

명령 옵션에 추가할 수도 있습니다. 예).

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"

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"

컨테이너 시작 주문의 경우

depends_on:

대기 중인 이전 컨테이너 시작 스크립트 사용

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

기사는 https://docs.docker.com/compose/startup-order/ 에 도움이 될 것입니다.

다양한 방법을 시도했지만 이 단순성이 마음에 들었습니다. https://github.com/ufoscout/docker-compose-wait

을할 수 는 다음과 . 즉, "대기" 상태여야 합니다.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 파일에 추가해야 합니다(다른 서비스가 시작될 때까지 기다려야 하는 서비스의 Docker 파일에).

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

이러한 샘플 도커 파일의 전체 예(프로젝트 레포 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를 참조하십시오.

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

이는 현재 공식 도커 설명서에 나와 있습니다.

를 설치해야 .netcat도커 인스턴스(사용할 수 없는 경우).이 작업을 수행하려면 다음 작업에 추가합니다.Dockervmdk:

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

대기에 사용할 수 있는 "도커 대기"라는 유틸리티가 있습니다.

이 블로그 게시물 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모드에서 됩니다.start_dependencies일을 끝낼 것입니다.

Docker Composite 파일 버전 3에서는 RESTART를 사용할 수 있습니다.

예:

도커-docker.yml

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

링크가 버전 3에서 더 이상 사용되지 않기 때문에 링크 대신 dependences_on을 사용했습니다.

작동하더라도 매번 실패할 때마다 도커 컨테이너를 다시 시작하기 때문에 이상적인 솔루션은 아닐 수 있습니다.

RESTART_POLICY도 확인합니다.재시작 정책을 미세 조정할 수 있습니다.

프로덕션에서 구성을 사용할 때는 실제로 재시작 정책을 사용하는 것이 좋습니다.

재시작과 같은 재시작 정책 지정: 항상 다운타임 방지

에, 는 가장 하는 것입니다.jwilder/dockerize 이미지예는 .)와 함께 @Henrik Sachse가 언급했습니다.-waitflag. 토끼가 .앱을 시작하기 전에 준비해야 하는 MQ:

version: "3.8"
services:
  # Start RabbitMQ.
  rabbit:
    image: rabbitmq

  # Wait for RabbitMQ to be joinable.
  check-rabbit-started: 
    image: jwilder/dockerize:0.6.1
    depends_on:
      - rabbit
    command: 'dockerize -wait=tcp://rabbit:5672'
  
  # Only start myapp once RabbitMQ is joinable.
  myapp:
    image: myapp:latest
    depends_on:
      - check-rabbit-started

심각한 배포에는 권장되지 않지만 기본적으로 "wait x seconds" 명령이 있습니다.

와 함께docker-compose3.4지침이 에 추가되었습니다.즉, 다음을 수행할 수 있습니다.

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

▁the입니다.healthcheck5초 후에 호출됩니다.이를 다음과 같이 부릅니다.status.sh스크립트는 항상 "문제 없음"을 반환합니다. 저가지금을 만들었습니다.zmq_client컨테이너는 시작하기 전에 5초 동안 기다립니다!

참고: 중요한 것은 다음과 같습니다.version: "3.4"에 약에만..4도커가 불평합니다.

대안 솔루션 중 하나는 Kubernetes와 같은 컨테이너 오케스트레이션 솔루션을 사용하는 것입니다.Kubernetes는 다른 컨테이너가 시작되기 전에 완료될 때까지 실행되는 init 컨테이너를 지원합니다.API 컨테이너가 init 컨테이너를 사용하여 데이터베이스를 초기화하는 SQL Server 2017 Linux 컨테이너의 예를 여기에서 찾을 수 있습니다.

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

또한 현재는 일부 서비스가 시작되기 전에 서비스가 가동되고 실행될 때까지 기다려야 하는 요구 사항은 다음과 같습니다.또한 여기와 다른 장소의 제안을 읽으십시오.하지만 그들 중 대부분은 요구합니다.docker-compose.yml어떻게든 조금 바뀌어야 합니다. 셸 . 스스로를 구성하고 마침내 제가 부르는 셸 스크립트를 고안했습니다.docker-compose-profile서비스가 호스트 디렉토리에 포트를 노출하지 않더라도 특정 컨테이너에 대한 tcp 연결을 기다릴 수 있습니다.제가 사용하는 방법은 스택 내에서 다른 도커 컨테이너를 시작하는 것이며, 다른 네트워크 구성이 적용되지 않는 한, 일반적으로 모든 서비스에 연결할 수 있습니다.특정 로그 메시지를 주의하는 대기 방법도 있습니다.다른 단계가 시작하도록 트리거되기 전에 서비스를 함께 그룹화하여 한 단계로 시작할 수 있습니다.시작할 다른 모든 서비스를 나열하지 않고 일부 서비스를 제외할 수도 있습니다(예: 사용 가능한 서비스 모음에서 일부 제외된 서비스 제외).이러한 종류의 구성은 프로파일에 번들로 제공될 수 있습니다. yaml 성이있라는 yaml .dcp.yml(현재로서는) 도커-docker.yml 파일을 따로 두어야 합니다.

질문 내용은 다음과 같습니다.

command:
  aliases:
    upd:
      command: "up -d"
      description: |
        Create and start container. Detach afterword.

profiles:
  default:
    description: |
      Wait for rabbitmq before starting worker.
    command: upd
    steps:
      - label: only-rabbitmq
        only: [ rabbitmq ]
        wait:
          - 5@tcp://rabbitmq:5432
      - label: all-others

이제 스택을 호출하여 시작할 수 있습니다.

dcp -p default upd

또는 단순히에 의해서라도.

dcp

할 수 up -d온에

아주 작은 문제가 있습니다.제 현재 버전은 (아직) 실제로 필요한 것과 같은 특별한 대기 조건을 지원하지 않습니다.그래서 토끼에게 메시지를 보내는 테스트는 없습니다.

호스트에서 특정 명령을 실행하거나 도커 컨테이너로 실행하기 위한 추가 대기 방법에 대해 이미 생각하고 있습니다.우리가 그 도구를 확장할 수 있었던 것과 같은 것.

...
        wait:
          - service: rabbitmq
            method: container
            timeout: 5
            image: python-test-rabbit
...

는▁calleder▁a▁image▁having▁dock다습있라는 도커 이미지를 가지고 있습니다.python-test-rabbit그게 당신의 수표입니다.

그러면 더 이상 대기 부분을 작업자에게 가져다 줄 필요가 없다는 이점이 있습니다.격리되어 오케스트레이션 계층 내부에 유지됩니다.

누군가 이것을 사용하는 것이 도움이 될 수 있습니다.어떤 제안이든 환영합니다.

이 도구는 https://gitlab.com/michapoe/docker-compose-profile 에서 찾을 수 있습니다.

에 다은예입다니음▁where▁example다가 있는 예가 있습니다.main가 컨이너대시간기를 기다립니다.worker 응답을 때:ping대 한 응 을 작 때 할 시 :

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

그러나 올바른 방법은 (>=2.1)을 사용하는 것입니다.

도커 사람들은 정말로 우리가 자신의 이미지에 있는 코드를 사용하여 서비스를 기다리기를 원하는 것 같습니다. 에서대도서구합성니다고에서 .docker-compose.yml진입점 스크립트를 사용하려는 경우 한 가지 방법이 있습니다.

이미지에 포함된 대기 도구를 사용하여 진입점 스크립트에 이 루프를 추가합니다.저는 https://github.com/vishnubob/wait-for-it/ 을 사용하고 있습니다.서비스를 전달하지 않으면 루프는 아무것도 수행하지 않습니다.

for service in "$@"; do
    echo "$0: wait for service $service"
    if ! wait-for-it "$service"; then
        echo "$0: failed on service $service"
        exit 1
    fi
done

에 이 합니다.docker-compose.yml:

    command: ["my-data-svc:5000"]

이것은 도커 명령이 진입점 스크립트에 인수로 전달되는 동작에 의존합니다.제가 여기서 도커 사령부의 의도를 악용하고 있다는 설득력 있는 주장을 하실 수 있을 겁니다.저 언덕에서 죽지는 않을 거예요. 저한테는 효과가 있을 뿐이에요.

저는 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

언급URL : https://stackoverflow.com/questions/31746182/docker-compose-wait-for-container-x-before-starting-y

반응형