Compose: 더 긴 시작 시간으로 종속 서비스를 지원하기 위해 컨테이너 시작을 지연하는 방법이 있습니까?

에 만든 2014년 08월 05일  ·  314코멘트  ·  출처: docker/compose

데이터를 가져와야하므로 시작하는 데 약간의 시간이 걸리는 MySQL 컨테이너가 있습니다.

MySQL 컨테이너에 의존하는 Alfresco 컨테이너가 있습니다.

현재 fig를 사용할 때 Alfresco 컨테이너 내부의 Alfresco 서비스는 MySQL 컨테이너에 연결하려고 할 때 실패합니다. 표면 상으로는 MySQL 서비스가 아직 수신하지 않기 때문입니다.

Fig에서 이런 종류의 문제를 처리하는 방법이 있습니까?

가장 유용한 댓글

그래, 나는 이것에 관심이있다.

내가 생각할 수있는 가장 작은 영향 패턴은 우리를 위해이 사용 사례를 고칠 것입니다.

링크와 유사한 값 의미를 사용하여 "wait"를 fig.yml에 새 키로 추가합니다. Docker는 이것을 전제 조건으로 취급하고 계속 진행하기 전에이 컨테이너가 종료 될 때까지 기다립니다.

따라서 내 도커 파일은 다음과 같습니다.

db:
  image: tutum/mysql:5.6

initdb:
  build: /path/to/db
  link:
    - db:db
  command: /usr/local/bin/init_db

app:
  link:
    - db:db
  wait:
    - initdb

실행중인 앱에서 모든 링크 컨테이너를 시작한 다음 대기 컨테이너를 실행하고 대기 컨테이너 (initdb)가 종료 된 후에 만 ​​실제 앱 컨테이너로 진행합니다. initdb는 데이터베이스를 사용할 수있을 때까지 대기하는 스크립트를 실행 한 다음 초기화 / 마이그레이션 / 무엇이든 실행 한 다음 종료합니다.

어쨌든 그것은 내 생각입니다.

모든 314 댓글

직장에서 우리는 링크가 아직 작동하는지 확인하는 스크립트로 종속 서비스를 래핑합니다. 내 동료 중 한 명이 이것에도 관심이 있다는 것을 알고 있습니다! 개인적으로 서비스를 사용할 수 있기를 기다리는 것이 컨테이너 수준의 우려라고 생각하지만 틀릴 수 있습니다. :)

우리는 포장도 똑같이합니다. https://github.com/dominionenterprises/tol-api-php/blob/master/tests/provisioning/set-env.sh 에서 예제를 볼 수 있습니다.

모든 링크를 반복하고 전달 된 명령을 시작하기 전에 작동 할 때까지 대기하는 진입 점 스크립트가 있으면 편리합니다.

이것은 Docker 자체에 내장되어야하지만 해결책은 없습니다. 노출 된 링크가 열릴 때까지 컨테이너가 시작된 것으로 간주해서는 안됩니다.

@bfirsh 는 내가 상상했던 것보다 많지만 훌륭 할 것입니다.

노출 된 링크가 열릴 때까지 컨테이너가 시작된 것으로 간주해서는 안됩니다.

나는 그것이 사람들에게 정확히 필요한 것이라고 생각합니다.

지금은 https://github.com/aanand/docker-wait 의 변형을 사용하겠습니다.

그래, 나는 이것에 관심이있다.

내가 생각할 수있는 가장 작은 영향 패턴은 우리를 위해이 사용 사례를 고칠 것입니다.

링크와 유사한 값 의미를 사용하여 "wait"를 fig.yml에 새 키로 추가합니다. Docker는 이것을 전제 조건으로 취급하고 계속 진행하기 전에이 컨테이너가 종료 될 때까지 기다립니다.

따라서 내 도커 파일은 다음과 같습니다.

db:
  image: tutum/mysql:5.6

initdb:
  build: /path/to/db
  link:
    - db:db
  command: /usr/local/bin/init_db

app:
  link:
    - db:db
  wait:
    - initdb

실행중인 앱에서 모든 링크 컨테이너를 시작한 다음 대기 컨테이너를 실행하고 대기 컨테이너 (initdb)가 종료 된 후에 만 ​​실제 앱 컨테이너로 진행합니다. initdb는 데이터베이스를 사용할 수있을 때까지 대기하는 스크립트를 실행 한 다음 초기화 / 마이그레이션 / 무엇이든 실행 한 다음 종료합니다.

어쨌든 그것은 내 생각입니다.

(개정, 아래 참조)

여기도 +1. 명령 자체에서이 작업을 수행해야하는 것은 그리 매력적이지 않습니다.

+1도합니다. 이 문제가 발생했습니다. 훌륭한 도구 btw는 내 인생을 훨씬 쉽게 만듭니다!

+1이 있으면 좋을 것입니다.

+1도합니다. 최근에 동일한 문제가 발생했습니다.

+1도합니다. dockerguys의 진술이 있습니까?

나는 래퍼 스크립트를 현재 동기화 할 진입 점으로 작성하고 있는데, 다른 방식으로 오케스트레이션을 수행하는 컨테이너에 대한 다른 대상이 있다면 fig에 메커니즘이있는 것이 현명한 지 확실하지 않습니다. 작업을 수행하는 컨테이너의 책임과 같이 저에게 매우 특정한 응용 프로그램으로 보입니다.

약간의 생각과 실험 끝에 나는 이것에 동의합니다.

이러한 응용 프로그램은 기본적으로 동기식
응용 프로그램의 서비스를 기다릴 수있는 waitfor (host, port) 함수
(환경을 통해 감지되거나 명시 적으로
CLI 옵션을 통한 구성).

건배
제임스

James Mills / prologic

E : [email protected]
W : prologic.shortcircuit.net.au

2014 년 8 월 22 일 금요일 오후 6:34, Mark Stuart [email protected]
썼다 :

현재 동기화 할 진입 점으로 래퍼 스크립트를 작성하고 있습니다.
다른 타겟이 있다면 무화과에 메커니즘을 갖는 것이 현명한 지 확실하지 않습니다.
다른 방식으로 오케스트레이션을 수행하는 컨테이너. 매우 보인다
컨테이너의 책임과 같은 나에게 특정한 응용 프로그램
일을.


이 이메일에 직접 답장하거나 GitHub에서 확인하세요.
https://github.com/docker/fig/issues/374#issuecomment -53036154.

네, 여기에 몇 가지 기본적인 "종속"이 필요합니다 ...
그래서 만약 당신이 20 개의 컨테이너를 가지고 있다면, 당신은 fig up을 실행하고 싶지 않고 모든 것이 올바른 순서로 시작됩니다.
그러나 일부 시간 초과 옵션 또는 기타 실패 포착 메커니즘도 있습니다.

여기에 또 다른 +1. Postgres를 시작하는 데 Django보다 오래 걸리므로 해커가없는 마이그레이션 명령을위한 DB가 없습니다.

@ahknight 흥미 롭습니다. run 동안 마이그레이션이 실행되는 이유는 무엇입니까?

build 단계에서 실제로 마이그레이션을 실행하고 싶지 않습니까? 이렇게하면 새로운 이미지를 훨씬 빠르게 시작할 수 있습니다.

아아, 문제의 응용 프로그램에 대한 더 큰 시작 스크립트가 있습니다. 지금은 비 DB 작업을 먼저 수행하고 루프에서 nc -w 1 를 사용하여 DB를 기다린 다음 DB 작업을 수행합니다. 작동하지만 더럽게 느껴집니다.

저는 fig build 단계에서이 작업을 성공적으로 수행했습니다. django 프로젝트 (아직 진행중인 작업)에 대한 한 가지 예가 있습니다. https://github.com/dnephin/readthedocs.org/blob/fig-demo/dockerfiles/database/Dockerfile#L21

시작을 위해 폴링 할 필요가 없습니다. mysql과 비슷한 작업을 수행했지만 mysqld init 스크립트가 아직 수행하지 않았기 때문에 시작을 위해 폴링해야했습니다. 이 postgres init 스크립트가 훨씬 더 나은 것 같습니다.

내가 생각한 것은 다음과 같습니다.

docker / docker # 7445 아이디어를 사용하여 그림에서 "wait_for_helth_check"속성을 구현할 수 있습니까?
그렇다면 Docker 문제가 아닌 무화과일까요?

어쨌든 fig가 연결된 컨테이너의 tcp 상태를 확인하도록 만드는 것이 있습니까? 그렇다면 이것이 갈 길이라고 생각합니다. =)

@dnephin 당신이 이것을 돕기 위해 Dockerfiles에서 무엇을하고 있는지 조금 더 설명 할 수 있습니까?
빌드 단계가 런타임에 영향을 줄 수 없습니까?

@docteurklein 할 수 있습니다. 위에서 링크를 수정했습니다 (https://github.com/dnephin/readthedocs.org/blob/fig-demo/dockerfiles/database/Dockerfile#L21).

아이디어는 빌드 중에 느린 "설정"작업을 모두 수행하므로 컨테이너 시작 중에 아무것도 기다릴 필요가 없다는 것입니다. 데이터베이스 또는 검색 색인의 경우 다음을 수행합니다.

  1. 서비스 시작
  2. 사용자, 데이터베이스, 테이블 및 고정물 데이터 생성
  3. 서비스 종료

모두 단일 빌드 단계로. 나중에 데이터베이스 컨테이너를 fig up 하면 기본적으로 즉시 사용할 수 있으며 이러한 느린 작업을 위해 docker 빌드 캐시를 활용할 수도 있습니다.

좋은! 감사 :)

@dnephin 멋지다, 그것을 생각하지 않았다.

+1 이것은 꼭 필요합니다.
추악한 시간 지연 해킹은 대부분의 경우 충분하지만 _real_ 솔루션은 환영 할 것입니다.

왜 / 언제 필요한지 예를 들어 주시겠습니까?

사용 사례에서는 Elasticsearch 서버와 Elasticsearch에 연결되는 애플리케이션 서버가 있습니다. Elasticsearch를 가동하는 데 몇 초가 걸리므로 Elasticsearch 서버에 연결할 때 응용 프로그램 서버가 즉시 실패하기 때문에 fig up -d 간단히 수행 할 수 없습니다.

한 컨테이너가 MySQL을 시작하고 다른 컨테이너가 MySQL이 필요한 앱을 시작하고 다른 앱이 더 빨리 시작한다고 가정 해 보겠습니다. 그 때문에 일시적인 fig up 실패가 있습니다.

crane 은 개별적으로 시작할 수있는 그룹을 만들 수있는 방법을 제공합니다. 따라서 MySQL 그룹을 시작하고 5 초간 기다린 다음 이에 의존하는 다른 작업을 시작할 수 있습니다.
소규모로 작동하지만 실제 솔루션은 아닙니다.

@oskarhane 이 "5 초 기다리기"가 도움이되는지 확실하지 않습니다. 어떤 경우에는 더 기다려야 할 수도 있습니다 (또는 5 초를 넘지 않을 것이라고 확신 할 수 없음) ... 기다리는 시간에 의존하십시오.
또한 수동으로 대기하고 다른 그룹을로드해야합니다. 이것은 일종의 절름발이입니다. fig는이를 대신해야합니다. = /

@oskarhane , @dacort , @ddossot : 현실 세계에서 모든 것이 충돌하고 다시 시작되고 네트워크 연결이 왔다가 사라지는 등을 명심하십시오. Fig이 TCP 소켓에서 대기하는 데 편리함을 도입하든 그렇지 않든 컨테이너는 연결 실패에 탄력적입니다. 그렇게하면 어디서나 제대로 작동합니다.

맞습니다.하지만 시작시 중요한 리소스 (예 : DB)의 부재에서 정상적으로 복구하는 것과 같은 작업을 수행하도록 기존의 모든 앱을 수정하기 전까지 (Great Thing ™이지만 안타깝게도 프레임 워크에서 거의 지원하지 않음) fig start 대신 지연된 특정 순서로 개별 컨테이너를 시작하려면 fig up .

docker를 제어하기 위해 fig를 제어하는 ​​쉘 스크립트를 볼 수 있습니다.

나는 이것이 무화과에 내장되어 있지 않지만 준비 상태를 기다리는 모범 사례에 대한 몇 가지 조언이 좋을 것입니다.

이전 주석에서 링크 된 일부 코드에서이 작업이 수행되는 것을 보았습니다.

while ! exec 6<>/dev/tcp/${MONGO_1_PORT_27017_TCP_ADDR}/${MONGO_1_PORT_27017_TCP_PORT}; do
    echo "$(date) - still trying to connect to mongo at ${TESTING_MONGO_URL}"
    sleep 1
done

내 경우에는 /dev/tcp 경로가 없지만 다른 Linux 배포판 (?) 일 수 있습니다.-우분투에 있습니다.

대신 제대로 작동하는 것 같은 방법을 찾았습니다.

until nc -z postgres 5432; do
    echo "$(date) - waiting for postgres..."
    sleep 1
done

이것은 작동하는 것처럼 보이지만 견고하다는 것을 알기에는 그런 것들에 대해 충분히 알지 못합니다 ... nc 까지 표시되는 포트와 postgres 서버 _really_ 허용 할 수있는 포트 사이에 가능한 경쟁 조건이 있는지 아는 사람이 있습니까? 명령?

수표를 뒤집을 수 있다면 더 기쁠 것입니다. 종속 컨테이너에서 폴링하는 대신 대상 (즉, postgres 서버) 컨테이너에서 모든 종속 자에게 신호를 보내는 것이 가능합니까?

어리석은 생각 일 수도 있고, 누구 생각이 있으신가요?

@anentropic Docker 링크는 단방향이므로 다운 스트림 컨테이너에서 폴링하는 것이 현재 유일한 방법입니다.

nc에 표시되는 포트와 postgres 서버가 실제로 명령을 수락 할 수있는 사이에 가능한 경쟁 조건이 있는지 아는 사람이 있습니까?

일반적인 경우를 알 수있는 방법이 없습니다. postgres의 경우 사실 일 수 있고 다른 서비스의 경우 거짓 일 수 있습니다.

@aanand 도커 / 대기 이미지 접근 방식을 사용해 보았지만 무슨 일이 일어나고 있는지 잘 모르겠습니다. 그래서 기본적으로 다른 NodeJS 앱 컨테이너가 연결되는 "Orientdb"컨테이너가 있습니다. 이 orientdb 컨테이너는 TCP 포트에서 수신 대기를 시작하는 데 약간의 시간이 걸리며 이로 인해 다른 컨테이너에서 "연결 거부"오류가 발생합니다.

대기 컨테이너를 Orientdb에 연결하면이 오류가 표시되지 않기를 바랐습니다. 그러나 불행히도 나는 여전히 무작위로 받고 있습니다. 내 설정은 다음과 같습니다 (Ubuntu 14.04 Box의 Docker 버전 1.4.1, 그림 1.0.1).

orientdb:
    build: ./Docker/orientdb
    ports:
        -   "2424:2424"
        -   "2480:2480"
wait:
    build: ./Docker/wait
    links:
        - orientdb:orientdb
....
core:
    build:  ./Docker/core
    ports:
        -   "3000:3000"
    links:
        -   orientdb:orientdb
        -   nsqd:nsqd

도움을 주시면 감사하겠습니다. 감사.

@mindnuts wait 이미지는 데모에 가깝 습니다. fig.yml 에서 사용하기에 적합하지 않습니다. core 컨테이너에서 동일한 기술 (반복 폴링)을 사용하여 기본 프로세스를 시작하기 전에 orientdb 컨테이너가 시작될 때까지 기다려야합니다.

+1은 사용자 정의 빌드 이미지를 가져 오는 대신 fig.yml에서 빌드하기 시작했습니다. mongodb가 아직 준비되지 않았기 때문에 노드 앱이 실패합니다 ...

Docker를 사용하여 WordPress를 수동으로 시작할 때 MySQL에 도달 할 수있는 이유와 Fig로 시작할 때 오프라인 인 이유를 디버깅하는 데 몇 시간을 보냈습니다. 이제는 응용 프로그램을 시작할 때마다 Fig가 항상 MySQL 컨테이너를 다시 시작한다는 것을 깨달았으므로 WordPress entrypoint.sh가 죽습니다. 아직 MySQL에 연결할 수 없습니다.

실제 entrypoint.sh를 실행하기 전에 5 초 동안 대기하는 재정의 된 entrypoint.sh를 추가했습니다. 그러나 분명히 이것은 Docker / Fig와 함께 MySQL + WordPress 컨테이너 조합을 쉽게 시작할 수 있어야한다면 일반적인 솔루션이 필요한 사용 사례입니다.

따라서 WordPress entrypoint.sh는 아직 MySQL에 연결할 수 없습니다.

WordPress 컨테이너의 문제라고 생각합니다.

처음에는이 아이디어의 팬 이었지만 https://github.com/docker/docker/issues/7445#issuecomment -56391294를 읽은 후 이러한 기능이 잘못된 접근 방식이라고 생각하고 실제로 나쁜 관행을 장려합니다.

이 문제가 해결하고자하는 두 가지 경우가있는 것 같습니다.

일부 초기화를 수행하려면 종속성 서비스를 사용할 수 있어야합니다.

모든 컨테이너 초기화는 실제로 build 동안 수행되어야합니다. 이렇게하면 캐시에 저장되며 이미지의 모든 사용자가 작업을 반복 할 필요가 없습니다.

연결을 열 수 있도록 종속성 서비스를 사용할 수 있어야합니다.

응용 프로그램은 실제로 연결 실패에 대해 탄력적이어야하며 연결을 다시 시도해야합니다.

문제의 근원은 서비스가 준비 될 때까지 기다리는 것이 누구의 책임인지에 대한 기본 규칙이 없다는 것입니다. 그러나 그것이 있었다고하더라도 개발자가 모든 초기화 스크립트에 데이터베이스 연결 재 시도를 추가 할 것이라고 기대하는 것은 약간 비현실적이라고 생각합니다. 이러한 스크립트는 방금 마운트 된 빈 데이터 볼륨을 준비하는 데 종종 필요합니다 (예 : 데이터베이스 생성).

응용 프로그램 컨테이너를 다시 시작할 때 Fig가 항상 연결된 컨테이너 (즉, 데이터베이스 서버)를 다시 시작하지 않았다면 문제는 실제로 훨씬 덜 방해가 될 것입니다. 왜 그런지 모르겠습니다.

응용 프로그램 컨테이너를 다시 시작할 때 Fig가 항상 연결된 컨테이너 (즉, 데이터베이스 서버)를 다시 시작하지 않았다면 문제는 실제로 훨씬 덜 방해가 될 것입니다. 왜 그런지 모르겠습니다.

실제로는 컨테이너를 _ 다시 시작 _하는 것이 아니라 컨테이너를 _ 파괴하고 다시 만듭니다 _. fig.yml 대한 변경 사항을 적용하는 가장 간단한 방법이기 때문입니다. 결국 "현재 구성"을 "원하는 구성"과 비교하고 변경된 사항 만 다시 생성 할 수있는 더 스마트 한 솔루션을 구현해야합니다.

원래 문제로 돌아가서 컨테이너에 연결 재시도 논리가있을 것으로 기대하는 것이 비현실적이라고 생각하지 않습니다. 작동하는 분산 시스템을 설계하는 데 필수적입니다. 다른 스크립트에서 공유해야하는 경우 실행 파일 (또는 셸을 사용하지 않는 경우 언어 별 모듈)으로 팩토 아웃해야하므로 각 스크립트는 상단에서 waitfor db 만 호출 할 수 있습니다.

@kennu --no-recreate 어떻습니까? / cc @aanand

@aanand 나는 Docker Hub의 관점에서 볼 때 비현실적인 주석이 이미 초기화 스크립트에서 연결 재 시도를 처리하지 않는 게시 된 이미지로 가득 차 있으며 모든 사람이 추가하도록하는 것은 상당한 작업이 될 것임을 의미했습니다. 그러나 Docker Inc가 일종의 공식 지침 / 요구 사항을 게시하면 가능할 것 같습니다.

개인적으로 저는 컨테이너 / 이미지를 단순하게 유지하고 기본 시스템이 종속성 해결에 대해 걱정하도록하고 싶습니다. 실제로 Docker의 다시 시작 정책은 이미 모든 것을 해결할 수 있습니다 (애플리케이션 컨테이너가 데이터베이스에 연결하지 못하면 데이터베이스를 사용할 수있을 때까지 다시 시작하고 다시 시도합니다).

그러나 재시작 정책에 의존한다는 것은 기본적으로 활성화되어야 함을 의미합니다. 그렇지 않으면 사람들이 문제를 디버깅하는 데 몇 시간을 소비합니다 (방금처럼). 예를 들어 Kubernetes는 포드의 경우 RestartPolicyAlways로 기본 설정됩니다.

이것에 대한 진전이 있습니까? 나는 모든 도커 이미지가 변경되고 전체 커뮤니티가 연결 재시도 관행을 구현할 것으로 기대하는 것이 합리적이지 않다는 것을 반향하고 싶습니다. Fig는 Docker 오케스트레이션 도구이며 문제는 작업 순서에 있으므로 Docker 또는 커뮤니티가 아닌 Fig에서 변경해야합니다.

모든 도커 이미지가 변경되고 전체 커뮤니티가 연결 재시도 사례를 구현할 것으로 예상하는 것은 합리적이지 않습니다.

docker 또는 fig 때문에 응용 프로그램을 다시 시도해야하는 것은 아닙니다. 네트워크가 안정적이지 않기 때문에 응용 프로그램은 끊어진 연결에 대해 복원력이 있어야합니다. 모든 응용 프로그램은 이미 이러한 방식으로 구축되어 있어야합니다.

개인적으로 컨테이너에서 재 시도를 구현할 필요가 없었으며 시작시 지연이나 대기도 필요하지 않았습니다. 나는이 문제의 대부분의 경우 가이 두 가지 범주에 속 한다고 생각합니다 ( "재시도"를 사용하는 것은 아마도 여기에서 좋지 않을 것입니다. 연결이 닫히면 연결을 다시 설정하고 여러 시도를 시도하는 일정 기간 동안 반드시 폴링하지 않음을 의미합니다.) 타임스).

모든 초기화가 "빌드"단계 중에 발생하고 다음 요청에서 연결이 다시 설정되었는지 확인하는 경우 다시 시도하거나 다른 컨테이너가 시작될 때까지 기다릴 필요가 없습니다. 연결이 느리게 열리면 (첫 번째 요청이있을 때), 열심히 (시작하는 동안) 대신 다시 시도 할 필요가 없다고 생각합니다.

문제는 [fig]가 일을하는 순서에 있습니다.

나는 지금까지이 토론에서 그것에 대한 언급을 보지 못했습니다. Fig는 구성에 지정된 링크를 기반으로 시작 순서를 지정하므로 항상 올바른 순서로 컨테이너를 시작해야합니다. 주문이 잘못된 테스트 케이스를 제공 할 수 있습니까?

여기서 @dnephin 에 동의

Compose / Fig는 이러한 결정을 내릴 수 없으며 모니터링 서비스는 컨테이너 내부에서 실행되는 애플리케이션의 책임이어야합니다.

@dnephin 이 단지 운이 좋았다고 제안하고

또한 WordPress 초기화 예제를 반복하고 싶습니다. MySQL 컨테이너에 아직 새 데이터베이스가없는 경우 새 데이터베이스를 만드는 시작 셸 스크립트를 실행합니다 (Docker 이미지를 빌드 할 때 수행 할 수 없습니다. 외부 마운트 데이터 볼륨). 이러한 스크립트는 일반 데이터베이스 오류와 "데이터베이스가 아직 준비되지 않음"오류를 구분하고 셸 스크립트 내에서 정상적인 재시도 논리를 구현해야하는 경우 훨씬 더 복잡해집니다. 이미지 작성자가 실제로 해당 경쟁 조건에 대해 시작 스크립트를 테스트하지 않을 가능성이 높습니다.

그럼에도 불구하고 Docker의 기본 제공 다시 시작 정책은 컨테이너가 산발적으로 시작되지 않고 정기적으로 로그에 오류를 인쇄 할 준비가 된 경우 이에 대한 해결 방법을 제공합니다. (그리고 당신이 그것을 켜는 것을 기억한다면.)

개인적으로 나는 Fig가 연결된 컨테이너에 노출되는 컨테이너 포트를 자동 감지하고 연결된 컨테이너를 시작하기 전에 핑 (정상적인 시간 제한 사용)하고 궁극적으로이 기능을 재정의 / 비활성화하는 구성 설정을 제공하여 Things Just Work를 만들 것입니다.

Docker 이미지를 빌드 할 때는 외부에 마운트 된 데이터 볼륨에 의존하기 때문에이 작업을 수행 할 수 없습니다.

진실. 여기서 접근 방식은 데이터베이스 컨테이너를 한 번만 시작 (필요한 경우 다른 진입 점 / 명령 사용)하거나 데이터베이스를 초기화하거나 데이터베이스 컨테이너 자체와 동일한 이미지에서 생성 된 데이터베이스에 데이터 전용 컨테이너 를 사용하는 것입니다.

이러한 스크립트는 일반 데이터베이스 오류와 "데이터베이스가 아직 준비되지 않음"오류를 구분해야하는 경우 훨씬 더 복잡해집니다.

Compose / Fig에서 같은 문제가 발생합니다. MySQL이 작동하고 _accepting_ 연결인지 확인하는 방법은 무엇입니까? (및 PostgreSQL 및 (_ 여기에 서비스 삽입 _)). 또한 _where_ "ping"을 실행해야합니까? 시작하는 컨테이너 내부에서 호스트에서?

내가 알 수있는 한, 공식 WordPress 이미지에는 MySQL이 docker-entrypoint.sh 에서 연결을 수락하는지 확인하는 검사가 포함되어 있습니다.

@thaJeztah 2 일 전에 tianon이 작성한 "MySQL 연결 오류를위한 PHP에 간단한 재시도 로직 추가" -Nice. :-) 누가 알겠습니까, 아마도 이것이 결국 표준 접근 방식이 될 것입니다. 그러나 저는 특히 모든 이미지 작성자가 실제로 테스트 한 이러한 종류의 재시도 구현에 대해 여전히 의구심을 가지고 있습니다.

포트 핑에 대해-최적의 구현이 무엇인지 직접 말할 수는 없습니다. 임시 연결된 컨테이너에서 간단한 연결을 확인하고 ECONNREFUSED를 얻는 동안 재 시도하는 것 같습니다. 무엇이든 문제의 80 % (또는 99 %)를 해결하므로 사용자가 매번 스스로 문제를 해결할 필요가 없습니다.

@kennu 아! 감사합니다. 최근에 추가 된 것을 몰랐습니다.이 토론으로 인해 지금 스크립트를 확인했습니다.

명확하게 말하면, 나는 당신이 겪고있는 문제를 이해하지만 Compose / Fig가 모든 사람에게 (그리고 안정적으로) 작동하는 깨끗한 방식으로 문제를 해결할 수 있을지 모르겠습니다. 레지스트리에있는 많은 이미지에 이러한 문제를 처리 할 수있는 "안전 장치"가 없다는 것을 알고 있지만이를 수정하는 것이 Compose / Fig의 책임인지 의심 스럽습니다.

위에 말한 것; 나는 이것을 Dockerfile 모범 사례 섹션에 문서화하는 것이 좋을 것이라고 생각합니다.

사람들은이를 인식하고 서비스 "정지"를 처리하는 방법을 설명하기 위해 몇 가지 예를 추가해야합니다. @dnephin이 참조를 위해 언급 한 WikiPedia 기사 (및 가능한 다른 출처)에 대한 링크 포함.

나는 같은 문제에 부딪 쳤고 @kennu 의이 아이디어를

Personally, I would make Things Just Work, by making Fig autodetect which container ports are exposed to a linked container, ping them before starting the linked container (with a sane timeout), and ultimately provide a configuration setting to override/disable this functionality.

나는 이것이 공식 mongodb 컨테이너에 의존 할 때와 같은 많은 일반적인 사용 사례를 해결할 것이라고 생각합니다.

@soupdiver에 동의합니다. 또한 mongo 컨테이너와 관련하여 문제가 있습니다. start.sh 스크립트로 작업하고 있지만 스크립트는 매우 동적이 아니며 내 저장소에 보관해야하는 다른 파일을 추가합니다 (그냥 내 노드 저장소의 Dockerfile 및 docker-compose.yml). 그냥 작동시키는 방법이 있다면 좋겠지 만, 대부분의 경우 대기 타이머와 같은 간단한 방법으로는 문제가 해결되지 않을 것 같습니다.

기본 네트워크 연결을 사용할 수 있지만 서비스 자체는 아직 준비되지 않았기 때문에 IMO 핑만으로는 충분하지 않습니다.
이것은 예를 들어 MySQL 이미지의 경우입니다. 노출 된 포트에 대한 연결 확인을 위해 curl 또는 telnet을 사용하는 것이 더 안전 할 수 있지만 충분한 지 여부는 알 수 없습니다. 그러나 대부분의 컨테이너에는 이러한 도구가 기본적으로 설치되어 있지 않습니다.

docker 또는 fig가 이러한 검사를 처리 할 수 ​​있습니까?

docker 또는 fig가 이러한 검사를 처리 할 수 ​​있습니까?

간단히 말해서 : _no_. 여러 가지 이유로

  • 컨테이너 내에서 "ping"을 수행하는 것은 두 번째 프로세스를 실행하는 것을 의미합니다. Fig / Compose는 이러한 프로세스를 자동으로 시작할 수 없으며 Fig / Compose가 _installing_ 소프트웨어 (예 : curl 또는 telnet)를 사용하여 컨테이너를 수정하는 것을 원하지는 않습니다.
  • (이전 의견에서 언급했듯이) 각 서비스는 연결을 수락하고 있는지 / 사용할 준비가되었는지 확인하는 다른 방법이 필요합니다. 일부 서비스는 연결을 _ 설정 _하려면 자격 증명이나 인증서가 필요할 수 있습니다. Fig / Compose는 그 방법을 자동으로 발명 할 수 없습니다.

그리고 Fig / Compose가 소프트웨어 (예 : curl 또는 telnet)를 설치하여 컨테이너를 수정하는 것을 원하지는 않을 것입니다.

아니, 당연하지.

Fig / Compose는 그 방법을 자동으로 발명 할 수 없습니다.

발명하지 않습니다. 나는 fig 또는 docker에 대한 지침, 예를 들어 확인하는 방법에 대해 더 많이 생각했습니다.

web:
    image: nginx
    link: db
db:
   is_available: "curl DB_TCP_ADDR:DB_TCP_PORT"

telnet 명령은 컨테이너가 아닌 docker-host에서 실행됩니다.
그러나 나는 큰 소리로 생각하고 있으며 이것이 완벽한 해결책이 아니라는 것을 알고 있습니다. 그러나 컨테이너에 대한 사용자 지정 검사 스크립트를 사용하는 현재 방법은 개선 될 수 있습니다.

telnet 명령은 컨테이너가 아닌 docker-host에서 실행됩니다.

그런 다음 curl 또는 <name a tool that's needed> 호스트에 설치해야합니다. 이것은 심지어 큰 보안 문제를 가질 수 있습니다 (예 : 누군가가 재미 있고 싶어하고 is_available: "rm -rf /" ). 그 외에도 _host_에서 데이터베이스에 액세스 할 수 있다고해서 컨테이너 내부에서도 액세스 할 수 있다는 보장은 없습니다.

그러나 나는 단지 크게 생각하고 있습니다.

알아, 감사합니다. 이를 자동화하는 신뢰할 수있는 방법이 없거나 대부분의 사용 사례를 제공 할 것이라고 생각하십시오. 대부분의 경우 복잡한 문제가 발생합니다 (예 : curl 예를 들어, 연결을 얼마나 오래 시도해야합니까? 재시도?). 이러한 복잡성은 컨테이너 내부로 이동하는 것이 더 낫습니다. 컨테이너가 Fig / Compose가 아닌 Docker로 시작된 경우에도 유용합니다.

@thaJeztah 나는 당신과 전적으로 동의합니다. 그리고 100 % 해결책이 없을 가능성이 매우 높습니다.

앞서 언급 한 제안을 반복하겠습니다. fig.yml에 "이 다른 컨테이너를 실행하기 전에이 컨테이너가 종료 될 때까지 기다리십시오"라고 말할 수 있다면 충분할 것입니다.

이를 통해 포트 확인, 데이터베이스 초기화 등 모든 종속성을 기다리는 방법을 아는 컨테이너를 만들 수 있으며 가능한 한 최소한의 정보 만 필요로합니다.

다음과 같이 구성된 것을 볼 수 있습니다.

"" "
앱:
연결:
-db : db
전제 조건 :
-먼저 실행

runthisfirst :
연결:
-db : db
"" "

runthisfirst에는 액세스를 확인할 수 있도록 데이터베이스가 시작됨을 의미하는 링크가 있습니다. 앱은 runthisfirst가 종료 된 후에 만 ​​실행됩니다 (runthisfirst가 성공적으로 종료되어야하는 경우 보너스 포인트).

이것이 대답으로 실현 가능합니까?

KJL

2015 년 2 월 10 일 05:28에 Tobias Munk [email protected] 은 다음과 같이 썼습니다.

@thaJeztah https://github.com/thaJeztah 나는 당신과 전적으로 동의합니다. 그리고 100 % 해결책이 없을 가능성이 매우 높습니다.


이 이메일에 직접 답장하거나 GitHub https://github.com/docker/fig/issues/374#issuecomment -73561930에서

방금 셸 스크립트 시작 관리자 마이그레이션을 시도했지만이 문제가 발생했습니다. 다음 컨테이너를 시작하기 전에 해당 시간 동안 잠자기 만하는 간단한 잠자기 / 대기 키를 추가하는 것만으로도 좋을 것입니다.

db:
  image: tutum/mysql:5.6
  sleep: 10
app:
  link:
    - db:db

나는 여러 가지 이유로 이것을 정말로 좋아하지 않는다.

a) 나는 이것이 잘못된 장소라고 생각합니다.
b) 얼마나 오래 자십니까?
c) 타임 아웃이 오래 걸리지 않으면 어떻게됩니까?

명백한 문제를 제외하고는 정말 생각하지 않습니다
인프라는 애플리케이션의
이며 그 반대도 마찬가지입니다. IHMO 앱을 작성해야합니다.
자신의 요구 사항에 대해 더 관용적이거나 더 현명합니다.

즉, 기존 애플리케이션과 레거시 애플리케이션
무언가가 필요할 것입니다.
라인 :

docker-compose.yml :

db:
  image: tutum/mysql:5.6
app:
  wait: db
  link:
    - db:db

waitdb "노출 된"서비스를 사용할 수있을 때까지 기다립니다.

문제는 어떻게 결정합니까?

가장 간단한 경우에는 성공적으로 열 수있을 때까지 기다립니다.
노출 된 서비스에 대한 tcp 또는 udp 연결.

이것은이 문제에 대한 과잉 일 수 있지만, 좋은 해결책은도 커가 한 컨테이너에서 트리거를 시작할 수있는 이벤트 트리거 시스템을 제공하여 다른 컨테이너에서 일종의 콜백을 초래 한 경우입니다. 다른 서비스를 시작하기 전에 MySQL 데이터베이스로 데이터 가져 오기를 기다리는 경우 포트를 사용할 수 있는지 모니터링하는 것만으로는 충분하지 않습니다.

진입 점 스크립트가 다른 컨테이너에서 이벤트를 트리거 한 (예 : 미리 정의 된 환경 변수 설정) 컨테이너 내부에서 Docker에 경고를 설정하면 (아마도 동일한 동기화 된 환경 변수 설정) 양쪽의 스크립트가 특정 시점을 알 수 있습니다. 작업이 완료되었습니다.

물론 자체 소켓 서버 나 다른 수단을 설정할 수 있지만 컨테이너 오케스트레이션 문제를 해결하는 것은 지루합니다.

@aanand 내가 가진 _almost_ 뭔가 시작 지점으로 대기 접근 방식을 사용하여 작업을. 그러나 도커-컴 포즈 실행도커 실행 사이에 다른 일이 일어나고 있는데, 여기서 전자는 매달린 것처럼 보이고 나중에는 매력적으로 작동합니다.

docker-compose.yml 예제 :

db:
  image: postgres
  ports:
    - "5432"
es:
  image: dockerfile/elasticsearch
  ports:
    - "9200"
wait:
  image: n3llyb0y/wait
  environment:
    PORTS: "5432 9200"
  links:
    - es
    - db

다음 사용 ...

docker-compose run wait

그러나 이것은 아닙니다. 연결된 서비스가 시작되고 우리는 그것이 질식 할 때까지만 기다릴 것 같습니다 (적어도 내 virtualbox 환경 내에서. 저는 nc 루프에 도달하고 단일 점을 얻었습니다 ... 아무것도 없습니다).

그러나 연결된 서비스를 실행하면이 방법을 사용할 수 있습니다 (본질적으로 CI 빌드를 위해 수행 한 작업입니다).

docker run -e PORTS="5432 9200" --links service_db_1:wait1 --links service_es_1:wait2 n3llyb0y/wait

docker-compose run 같은 방식으로 작동해야하는 것 같습니다. 차이점은 분리 플래그 -d docker-compose run 와 함께

약간의 시행 착오 후에 위의 접근 방식이 작동하는 것 같습니다! busybox base에는 잘 작동하는 netcat 유틸리티가 없습니다. 내 수정 된 버전을 사용하는 경우 @aanand 대기 유틸리티는 고정 표시기-작성 1.1.0에 대한 작업을 수행 docker-compose run <util label> 대신 docker-compose up . 링크에서의 사용 예.

그래도 원래 질문에 따라 체인 상황을 처리 할 수 ​​있는지 확실하지 않습니다. 아마 아닐 것입니다.

당신이 무슨 생각을하는지 제게 알려주세요.

이것은 매우 흥미로운 문제입니다. 한 컨테이너가 다른 컨테이너가 준비 될 때까지 기다리는 방식이 있으면 정말 재미있을 것 같습니다. 그러나 모두가 말했듯이 ready는 무엇을 의미합니까? 제 경우에는 MySQL 용 컨테이너, 백업을 관리하고 초기 데이터베이스 가져 오기를 담당하는 또 다른 컨테이너가 있고 데이터베이스가 필요한 각 앱의 컨테이너가 있습니다. 포트가 노출 될 때까지 기다리는 것만으로는 충분하지 않습니다. 먼저 mysql 컨테이너를 시작하고 나머지는 mysql 서비스를 사용할 준비가 될 때까지 기다려야합니다. 이를 위해 docker exec 기능을 사용하는 재부팅시 실행되는 간단한 스크립트를 구현해야했습니다. 기본적으로 의사 코드는 다음과 같습니다.

run mysql
waitUntil "docker exec -t mysql mysql -u root -prootpass database -e \"show tables\""
run mysql-backup
waitUntil "docker exec -t mysql mysql -u root -prootpass database -e \"describe my_table\""
run web1
waitUntil "dexec web1 curl localhost:9000 | grep '<h1>Home</h1>'"
run web2
waitUntil "dexec web2 curl localhost:9000 | grep '<h1>Home</h1>'"
run nginx

waitUntil 함수에는 docker exec … 명령을 평가하고 종료 코드가 0인지 확인하는 시간 제한이있는 루프가 있습니다.

이를 통해 모든 컨테이너는 종속성을 사용할 준비가 될 때까지 기다립니다.

그래서 compose 유틸리티 내에서 통합하는 옵션이 될 수 있다고 생각합니다. wait_until 는 다른 종속성 (컨테이너) 목록을 선언하고 각 종속성 (컨테이너)이 해당 명령에 정상적으로 응답 할 때까지 (또는 선택적 패턴이나 정규식을 사용하여 결과가 일치하는지 확인하기 위해 기다립니다. grep 명령을 사용하는 것만으로도 충분할 수 있습니다.

mysql:
  image: mysql
  ...
mysql-backup:
  links:
   - mysql
  wait_until:
   - mysql: mysql -u root -prootpass database -e "show tables"
  ...
web1:
  links:
   - mysql
  wait_until:
   - mysql: mysql -u root -prootpass database -e "describe my_table"
  ...
web2:
  links:
   - mysql
  wait_until:
   - mysql: mysql -u root -prootpass database -e "describe my_table"
  ...
nginx:
  links:
   - web1
   - web2
  wait_until:
   - web1: curl localhost:9000 | grep '<h1>Home</h1>'
   - web2: curl localhost:9000 | grep '<h1>Home</h1>'
  ...

그와 같은 항구에 대한 간단한 eait가 아닌가?
http://docs.azk.io/en/azkfilejs/wait.html#

@robsonpeixoto : 많은 사용 사례에서 포트를 기다리는 것만으로는 충분하지 않습니다. 예를 들어 생성시 데이터로 데이터베이스를 시드하고 데이터 작업이 완료 될 때까지 웹 서버가 시작되고 연결되는 것을 원하지 않는다고 가정 해 보겠습니다. 포트는 웹 서버 시작을 차단하지 않도록 항상 열려 있습니다.

AWS CloudFormation의 WaitCondition과 같은 것이 좋을 것입니다. http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/using-cfn-waitcondition.html

+1 MySQL에 의존하는 Rails 앱을 테스트하기 위해 Docker를 사용할 때 동일한 문제가 발생합니다.

+1 나도이 문제가 있습니다. 저는 @adrianhurt 아이디어를 좋아

+1

이 탭을 잠시 열었습니다. http://crosbymichael.com/docker-events.html ... 관련이있는 것 같습니다.

+1

간단한 타임 아웃의 경우 +1

준비 상태의 경우 +1

+1

이 스레드에서 권장했던 것처럼 잠시 이후 애플리케이션 수준에서이 문제를 매우 안정적으로 해결하고 있습니다.

이것이 MySQL + PHP에서 어떻게 구현 될 수 있는지 알려 드리기 위해 여기에 제 코드가 있습니다.

igorw / retry에서 :)

네트워크는 신뢰할 수 있으므로 항상 작동해야합니다. 내가 맞아? 그렇지 않은 경우 다시 시도합니다.

+1

@ schmunk42 좋은 물건-연결을 설정하고 멱등 데이터베이스 설정 작업을 수행하는 좋은 예라는

NodeJS, Ruby, PHP와 같은 다른 경우에 문서에 포함 할 (일부) 기본 예제를 만드는 것이 좋습니다.

+1, 적어도 컨테이너가 성공적으로 시작되기 전에 약간의 지연을 추가하는 몇 가지 옵션을 제공해야합니다.

+1

코드가 아닌 서비스를 연결하려고 할 때 문제를 해결하는 방법.
예를 들어, 서비스 Service 및 데이터베이스 InfluxDB . Services 에는 InfluxDB Services 가 필요하고 InfluxDB 시작 속도가 느립니다.

docker-compose는 InfluxDB 가 준비 될 때까지 어떻게 기다릴 수 있습니까?

나는 코드가 내, 재 시도를 넣어 해결할 수 있습니다. 하지만 세 번째 앱의 경우 코드를 변경할 수 없습니다.

@robsonpeixoto 이 티켓에는 netcat 또는 이와 유사한 방식으로 몇 가지 예가 있습니다. https://github.com/docker/docker/issues/7445#issuecomment -101523662에서 내 MySQL 예제를 살펴볼 수 있습니다.

이것이 각 컨테이너에 자체 준비 상태를 나타내는 선택적 기능이 있어야한다고 생각하는 이유입니다. 예를 들어 DB의 경우 프로세스가 생성 될 때가 아니라 서비스가 완전히 준비 될 때까지 기다리고 싶습니다. 예를 들어 docker exec 로 사용자 지정 검사를 통해이 문제를 해결하고 간단한 쿼리를 해결할 수 있는지 확인합니다.

내부 검사 명령을 나타내는 docker run 에 대한 일부 선택적 플래그는 나중에 링크에 대한 특수 플래그를 사용하여 다른 컨테이너에서 링크하는 것이 좋습니다.

다음과 같은 것 :

$ sudo docker run -d --name db training/postgres --readiness-check /bin/sh -c "is_ready.sh"
$ sudo docker run -d -P --name web --link db:db --wait-for-readiness db training/webapp python app.py

여기서 is_ready.sh 는 컨테이너가 준비된 것으로 간주되는시기를 결정하는 간단한 부울 테스트입니다.

+1

@ schmunk42 좋은 견적!

+1

+1

+1

+1

+1

+1

+1

+1

+1

사실 저는 이것에 대해 마음을 바꿨습니다. 그래서 -1

컨테이너가 타사 서비스를 사용할 수 있는지 확인하는 것이 더 합리적이며 예를 들어 nc 를 사용하는 작은 bash 래퍼 스크립트로 쉽게 수행 할 수 있습니다.

지연에 의존하는 것은 유혹적이지만 다음과 같은 이유로 좋지 않은 솔루션입니다.

  • 컨테이너는 준비되기 전에 _always_ X 초를 기다립니다.
  • X 초는 일부 경우 (예 : 호스트의 과도한 I / O 또는 CPU) 여전히 충분하지 않을 수 있으므로 컨테이너는 여전히 안전하지 않습니다.
  • 실패 전략이 없습니다.

래퍼 bash 스크립트 작성에 의존하는 것이 더 좋습니다.

  • 가능한 한 빨리 컨테이너가 준비됩니다.
  • 실패 전략을 구현할 수 있습니다. 예를 들어 10 번 시도한 다음 실패하고 영원히 시도하는 등의 작업을 수행 할 수 있습니다. 시도하기 전에 잠을 자면서 지연을 구현할 수도 있습니다!

이 스레드를 읽어 보면 아무도 비밀을 언급하지 않는다는 것을 알 수 있습니다. 실행되면 비밀을 요청하는 데이터 전용 컨테이너를 사용하려고합니다. 내가 가진 문제 : 내 비밀이 전송 / 복호화하는 데 너무 오래 걸리면 기대하는 데이터가 없기 때문에 내 종속 컨테이너가 실패합니다. 나는 "잘 실행하기 전에 컨테이너에 모든 것을 넣어 라"는 방법은 비밀이기 때문에 실제로 사용할 수 없습니다.

반환 코드의 컨텍스트로 인해 compose의 데이터 전용 컨테이너에 약간의 모호함이 있음을 알고 있지만 더 좋은 방법이 있습니까?

마찬가지로 이것에 대한 내 마음을 바꾸는 것, -1. @dnephin 의 접근 방식은 전적으로 정확합니다. _application_이 _service_에 의존하는 경우, 애플리케이션 자체가 해당 서비스의 비 가용성을 적절하게 처리 할 수 ​​있어야합니다 (예 : 연결 재설정). Compose 또는 Docker의 일부 bash 래퍼 스크립트 나 로직이 아니어야하며 애플리케이션 자체의 책임입니다. 응용 프로그램 수준이 아닌 것은 초기화에서만 작동합니다. 해당 서비스가 다운되면 래퍼 스크립트 등이 실행되지 않습니다.

이제 애플리케이션 / 라이브러리 / 프레임 워크 개발자가이 책임을 인식하고 지원하도록 할 수 있다면 환상적 일 것입니다.

권장하지 않는 다른 데몬을 사이드로드하는 것과 관련된 접근 방식을 고려하기가 어렵습니다. 다른 rails 앱이 현재 초기 시작시 DB를 마이그레이션하고 시드하는 동안 Rails 앱이 MySQL 데이터베이스에 연결을 시도하는 제 예의 경우, Rails 앱이 DB를 사용하지 않도록 알리기 위해 다음 중 하나를 수행합니다. ActiveRecord 라이브러리를 수정하거나 (발생하지 않음) DB가 마이그레이션되고 시드되었는지 계속 확인하는 스크립트를 실행해야합니다. 그러나 거기에 어떤 데이터가 있어야하는지 알지 못하거나 DB를 시드하는 시스템에서 실행되는 스크립트를 가지고 나머지에 연결하도록 알리지 않고 어떻게 확실히 알 수 있습니까?

아마도 나는 분명한 해결책을 놓치고 있지만 "개발자는 자신의 코드로 이것을 처리 할 수 ​​있어야한다"라는 대답은 선반 라이브러리를 사용할 때와 데몬을 사이드로드 할 "추정"되지 않았을 때 무너진다. 컨테이너.

@mattwallington Compose가 어떻게 그 상황에 대한 해결책을 제공할지 모르겠습니다 ...
그것은 또한 매우 구체적이어서 Compose가 발명하는 것을 더욱 어렵게 만듭니다. 귀하의 경우에 도움이 될 수 있으므로 초기화 / 마이그레이션 / 시드에 대한 위의 @dnephin 팁을 읽을 것입니다.

내 마지막 줄의 요점을 놓친 것 같습니다. 많은 기성 라이브러리가 탄력적으로 구축되지 않았기 때문에 _ 정확하게 _ 작동하지 않습니다. Compose가 구현할 수있는이 모든 것을 해결할 수있는 마법의 솔루션은 없습니다.

알겠습니다. 이러한 많은 사용 사례에서 작동하는 이전의 제안은 컨테이너간에 환경 변수를 공유하는 것입니다. 한쪽은 변수 폴링을 잠글 수 있고 다른 쪽은 작업을 수행 한 다음 변수를 설정할 수 있습니다.

+1 @mattwallington 컨테이너 간 공유 환경 변수 아이디어

감사합니다. 그것은 간단합니다 (제품 수준에서. 저는 코드를 보지 않았기 때문에 개발 측면에서 무엇을 취할지 모르겠습니다). 이 문제.

그러나 거기에 어떤 데이터가 있어야하는지 알지 못하거나 DB를 시드하는 시스템에서 실행되는 스크립트를 가지고 나머지에 연결하도록 알리지 않고 어떻게 확실히 알 수 있습니까?

@mattwallington : 스키마 테이블에서 마이그레이션 번호를 확인합니다. 숫자가 정확하면 마이그레이션이 실행 된 것입니다.

Compose 또는 Docker의 일부 bash 래퍼 스크립트 나 로직이 아니어야하며 애플리케이션 자체의 책임입니다. 응용 프로그램 수준이 아닌 것은 초기화에서만 작동합니다. 해당 서비스가 다운되면 래퍼 스크립트 등이 실행되지 않습니다.

@ agilgur5 : 예, 응용 프로그램에서 처리한다는 데 동의하지만 bash 스크립트는 서비스를 사용할 수 없을 때 응용 프로그램을 다시 시작하는 등의 방식으로 코딩되지 않은 응용 프로그램을 처리하는 간단한 솔루션입니다.

앱 수준에서 무엇을해야하거나 할 수 있는지에 대해 하루 종일 논쟁을 할 수 있지만 시장의 모든 앱이이 문제를 처리하고 자체 복구에 능숙 해지기를 기대하는 대신 (가능성이 낮음) 해결할 수있는 일부 기능 추가에 반대하는 이유는 무엇입니까? 이 문제는 타사 앱이 작성되는 방식이나 수행해야 할 작업에 관계없이 도커에서 실행되는 앱에 대한 문제입니다. 이것이 우리가 통제 할 수있는 것입니다. 우리는 그것을 통제 할 수 없기 때문에 문제를 해결할 사람을 결정하기보다는 문제를 해결합시다.

@mattwallington에 동의합니다. 모든 단일 컨테이너 이미지의 모든 개발자로부터 앱 수준의 자체 복구를 위해이 추가 노력이 필요할 수 있지만, 그중 상당수가 너무 무지하거나 너무 바빠서 신중하게 구현하고 테스트 할 수 없습니다. 최종 결과는 일부 컨테이너는 자체 복구 방법을 알고 있지만 많은 컨테이너는 그렇지 않은 것입니다. 그리고 사용자에게는 그렇지 않은 도구를 관리 할 도구가 없습니다.

내 마음에 떠오른 아이디어 : 컨테이너 시작을 지연시켜 문제를 해결하는 대신 Compose는 실패한 컨테이너를 복구 할 수 있습니다.

recover: auto 같은 것은 실패한 컨테이너를 2, 4, 8, 16, 32 초에 5 번 다시 시작한 다음 완전히 포기합니다.

컨테이너 종속성 컨테이너의 개념에 대해 _ 생각한 사람이 있습니까?

예를 들면 :

```#! yml
db :
이미지 : mysql

기다립니다:
연결:
-db
볼륨 :
-/var/lib/docker.sock:/docker.sock
-$ {PWD} /docker-compose.yml:/docker-compose.yml
명령 : docker-compose up -d app

앱:
이미지 : myuser / myapp
연결:
-db
```

여기서 기본 아이디어는 모든 사람이 구성에 주입 할 수있는 Docker Hub에 게시 할 수있는 재사용 가능한 전용 서비스를 만들어 자체 복구 메커니즘이없는 컨테이너의 문제를 _ 해결 _한다는 것입니다.

나는 그러한 서비스 / 컨테이너 / 이미지의 프로토 타입을 기꺼이 _하고 싶고, 다른 사람들이 이것으로 어떻게 벌어지는 지 알아 보도록하겠습니다.

@prologic 의존성의 문제는 당신이 말하고 싶은 서비스가 실제로 작동하는지 어떻게 확인 하는가입니다.

db 컨테이너는 ping 응답 할 수 있지만 실제로 mysql / psql 명령에 사용할 수 있기 전에 데이터베이스를 사전 실행 정리 / 초기화하고 있습니다.

해당 테스트를 구성 가능한 방식으로 정의하거나 재사용 가능한 waitfor 유형 서비스에 스크립트로 제공 할 수 있습니까?

IMHO, 이것은 매우 일반적인 문제이며 모든 사람이 자신의 특정 요구 사항을 가지고 있습니다. 이 문제에서 앞서 언급했듯이, Docker는 컨테이너가 자신의 준비 상태를 확인하는 간단한 명령을 지정하는 방법을 제공 할 수 있다고 생각합니다. 분명히 우리는 개발자로서 각 컨테이너의 준비 상태를 확인하는 방법을 구체적으로 표시해야합니다.

내부 검사 명령을 나타 내기 위해 docker 실행에 대한 일부 선택적 플래그는 나중에 링크에 대한 특수 플래그를 사용하여 다른 컨테이너에서 링크하는 것이 좋습니다.

다음과 같은 것 :

$ sudo docker run -d --name db training/postgres --readiness-check /bin/sh -c "is_ready.sh"
$ sudo docker run -d -P --name web --link db:db --wait-for-readiness db training/webapp python 

is_ready.sh는 컨테이너가 준비된 것으로 간주되는시기를 결정하는 간단한 부울 테스트입니다.

컨테이너가 준비 상태를 수동으로 확인하는 명령 일 수도 있습니다.

is_ready.sh는 컨테이너가 준비된 것으로 간주되는시기를 결정하는 간단한 부울 테스트입니다.

즉, 모든 개발자는 컨테이너가 준비되었는지 확인하는 데 사용할 수있는 _something_을 포함하도록 이미지 / 컨테이너를 준비해야합니다.

그러면 우리는 다시 제곱 1로 돌아갑니다. 개발자는 자신의 상황에 대해 "무엇을"의미하는지 알 수있는 유일한 사람이기 때문에 서비스 중단 / 시작 시간에 대해 컨테이너를 복원 할 책임이있는 사람입니다.

아니면 여기서 뭔가를 간과하고 있습니까?

나는 동의한다. 책임은 개발자 / 컨테이너 / 서비스에 있습니다.

2015 년 7 월 30 일 목요일, Sebastiaan van Stijn [email protected]
썼다 :

is_ready.sh는 다음을 담당하는 간단한 부울 테스트입니다.
용기가 준비된 것으로 간주되는시기의 결정.

이는 모든 개발자가 자신의 이미지 / 컨테이너를 준비해야 함을 의미합니다.
컨테이너가 있는지 확인하는 데 사용할 수있는 _something_ 포함
준비된.

그러면 우리는 다시 제곱 1로 돌아갑니다. 개발자는 책임이 있습니다
서비스 중단 / 시작 시간에 컨테이너를 복원 할 수 있습니다.
그들이 자신의 상황에 대해 "무엇을"의미하는지 말할 수있는 유일한 사람입니까?

아니면 여기서 뭔가를 간과하고 있습니까?


이 이메일에 직접 답장하거나 GitHub에서 확인하세요.
https://github.com/docker/compose/issues/374#issuecomment -126278215.

James Mills / prologic

E : [email protected]
W : prologic.shortcircuit.net.au

예, 물론입니다. 나에게 컨테이너가 언제 준비되었는지 실제로 아는 유일한 것은 자체 컨테이너입니다. Docker는 컨테이너의 내용에 대해 아무것도 알 수 없습니다. 블랙 박스입니다. 이것이 할 수있는 유일한 일은 컨테이너에 요청하는 것입니다 (제가 제안한대로 실행하려는 경우 지정된 사용자 지정 작업 또는이를 테스트하는 다른 일반적인 방법). 그리고 분명히 개발자는 그가 필요로하는 것과 블랙 박스의 내용을 아는 유일한 사람입니다.

그래 맞아!

2015 년 7 월 30 일 목요일에 adrianhurt [email protected] 은 다음과 같이 썼습니다.

예, 물론입니다. 저에게있어 컨테이너가 언제인지 아는 유일한 사람은
준비는 자신의 컨테이너입니다. Docker는 내용에 대해 아무것도 알 수 없습니다.
컨테이너. 블랙 박스입니다. 할 수있는 유일한 것은
컨테이너 (나와 같이 실행할 때 지정한 사용자 지정 작업 포함)
제안 또는 기타 일반적인 테스트 방법). 그리고 분명히 개발자
그가 필요로하는 것과 그 블랙 박스의 내용을 아는 유일한 사람입니다.


이 이메일에 직접 답장하거나 GitHub에서 확인하세요.
https://github.com/docker/compose/issues/374#issuecomment -126285056.

James Mills / prologic

E : [email protected]
W : prologic.shortcircuit.net.au

OK-네트워크 장애를 처리 할 수없는 개발중인 모든 소프트웨어 나 레거시 소프트웨어 때문에 결국이 문제를 해결하고 싶다고 가정 해 보겠습니다. 나는 우리가 그렇다고 말하는 것이 아니라 구문, 의미론 및 복잡성에 대한 느낌을 얻고 싶습니다.

최소한의 요구 사항은 다음과 같습니다.

  • Compose가 다른 서비스가 "준비"될 때까지 서비스를 시작하기를 원합니다.
  • "준비"를 "포트 X에서 TCP 연결을 수락 함"또는 다른 것으로 정의하고 싶습니다.

또한 상태 확인이 한동안 Docker에 들어 가지 않을 것이라고 가정 해 보겠습니다.

_ 다른 서비스의 컨테이너가 종료 될 때까지 기다리면 _ 일반적인 경우에 해결할 수 있는지 궁금합니다. 그런 다음 상태 확인을 다른 서비스로 작성할 수 있습니다.

web:
  image: mywebapp
  links: ["db"]
  wait_for: ["db_wait"]

db_wait:
  image: netcat
  links: ["db"]
  command: sh -c "while ! nc -w 1 -z db 5432; do sleep 1; done"

db:
  image: postgres

사용자 지정 상태 확인을 원하면 "대기"서비스에서 정의합니다. 여기에서 db_waitmydb 데이터베이스에 mytable 가있는 경우에만 종료됩니다.

db_wait:
  image: postgres
  links: ["db"]
  command: sh -c "while ! psql --host db --dbname mydb -c "\d mytable"; do sleep 1; done"

먼저 실행할 db 준비 스크립트가있는 경우 대기하도록 만들 수 있습니다.

web:
  image: mywebapp
  links: ["db"]
  wait_for: ["prepare_db"]

prepare_db:
  image: prepare_db
  links: ["db"]
  command: ./prepare.sh

db:
  image: postgres

첫 번째 경우 (컨테이너가 TCP 연결을 수락 할 때까지 기다림)는 기본적으로 지원할 가치가있을만큼 일반적 일 수 있습니다.

web:
  image: mywebapp
  links: ["db"]
  wait_for_tcp: ["db:5432"]

db:
  image: postgres

이 모든 것에는 숨겨진 의미가 있습니다. docker-compose up -d 는 중개 상태 확인 또는 준비 서비스가 실행되는 동안 차단해야하므로 일단 완료되면 소비자 서비스를 시작할 수 있습니다.

예. 그러나 제 생각에는 docker 자체가 컨테이너가 준비된시기를 결정하는 방법을 제공해야하며, 그러면 compose가이를 관리 할 수 ​​있습니다. 그런 다음 docker에서 직접 새로운 문제를 제기 할 수 있습니다. 나를 위해 그것은 다음과 같을 수 있습니다.

web:
  image: mywebapp
  links: ["db"]
  wait_for: ["db"]

db:
  image: postgres
  ready_when: sh -c "while ! psql --host db --dbname mydb -c "\d mytable"; do sleep 1; done"

그러면 해결 방법으로 새 ​​서비스를 만들 필요가 없습니다.

동의합니다. 개발자에게 유연성을 제공하십시오. 또한 컨테이너를 일시 중지하는 것은 개발자가 기다리는 동안 컨테이너가 수행해야하는 작업이 아닐 수도 있습니다. 아마도 발생해야 할 자체 초기화가 있지만 db가 연결 준비가 될 때까지 기다립니다. 따라서 단순한 공유 환경 변수 인 경우 개발자가 필요에 따라 사용할 수 있습니다.

공유 환경 변수는 어떻게 업데이트됩니까? 내가 아는 한, 일단 시작되면 프로세스의 환경 변수 세트를 변경할 수 없습니다.

예를 들어 bash 세션에서 변경할 수 있지만 다른 모든 레이어에 전파되지는 않습니다.

이를 위해 변경 사항을 커밋하고 컨테이너를 다시 시작해야합니다. 이 시나리오에서는 이것은 꽤 쓸모가 없습니다.

또한 변수가 변경 될 수 있더라도 컨테이너의 프로세스는이를 폴링하기 위해 알아야하므로이 기능이 표면적으로 사용되는 레거시 소프트웨어에 대한 솔루션이 아닙니다.

우리는 개발 환경에서 레거시 컨테이너에 대해이 문제를 해결하는 것에 대해서만 이야기하고 있기 때문에 compose docker-compose ps -s (종속성 순서로 서비스 나열, # 1077) 위에있는 도구로 해결할 수 있다고 생각합니다.

이 두 명령을 사용하면 다음과 같은 작업을 수행하는 도구를 작성할 수 있습니다.

  1. docker-compose ps -s 를 실행하여 종속성 순서로 서비스 이름 목록을 가져옵니다.
  2. docker-compose up -d --no-recreate <first service from the list>
  3. 정상 상태가되거나 시간 초과에 도달 할 때까지 해당 서비스에 대해 "healthcheck"명령을 실행합니다. HTTP 요청 또는 docker exec 호출 일 수 있습니다.
  4. 목록의 각 서비스에 대해 2와 3을 반복합니다.
  5. docker-compose logs (또는 -d 이 전달 된 경우 실행하지 않음)

이렇게하면 "healthcheck"및 "wait for"구성이 외부 구성으로 구성 될 수 있지만 구성 자체의 일부로 구현 된 경우 필요한 것보다 더 많은 것을 제공 할 필요는 없다고 생각합니다.

이것이 작동하지 않는 이유는 무엇입니까?

범위를 레거시 컨테이너로 제한했기 때문에 기쁩니다. 훨씬 더 합리적입니다. + 1 :

@dnephin 유연하고 Compose가 레거시 컨테이너에 대한 일부 내장 지원이 필요하지 않다는 즉각적인 관점에서 볼 때 훌륭하다고 생각하지만 @mattwallington이 설명한 것과 유사한 즉각적인 문제가 있습니다. 이 서비스에 연결하기 전에 몇 가지 (예 : init)를 실행 하시겠습니까? 해당 컨테이너에서 _works_ 차단하지만 이상적이지 않습니다 (즉, 레거시 컨테이너에 이상적인 솔루션이 있는지 확실하지 않습니다). 그것은 적어도 내 문제를 해결할 것입니다. 이제 그 티켓을 찾아야합니다!

+1

docker-compose 파일에서 종속성을 지정할 수 있습니다 ...

... 링크를 사용하지 않습니다 (net = host와 호환되지 않기 때문에). 꼭두각시가 자체 종속성 트리를 가지고있는 것처럼, 어떤 순서로 시작해야하는지 아는 것이 작업 또는 적어도 멀티 컨테이너 관리 도구의 관심사라고 생각했을 것입니다.하지만 때로는 사용자가 가장 잘 알고 재정의 할 수 있습니다. 위의 내용을 모두 읽어 보면, 컨테이너가 "업"상태가되어 종속성 체인의 다음 컨테이너가 시작될 수 있는지 결정하는 것이 유일한 어려움 인 것 같습니다. 이것은 링크 메커니즘 (현재로서는)과 똑같은 메커니즘 일 수 있습니다. 아무것도없는 것보다 낫습니다. 나중에 "종속성 충족"에 대한 설명은 예를 들어 docker-compose 파일에 의해 지정 될 수 있습니다.이 종속성은 컨테이너가 실행 중임을 의미합니다.

depends_on:
  container: foo
  requires: running

또는이 종속성은 컨테이너 TCP 포트가 수신하는 것이 중요합니다.

depends_on:
  container: foo
  requires: listening

docker-compose 위에있는 일부 외부 도구 또는 스크립트의 역할이라고 말하는 것은 docker-compose가 동일한 시스템에서 2 개 이상의 컨테이너를 실행하는 조정에 대한 실질적인 관심이나 책임이 없다고 말하는 것과 같습니다. 그래서 그 목적은 무엇입니까?

나는 어떤 순서로 시작해야 하는지를 아는 것이 작업이거나 적어도 멀티 컨테이너 관리 도구의 관심사라고 생각했을 것입니다.

아니요, 반드시 그런 것은 아닙니다. 이 스레드에 이미 여러 번 제시된 이유 때문에이 작업을 컨테이너 관리 도구에 넘겨 줄 이유는 두 가지 뿐이라고 생각합니다.

  1. 의존하는 업스트림 서비스를 사용할 수없고 기술 또는 비즈니스 이유로 인해 변경하거나 확장 할 수없는 기성 컨테이너 이미지를 실행하고 있습니다.
  2. 프로덕션 환경이 아닌 개발 환경에서만 소프트웨어를 실행하고 있으며 복원력을 구현하는 것보다 더 좋은 시간을 보낼 수 있습니다.

그러나 소프트웨어를 제어 할 수 있고 프로덕션에 배포 할 계획이라면 준비 상태를 신중하게 정의 했더라도 올바른 순서로 작업을 시작하는 외부 도구에 의존 할 수는 없습니다. 근본적인 문제에 대한 해결책이 아니며 네트워크 딸꾹질이 발생하는 순간 시스템이 무너집니다. 기껏해야 모든 웹 프런트 엔드 컨테이너가 발생할 때마다 자동으로 다시 시작해야하는데, 그 누구에게도 허용 가능한 가동 중지 시간이라는 것을 알 수 없습니다.

잘 작성된 소프트웨어가 네트워크 중단에 대처할 것이라는 데 동의하십시오. 모든 소프트웨어가 잘 작성된 것은 아니며 개발자가 가능한 모든 사용 사례에 대해 항상 생각하지는 않는다는 데 모두 동의한다고 생각합니다.

JVM을 실행하는 클라이언트 컨테이너와 여기에 연결할 다른 모니터링 도구를 호스트 PID 네임 스페이스에서 실행하고 싶을 수 있습니다. 둘 다 호스트 PID 네임 스페이스에서 다른 하나를 모니터링 할 수 있고 공급 업체가 승인 한 이미지로 이러한 도구를 실행할 수있는 권한 만 부여 받았습니다. . 모니터링 도구가 기존 JVM을 모니터링하는 경우 시작되는 순서가 중요합니다 (분명히). 네트워크 (mysql, elasticsearch, 서비스 검색 클러스터가 모두 언급 됨)와 관련된 주문이 중요한 사용 사례가 수백 가지있을 수 있지만 다른 네임 스페이스를 효과적으로 사용하여 공유 할 수있는 다른 것들이 포함됩니다.

그래서 저는 유스 케이스 (1)에 확실히 동의합니다. 어떤 상황에서는 컨테이너를 변경할 수 없다는 점에서

그러나 도구가 여러 항목과 관련이 있으면 즉시 주문에 반대합니다. 순서가 중요하고 순서를 보장하는 유일한 방법이 docker-compose 주위에 bash 스크립트를 작성하여 먼저 무언가를 작성한 다음 다른 것을 실행하는 경우 docker-compose는 사실 외에는 체인에 존재하지 않을 수도 있습니다. JSON / YAML은 cmdline 인수보다 더 예쁩니다.

IMHO 궁극적으로 도구는 많은 사용 사례에 유용하거나 유용하지 않습니다. Docker-compose는 동일한 호스트에서 여러 컨테이너의 정렬되지 않은 시작에 분명히 유용합니다. 충분한 사람과 충분한 사용 사례가 주문에 관한 것이고 도구가 그들을 해결하지 못한다면 사람들은 그 사용 사례를 위해 다른 곳으로 갈 것입니다.

어쨌든 이전 인수를 다시 해시하는 것이므로 지금이 스레드에서 제거하겠습니다 ..

이것은 "모든 코드가 모든 사람에 의해 적절하게 작성 되었다면 이렇게 할 필요가 없을 것이므로 그렇게하지 말자"라는 매우 다양한 개발 주제에 대해 수천 개의 스레드에 걸쳐 언급 된 것과 동일한 주장입니다. 이는 세계의 모든 사람들이 화석 연료를 태우거나 전기를 사용하는 것을 중단한다면 지구를 일으키는 문제를 해결할 수 있다는 말과 같습니다. 당신이 올바른지. 모든 앱이해야 할 일을했다면 여기에서 이에 대해 이야기하지 않을 것입니다. 그러나 우리는 지구에 살고 있습니다. 어려운 방법으로 배워야하는 종족의 존재들에게 엄청난 불완전 함이있는 곳. 다음 자금 조달 또는 언젠가 자신이 원하는 버전을 구축 할 수 있도록 허용 할 다음 고객이 될 수 있도록기도하기 위해 "최소 실행 가능한 제품"을 구축하기 때문에 회사를 시작하는 동일한 사람들 .

세상은 완벽하지 않으며 결코 완벽하지 않을 것이므로 우리는 우리 자신이 통제 할 수있는 것만 할 수 있습니다. 그리고이 경우에 제가 제어 할 수있는 유일한 것은 여러분 모두 (일명 제가 절대적으로 좋아하고이 기능 하나만 있으면 미친 듯이 사용할 도구를 개발하는 사람들)을 설득하는 것입니다. 우리가 살고있는 세상에 존재하는 소프트웨어를 처리 할 수있는 방법입니다. 우리가 살았 으면하는 것이 아닙니다.

2015 년 7 월 31 일 오전 3:42에 Aanand Prasad [email protected] 은 다음과 같이 썼습니다.

나는 어떤 순서로 시작해야 하는지를 아는 것이 작업이거나 적어도 멀티 컨테이너 관리 도구의 관심사라고 생각했을 것입니다.

아니요, 반드시 그런 것은 아닙니다. 이 스레드에 이미 여러 번 제시된 이유 때문에이 작업을 컨테이너 관리 도구에 넘겨 줄 이유는 두 가지 뿐이라고 생각합니다.

의존하는 업스트림 서비스를 사용할 수없고 기술 또는 비즈니스 이유로 인해 변경하거나 확장 할 수없는 기성 컨테이너 이미지를 실행하고 있습니다.

프로덕션 환경이 아닌 개발 환경에서만 소프트웨어를 실행하고 있으며 복원력을 구현하는 것보다 더 좋은 시간을 보낼 수 있습니다.

그러나 소프트웨어를 제어 할 수 있고 프로덕션에 배포 할 계획이라면 준비 상태를 신중하게 정의 했더라도 올바른 순서로 작업을 시작하는 외부 도구에 의존 할 수는 없습니다. 근본적인 문제에 대한 해결책이 아니며 네트워크 딸꾹질이 발생하는 순간 시스템이 무너집니다. 기껏해야 모든 웹 프런트 엔드 컨테이너가 발생할 때마다 자동으로 다시 시작해야하는데, 그 누구에게도 허용 가능한 가동 중지 시간이라는 것을 알 수 없습니다.


이 이메일에 직접 답장하거나 GitHub에서 확인하세요.

+1 @aanand. 이것은 범위를 제한 할 수있는 것이 아닙니다. 기능이 완료되면 사람들이 신뢰할 수있는 기능이어야합니다. 그들은 오랫동안 "내구성있는"인프라를 위해 코딩 해 왔으며 대중을 변환하는 데 오랜 시간이 걸립니다. 그들은 이것을 오랫동안 사용할 것입니다.

나는 우리가 컨테이너 간의 시작 타이밍 의존성 문제를 완화하기 위해 무언가를 구현하는 것을 배제하지 않았다는 것을 반복하고 싶습니다. 어제 바로이 스레드에서 하나의 가능한 해결책을 스케치했습니다.

그러나 저는이 기능이 누구를위한 것인지, 어떤 문제를 해결할 것인지, 어떤 문제를 해결할 수 _ 않고 _ 어떤 정도에 의존 할 수 있는지에 대해 동일한 페이지에 있기를 바랍니다. 그것이 내가 느끼고 자하는 것입니다.

또한 존재하는 준비 상태에 대한 여러 정의 ( "컨테이너가 시작됨"vs "컨테이너가 TCP 연결을 수락 함"vs "사용자 지정 상태 확인 통과")와 각각의 구현의 복잡성이 서로 다르기 때문에 비교 결과를 얻고 싶습니다. 얼마나 많은 사람들이 각각에 대한 기본 지원으로 혜택을받을 수 있는지에 대한 아이디어.

서비스를 동기화하는 일반적인 기술은 etcd 또는 이와 유사한 것을 사용하는 "서비스 레지스트리"와 같은 것입니다. wait_for_service는 어떻습니까?

web:
  image: mywebapp
  links: ["db"]
  wait_for_service:
    type: etcd (or consul, or zk)    -- or use swarm type notation
    addr: http://my.etcd.com/
    path: postgres.service

db:
  image: postgres

compose는 서비스가 실제로 준비되었는지 알지 못하지만 레지스트리에서 데이터를 찾고이를 기반으로 종속 컨테이너를 시작할 수 있습니다. 레지스트리에 가용성을 게시하는 것은 서비스 (postgres와 같은)의 책임이므로 레거시 애플리케이션의 경우 일종의 래핑 스크립트가이를 수행합니다. 앱을 시작하고 포트가 작동하는지 확인한 다음 레지스트리에 게시합니다.

안녕하세요 @aanand.

오늘 저는 트위터에서 @bfirsh와이 문제 에 대해 논의했습니다.

특히, 여러 개의 작은도 커화 된 구성 요소로 분산 시스템을 구축 할 때 모든 주요 인터페이스 앱과 해당 종속성을 구동 한 다음 모든 앱을 다시 분해하기 전에 다양한 테스트를 실행하는 통합 테스트가 필요하다는 것을 알았습니다.

이것은 예를 들어 Riak을 사용하는 다른 거의 모든 것에 비해 시작하는 데 시간이 걸리는 문제로 이어집니다.

나는 "컨테이너가 비동기식으로 시작하고 처리한다"라고 말하는 것에 특별히 반대하지는 않지만, 일관된 상태 확인을 노출하는 각 서비스를 중심으로 설계하는 것은 적어도 코드가 아닌 서비스 당 하나의 구현에 "처리"를 포함합니다. 서비스에 의존하는 각 앱에서 연결 재 시도를 처리합니다.

자체 상태 확인을 정의하는 서비스도 모니터링 목적으로 유용합니다.

@elliotcm 두 점 모두 동의했습니다.

CI 테스트를 위해 Docker 컨테이너에서 연결된 서비스가 준비 될 때까지 기다릴 수있는 작은 유틸리티 를 구축했습니다. 환경 변수에서 연결된 모든 TCP 서비스를 자동으로 찾고 성공하거나 시간이 초과 될 때까지 TCP 연결을 반복적으로 동시에 시도합니다.

또한 우리가 구축 한 이유와 사용 방법을 설명 하는

@meeee 정말 멋지고 유용 해 보입니다! 어떻게 회전하는지 예를 보여 주시겠습니까? 특히 docker-compose와 함께 사용합니까?

나는 오늘 처음으로 mysql 컨테이너를 시작한 까다로운 경우가있었습니다. 컨테이너는 처음 실행될 때 자체 부트 스트랩하고 구성되면 데이터베이스 데몬을 다시 시작합니다. 이로 인해 포트 가용성 검사가 조기에 트리거되고 종속 컨테이너가 시작되었지만 연결에 실패했습니다. 이것은 우리가 처음부터 완전히 설정하기를 원하는 CI 환경이었습니다.

나는 어떤 종류의 대기 / 확인 동작을 지원하기 위해 compose를 매우 열망했지만, 기만적으로 까다로운 경우가 있습니다. 토론에 참여하게되어 기쁩니다.

@prologic 애플리케이션이나 테스트를 실행하기 전에 다른 서비스 / 컨테이너에 따라 Docker 컨테이너에서 waitforservices 명령을 실행하기 만하면 됩니다. 연결된 모든 서비스를 찾아서 연결할 수 있거나 특정 시간 (기본적으로 60 초)이 경과 할 때까지 실행됩니다. 바이너리 종료 후 다른 서비스에 의존하는 모든 코드를 실행하기 만하면됩니다 (그래도 종료 상태를 확인하고 싶을 수도 있습니다).

@pugnascotia 데이터베이스 서버는 부트 스트랩되는 동안에 만 localhost에서 수신 할 수 있습니다. 어쨌든 컨테이너가 준비되었는지 여부를 나타내는 일종의 표시기를 노출해야합니다. 우리는 MySQL을 사용하지 않지만 waitforservices는 공식 postgres 이미지 와 완벽하게 작동합니다.

@aanand Postgres는 실제로 선택할 수있는 훌륭한 예입니다. 왜냐하면 TCP 포트가 열리기를 기다리는 것은 충분하지 않기 때문입니다.이 유형의 (도커) 시나리오에서 그렇게하면 때때로 FATAL: the database system is starting up. 와 같은 오류가 발생합니다 psql 이 필요합니다. select version() 하지만 더 가벼운 대안이있을 수 있습니다.

흥미로운 대기 구현이있는 특정 Maven 도커 플러그인 이 있습니다. 현재 나는 bash 래퍼를 사용하여 각 서비스를 시작하고 있으며 이는 compose 사용의 요점을 무너 뜨립니다.

이를 해결 방법으로 사용 (방 탄성이 확실하지 않음) :

db:
  image: postgres:9.3
  ports:
    - "5432:5432"
createdbs:
  image: postgres:9.3
  links:
    - db
  command: >
    /bin/bash -c "
      while ! psql --host=db --username=postgres; do sleep 1; done;
      psql --host=db --username=postgres -c 'CREATE DATABASE \"somedatabase\";';
    "

@olalonde와 비슷한 방법을 사용하고 있습니다. /bin/bash -c 이후에 실행되는 명령에 작은 따옴표를 사용할 때 다른 응용 프로그램에서 링크에서 재사용되는 환경 변수를 활용할 수 있으므로 사용자 이름과 암호를 두 개로 유지하지 않고도 사용할 수 있습니다. 장소. 이것은 API와 같은 서비스가 있고 데이터베이스를 가동해야하고 특정 테이블이나 레코드가 있는지 확인하기 위해 쿼리 검사를 실행하여 적절한 데이터를 부트 스트랩하는 상황에서 잘 작동합니다. 이것은 또한 데이터베이스를 제대로 쿼리하기 위해 컨테이너에 일종의 클라이언트를 설치해야하지만 작동한다는 것을 의미합니다.

+1이 기능에 정말 관심이 있습니다.

의존성에 +1. 원칙적으로 아키텍처는 모든 시작 순서를 지원할 수있을만큼 견고해야한다는 데 동의합니다. 그러나 종종 그렇게하는 것은 실용적이지 않습니다.

이 기능에 대한 푸시 백은 멀리서 아키텍처를 지시하려는 다른 사람들로부터 비롯된 것 같습니다. 그들은 정말로 그렇게 할 권리가 없습니다. 이 기능을 사용하면 시간이 많이 걸리는 리팩터링을 해결할 수 있습니다. 장기적인 가치가 거의 없습니다. (리팩토링을위한 리팩토링).

예, 저는 "주위 작업"이라고 말했습니다. 그리고 나는 더럽다. 하지만 저에게 작곡은 다른 사람들이 생산성을 발휘할 수 있도록하는 것입니다. 이 간단한 구성을 통해 가능합니다.

이 기능이 도구에 존재한다면 1 분 안에 문제를 해결하고 실제 가치를 추가 할 수 있습니다. 대신, 나는 외부 의존성과 함께 시작 순서 문제를 해결하기 위해 벽에 머리를 부딪 히고 있습니다.

@beardface, 그리고 다른 사람 : 어떤 기능, 특히 앱을 개발하여 이동 수 있습니까?

  1. 서비스 A가 서비스 B가 시작될 때까지 시작될 때까지 기다려야 함을 지정하는 기능? (컨테이너가 시작되었지만 연결을 수락 할 준비가되지 않았을 때 여전히 경쟁 조건을 해결하지 못함을 명심하십시오)
  2. 서비스 A가 서비스 B가 연결을 수락 할 때까지 시작을 기다려야 함을 지정하는 기능? (컨테이너가 수신 중이지만 초기화를 완료하지 않았을 때 경합 상태를 해결하지 못합니다. 예를 들어 시작시 데이터베이스를 생성하는 postgres 컨테이너, @rarkins '예제를 사용하기 위해)
  3. 서비스 B에서 상태 확인을 정의하고 서비스 B의 상태 확인이 통과 할 때까지 서비스 A가 시작을 기다려야한다고 지정하는 기능은 무엇입니까?

@aanand 넘버 3이 내 투표입니다. 이는 개발자가 시간을 결정하기 위해 서비스에 다시 의존하는 대신 상태 확인 로직을 선택할 수있는 유연성을 제공합니다. 이 특정 사용 사례의 경우 개발자의 자유가 더 좋습니다. 컨테이너에 설치 될 모든 유형의 앱을 예상하는 것은 불가능합니다.

+3

그래도 몇 가지 기본 건강 검사가 포함되어 있으면 좋을 것입니다. 포트 80_에서 _http 200 ok와 같은 것은 너무 일반적이어서 노력할만한 가치가 있습니다.

"배터리 포함"3 번을 사용하는 것이 좋을 것입니다 (그러니 감히 위의 모든 것을 말합니까?)

즉, "컨테이너가 작동 중", "파일이 있음"및 "포트가 열려"유형의 대기에 대한 기능이 내장 된 다음 사람들이 자신의 "애플리케이션 계층"검사를 정의 할 수 있도록합니다.

3은 내 투표를 얻습니다.

3은 더 일반적입니다. 2는 더 일반적인 1입니다. 모든 사람이 3을 선호하지만 2 또는 1이 일부에게는 충분합니다.

3 개 투표

분명히 세 번째 옵션입니다. 이 토론에만 많은 사례가 있습니다. 따라서 1 차와 2 차 옵션이 좋을 것이고 많은 사람들이 행복 할 것이지만 문제는 여전히 열려있을 것입니다.

3 개 투표

3 개 투표

3에 투표하십시오. 베타 테스트에도 관심이 있습니다.

3에 투표하십시오.

3에 투표하십시오. 베타 테스트에도 관심이 있습니다.

3 개 투표

모두에게 감사합니다. 이제 투표를 중지 할 수 있습니다. 메시지가 분명하다고 생각합니다.

https://github.com/docker/compose/issues/374#issuecomment -126312313-대체 디자인 제안에서 제안한 디자인에 대한 피드백과 강점 / 약점에 대한 토론에 관심이 있습니다.

wait_for_tcp 편의 방법이 유용 할 수 있지만 상태 확인을 수행하기 위해 별도의 컨테이너를 갖는 것이 위의 @olalonde@mbentley에서 설명한대로 동일한 컨테이너에서 수행하는 것보다 더 쉬운 방법은 명확하지 않습니다. .

alexec이 docker-maven-plugin에서 수행하는 것과 같은 작업을 수행하는 것은 어떻습니까? 그는 자신의 구성이 docker-compse / fig와 유사하도록 명시 적으로 설계했으며 지금까지 내 프로젝트에서 훌륭하게 작동했습니다.

healthChecks:
  pings:
     # check this URL for 200 OK
     - https://localhost:8446/info
     # check another URL with non-default time out, with a pattern, and non checking SSL certificates
     - url: https://localhost:8446/info
       timeout: 60000
       pattern: pattern that must be in the body of the return value
       sslVerify: false
  logPatterns:
     - pattern that must be in log file
     - pattern: another pattern with non-default timeout
       timeout: 30000

출처 : https://github.com/alexec/docker-maven-plugin/blob/master/USAGE.md

tcp 연결이 작동하는지 확인하는 것만으로는 데이터베이스가 시작되었음을 알 수 없습니다. 데이터베이스 상태를 확인하는 명령을 사용하는 것이 좋습니다.

@ceagan 그렇게. 사용자 지정 명령도 유용합니다. 예

healthChecks:
  custom:
    # retry this command until it returns success exit code
    - cmd: psql --host=localhost --username=postgres
      sleep: 1s

또한 대소 문자 규칙을 기억할 필요가 없기 때문에 checkshealthChecks 보다 낫다고 생각합니다. wait (상태 확인을 시작하기 전에 대기해야하는 시간 (초)), attempts (포기하기 전에 상태를 확인해야하는 횟수), retire 를 갖는 것도 유용 할 수 있습니다

이것은 마라톤 프레임 워크가 어떻게 해결했는지 방향으로 나아갑니다. 기본 종속성상태 검사 . Docker 컨테이너를 시작하는 데 매우 인기가 있으므로 작성에 채택 할 옵션 (시간 초과, 간격, 응답 코드 등)을 확인하는 것이 좋습니다.

옵션 3도 마찬가지입니다.

+1

+1

+1

사용자 지정 대기 스크립트를 사용하지만 매우 좋을 것입니다.

+1

+1

옵션 3-healthChecks는 좋은 것 같습니다.

+1

+1

+1

+3.
토론에 다른 생각을 추가하기 위해 @aanand가 제안한 선택은 실제로 다음과 같습니다. 컨테이너의 상태는 docker-compose가 아니라 docker의 책임입니다. Docker가 상태 정보를 제공하면 Docker-compose는 이러한 모든 사용 사례를 깨끗하고 우아한 방식으로 구현할 수 있습니다. 그러나 도커는 그렇지 않습니다. 즉각적인 상태 비 저장 컨테이너의 비전을 고수하는 것 같습니다. 너무 빨리 시작되어 이러한 종류의 동기화 문제는 중요하지 않습니다.
제 경우에는 각 경우에 대해 제 서비스에 가장 적합한 아키텍처를 선택할 수 있다는 아이디어를 추구합니다. 예를 들어, 때때로 각각 단일 애플리케이션을 제공하는 여러 MariaDB 인스턴스를 원합니다. 다른 경우에는 여러 애플리케이션을 제공하는 단일 MariaDB 인스턴스를 원합니다. Docker가 가장 좋은 것이 무엇인지 또는 대신해야 할 일을 알려주기를 원하지 않습니다. Docker는 항상 이런 종류의 유혹을 가지고있는 것 같습니다;).
가장 좋은 해결책은 컨테이너가 자신에 대한 임의의 메타 데이터를 선언하도록 Docker를 설득하고 해당 기능을 사용하여 컨테이너가 "준비된"것으로 간주되어 다른 사람들이 신뢰할 수있는 것으로 간주되는지 여부를 docker-compose가 알아 내도록하는 것입니다.
"단일 db-multiple 앱"접근 방식에 대해서는 다음과 같은 정의를 원합니다.

db:
  image: postgres:9.3
  ports:
    - "5432:5432"
app1:
  image: wordpress
  links:
    - db [WP]
app2:
  image: ghost
  links:
    - db [GST]

Docker Compose는 "db"를 시작하고 해당 메타 데이터에 대해 질문합니다 (Docker Compose 관련). yml 파일에서 "app1"은 "db"가 ​​"wordpress ready"(연결을 허용 할뿐만 아니라 필수 개체도 포함 함을 의미)가 될 것으로 예상합니다.

이 상황을 해결하는 방법에 대한 간단한 해결책이 없습니다. 저는 현재 두 단계로 수동으로 수행합니다. 사용자 지정 postgresql-bootstrap 이미지, 여기에서 db와 데이터베이스 사용자를 만들어 액세스합니다. 및 사용자 정의 liquibase-postgresql 이미지는 Wordpress 컨테이너에서 제공하거나 추출한 DDL에서 데이터베이스 개체를 생성합니다. 그래야 "app1"을 실행할 수 있습니다.
따라서 "인프라"컨테이너가 서로 다른 응용 프로그램을 제공하는 경우 "인프라"및 "앱"그룹에서 컨테이너를 분리해야합니다.

Docker Compose는 Docker 자체만큼 상태 비 저장을 원합니다. 정말 유용하고 싶다면 그게 가능한지 모르겠습니다.

옵션 3의 경우 +1

+1

옵션 3의 경우 +1.

옵션 3의 경우 +1

옵션 3의 경우 +1

이 문제는 한동안 발생했습니다. 해결책은 무엇입니까?

@ bweston92 나는 @aanand 가이 스레드의 초기에 해결책을 제안했고 찾고 있는 상태라고 생각합니다.

강점 / 약점에 대한 토론과 함께 대체 설계 제안.

개인적으로 @aanand 의 제안 된 솔루션이 많은 의미가 있다고 생각합니다. 그것은 나에게 매우 명백한 것처럼 보이지만 유연하게 보입니다. TCP 포트가 열리기를 기다리거나 고정 된 시간을 기다리지 않고 내 필요를 충족 할 수 있습니다.

내 사용 사례는 테스트 용입니다. 데이터베이스가 생성되기 전에 테스트가 시작되면 테스트가 실패하므로 다음과 같이 명령을 bash -c "sleep 2; python manage.py test --keepdb" 변경했습니다.

db:
    image: postgres:9.5
test:
    build: .
    command: bash -c "sleep 2; python manage.py test --keepdb"
    volumes:
        - ./test_project:/app
    links:
        - db
        - selenium
    environment:
        - EXTERNAL_TEST_SERVER=http://testserver:8000/
        - SELENIUM_HOST=http://selenium:4444/wd/hub
selenium:
    image: selenium/standalone-chrome:2.48.2
    links:
        - testserver
testserver:
    build: .
    command: bash -c "sleep 5; python manage.py testserver 8000 --static"
    volumes:
        - ./test_project:/app
    ports:
      - "8000:8000"
    links:
        - db

데이터베이스를 먼저 시작하고 기다리지 않고도 docker-compose run test 를 실행할 수 있습니다.

요즘 어떤 이슈가 명시 적 종속성을 선언 할 수있는 새로운 도커 작성 기능에 투표하기에 "올바른"장소인지 말하기는 어렵지만 내 투표는 강력한 것으로 간주합니다. 새로운 Docker 1.9 네트워킹 기능과이를 선호하는 컨테이너 링크의 사용 중단이 다가 오면 이제 컨테이너 A가 컨테이너 B보다 먼저 시작되는지 확인할 수있는 좋은 방법이 없습니다. Docker 1.9 사용자 정의 네트워킹을 사용하면 다음을 수행 할 수 있습니다. 더 이상 컨테이너 링크를 지정하지 않습니다. 그건 ... 망가 졌어.

나는 동의한다. 옵션 3을 받기위한 일정이 있습니까? 이것을 신속하게 처리하면 좋을 것입니다.

종속성 순서가 실제로이 문제를 해결하지 않는다는 점은 주목할 가치가 있습니다. 이 문제는 링크에도 적용됩니다. 대부분의 경우 컨테이너는 문제를 인식하지 못할만큼 빠르게 시작되지만 문제는 여전히 존재합니다.

이 문제를 해결하기 위해 필요한 것은 애플리케이션 인식 상태 점검입니다. 상태 확인은 기본적으로 작업이 성공하거나 시간 초과에 도달 할 때까지 일부 작업을 재 시도하는 루프입니다. HTTP 서비스의 경우 2xx 코드를 얻을 때까지 http 요청을 할 수 있습니다. 데이터베이스의 경우 연결하고 테이블에서 선택할 수 있습니다.

어떤 경우 든 애플리케이션에 따라 다르므로 개발자가 정의해야합니다. https://github.com/docker/compose/issues/374#issuecomment -135090543에서 옵션 3을 구현하려면이 상태 확인 논리를 구현해야합니다.

이 문제에서 이미 몇 번 언급되었습니다 (https://github.com/docker/compose/issues/374#issuecomment-53036154, https://github.com/docker/compose/issues/374#issuecomment-71342299). ), 그러나 다시 반복하려면 연결을 재 시도하여 애플리케이션 이 장애 에 대해

애플리케이션을 장애에 대해 복원력있게 만드는 기능은 사실상 상태 확인과 동일한 논리로 밝혀졌습니다. 따라서 어느 쪽이든 동일한 논리를 구현해야합니다. 유일한 차이점은 포함하는 위치입니다. 지금 당장 애플리케이션이나 진입 점 스크립트에 포함 할 수 있습니다. 제안 된 변경 사항을 사용하여 Compose 파일에서 정의 할 수 있습니다. 어느 쪽이든 여전히 각 서비스에 대해 상태 확인을 구현해야합니다.

진입 점 스크립트 대신 Compose 파일에 포함하면 큰 이점이 있습니까? 그것은 여전히 ​​논쟁의 여지가 있습니다.

Compose 파일에 넣는 가장 큰 단점은 up 속도를 상당히 느리게 만든다는 것입니다.

새로운 네트워킹을 통해 up 이 병렬로 발생하도록 할 수 있습니다 (예 : stop, rm 및 scale에서 수행). 모든 컨테이너는 한 번에 시작하고 일부 초기화를 수행 한 다음 계속 진행할 수있는 종속성을 사용할 수있을 때까지 기다릴 수 있습니다. 이것은 환경을 매우 빠르게 시작하게합니다.

Compose가 상태 확인이 완료 될 때까지 기다려야하는 경우 시작은 사실상 순차적입니다. 컨테이너 시작 및 애플리케이션 초기화는 병렬로 발생하지 않으며 모든 것이 느립니다.

대부분의 앱은 LB 뒤에 있기 때문에 상태 확인 기능이 있고 외부에서 모니터링됩니다. 새 앱을 여는 것은 어렵지 않습니다. 따라서 compose가 지원한다면 사람들이 사용할 수있는 선택입니다. 필수는 아닙니다. 현실 세계에서 사람들은 다양한 애플리케이션을 다루어야하며 갑자기 모든 앱을 스마트하게 만들 수 있다는 생각은 비현실적이고 비현실적입니다. 진입 점의 래퍼 논리는 추악합니다. 저는 커뮤니티에서 기능에 대한 충분한 수요가 있었고 옵션 3이 많은 표를 얻었습니다.

내 iPhone에서 보냄

2015 년 11 월 18 일 오전 11:01에 Daniel Nephin [email protected] 다음과 같이 썼습니다.

종속성 순서가 실제로이 문제를 해결하지 않는다는 점은 주목할 가치가 있습니다. 이 문제는 링크에도 적용됩니다. 대부분의 경우 컨테이너는 문제를 인식하지 못할만큼 빠르게 시작되지만 문제는 여전히 존재합니다.

이 문제를 해결하기 위해 필요한 것은 애플리케이션 인식 상태 점검입니다. 상태 확인은 기본적으로 작업이 성공하거나 시간 초과에 도달 할 때까지 일부 작업을 재 시도하는 루프입니다. HTTP 서비스의 경우 2xx 코드를 얻을 때까지 http 요청을 할 수 있습니다. 데이터베이스의 경우 연결하고 테이블에서 선택할 수 있습니다.

어떤 경우 든 애플리케이션에 따라 다르므로 개발자가 정의해야합니다. # 374 (주석)의 옵션 3을 구현하려면이 상태 확인 논리를 구현해야합니다.

이 문제에서 이미 몇 번 언급되었지만 (# 374 (주석), # 374 (주석)), 다시 반복하려면 연결을 재 시도하여 애플리케이션을 장애에 대해 복원력있게 만들어 오늘이 문제를 해결할 수 있습니다. 어쨌든 모든 프로덕션 시스템에 대해이 작업을 수행해야합니다.

애플리케이션을 장애에 대해 복원력있게 만드는 기능은 사실상 상태 확인과 동일한 논리로 밝혀졌습니다. 따라서 어느 쪽이든 동일한 논리를 구현해야합니다. 유일한 차이점은 포함하는 위치입니다. 지금 당장 애플리케이션이나 진입 점 스크립트에 포함 할 수 있습니다. 제안 된 변경 사항을 사용하여 Compose 파일에서 정의 할 수 있습니다. 어느 쪽이든 여전히 각 서비스에 대해 상태 확인을 구현해야합니다.

진입 점 스크립트 대신 Compose 파일에 포함하면 큰 이점이 있습니까? 그것은 여전히 ​​논쟁의 여지가 있습니다.

Compose 파일에 넣을 때의 가장 큰 단점은 구성 속도가 상당히 느리다는 것입니다.

새로운 네트워킹을 통해 우리는 병렬로 구성 할 수 있습니다 (예 : 중지, rm 및 확장). 모든 컨테이너는 한 번에 시작하고 일부 초기화를 수행 한 다음 계속 진행할 수있는 종속성을 사용할 수있을 때까지 기다릴 수 있습니다. 이것은 환경을 매우 빠르게 시작하게합니다.

Compose가 상태 확인이 완료 될 때까지 기다려야하는 경우 시작은 사실상 순차적입니다. 컨테이너 시작 및 애플리케이션 초기화는 병렬로 발생하지 않으며 모든 것이 느립니다.


이 이메일에 직접 답장하거나 GitHub에서 확인하세요.

@dnephin 최종 결과는 각각의 모든 서비스에 대해 동일한 래퍼 스크립트가 있다는 것입니다. 내 요점은 매우 일반적인 것 (80 및 443의 HTTP 200 또는 5432의 TCP)이 있으므로 compose와 함께 제공하는 것이 좋습니다.

물론 애플리케이션 수준에서이 모든 문제를 해결하는 것이 좋지만 실제로는 데이터베이스, 캐시 또는 마사지 큐와 같은 다른 모든 움직이는 부분이 아닌 자신의 애플리케이션 만 제어 할 수 있습니다.

@mbdas@jayfk 모두에 동의하며 추가 할 것입니다. 이에 대한 저항이 종속성 사양 및 컨테이너 시작의 결과 순서를 사용하더라도 오류가 발생하고 컨테이너 링크 및 볼륨을 사용하는 것입니다. 제어 컨테이너 시작 순서가 발생해서는 안됩니다. 이제 새 네트워크 모델이 링크가 더 이상 사용되지 않음을 의미하고 새 네트워크 모델이 문자 그대로 링크와 공존 할 수 없다는 것을 의미하므로 동일한 시작이 필요합니다. -링크가 허용 된 주문 기능은 어떤 식 으로든 우리에게 다시 제공됩니다. 물론, 링크 기반 컨테이너 주문에서 발생할 수있는 모든 실패 사례는 새로운 네트워크 모델 및 컨테이너 종속성에서 여전히 발생할 수 있지만 우리는 모두이를 준수하는 법을 배웠습니다.

@delfuego : 링크가 더 이상 사용되지 않는 방식, 특히 대체되는 항목에 대해 자세히 설명해 주시겠습니까? 일부 문서 / 예제에 대한 링크로 충분합니다.

@ h17liner : 예, 흥미 롭습니다! 감사

@dnephin에 동의 하지만

이 문제에서 이미 몇 번 언급되었지만 다시 반복하려면 연결을 다시 시도하여 응용 프로그램을 장애에 대해 복원력있게 만들어 오늘이 문제를 해결할 수 있습니다. 어쨌든 모든 프로덕션 시스템에 대해이 작업을 수행해야합니다.

나는 테스트 실행과 같은 이유로 이것을 만드는 것으로 보지 않습니다. Django 앱에서 모델이 올바르게 저장되는지 테스트하는 중이라면 데이터베이스 연결에 복원력을 추가하는 것이 얼마나 의미가 있는지 잘 모르겠습니다.

@delfuego 나는 당신이 원래 그 문제에 대해 올바른 위치 (# 686)에 있다고 생각합니다. 이 문제는 주문에 관한 것이 아니라 인위적인 시작 지연 (주문이 이미 존재하는 경우)에 관한 것입니다. 이러한 것들은 관련이 있지만 별개의 문제입니다.

사용자 생성 브리지 네트워크에서 지원되지 않는 링크에 동의하지 않으며 일반적으로 더 이상 사용되지 않는 것으로 문서화되어 주문이 없습니다. 따라서 옵션 3은 주문과 발행시기를 모두 처리합니다.

내 iPhone에서 보냄

2015 년 11 월 19 일 오전 8시 14 분에 Daniel Nephin [email protected] 은 다음과 같이 썼습니다.

@delfuego 나는 당신이 원래 그 문제에 대해 올바른 위치 (# 686)에 있다고 생각합니다. 이 문제는 주문에 관한 것이 아니라 인위적인 시작 지연 (주문이 이미 존재하는 경우)에 관한 것입니다. 이러한 것들은 관련이 있지만 별개의 문제입니다.


이 이메일에 직접 답장하거나 GitHub에서 확인하세요.

옵션 4를 제안하고 싶습니다 (실제로는 3의 변형이라고 말할 수도 있습니다).
모든 시작 명령이 종료 코드 0으로 완료 될 때까지 컨테이너는 준비되지 않습니다. 각 컨테이너에 대해 yml 파일에서 이러한 시작 명령을 정의 할 수 있어야합니다. 이 명령은 실행중인 컨테이너에 대해 "docker exec"로 수행하는 것처럼 실행됩니다. 클래식 단위 테스트에서 setUp () 및 tearDown () 메서드를 생각해보십시오. 예, "종료"명령도 가질 수 있습니다.
분명히 계층 구조의 다음 컨테이너는 종속 된 모든 컨테이너가 준비 될 때까지 시작되지 않습니다.
PS 훌륭한 DockerCon.Eu 2015에 감사드립니다.

HEALTHCHECK 지시문은 훨씬 더 유연하고 (즉, 나중에 사용할 수 있음) 유용합니다. 설정은 CMD 또는 (더 나은) ENTRYPOINT 스크립트 내에서 수행해야하며 프로세스 신호를 처리하여 분해해야합니다.

여기서 문제의 핵심은 사람들이 단일 docker-compose up 명령으로 스택을 가져오고 모든 것이 마술처럼 작동하기를 원한다는 것입니다.

모든 피드백을 바탕으로 다양한 사용 사례에 대한 솔루션이 분명히 많지만 "하나의 크기로 모두 적합"하지는 않습니다.

여러 개의 docker-compose 명령을 실행하여 "초기화"작업을 매우 쉽게 실행할 수 있습니다.이 접근 방식이 가장 일반적이고 유연한 접근 방식이라고 생각합니다.

예를 들어 내 데이터베이스 (MySQL) 컨테이너가 포트 3306에서 실행될 때까지 기다리는 단일 작업이있는 "에이전트"컨테이너에서 Ansible 플레이 북을 실행합니다.이 "에이전트"컨테이너는 내 "db"컨테이너에 자동으로 연결됩니다. 다음이 실행되면 시작됩니다.

$ docker-compose run --rm agent
Creating db_1

PLAY [Probe Host] *************************************************************

TASK: [Set facts] *************************************************************
ok: [localhost]

TASK: [Message] ***************************************************************
ok: [localhost] => {
    "msg": "Probing db:3306 with delay=0s and timeout=180s"
}

TASK: [Waiting for host to respond...] ****************************************
ok: [localhost -> 127.0.0.1]

PLAY RECAP ********************************************************************
localhost                  : ok=3    changed=0    unreachable=0    failed=0

그런 다음 docker-compose up 를 실행하여 db 컨테이너가 완전히 작동하는지 확인할 수 있습니다.

다음은이를 지원하는 간단한 docker-compose.yml 파일입니다.

...
...
db:
  image: mysql
  hostname: db
  expose:
    - "3306"
  environment:
    MYSQL_DATABASE: xxx
    MYSQL_USER: xxx
    MYSQL_PASSWORD: xxx
    MYSQL_ROOT_PASSWORD: xxx

agent:
  image: cloudhotspot/ansible
  links:
    - db
  volumes:
    - ../../ansible/probe:/ansible
  environment:
    PROBE_HOST: "db"
    PROBE_PORT: "3306"

"에이전트"컨테이너는 아래 표시된 /ansible 마운트 된 볼륨에서 site.yml 라는 플레이 북을 실행합니다.

- name: Probe Host
  hosts: localhost
  connection: local
  gather_facts: no
  tasks: 
    - name: Set facts
      set_fact: 
        probe_host: "{{ lookup('env','PROBE_HOST') }}"
        probe_port: "{{ lookup('env','PROBE_PORT') }}"
        probe_delay: "{{ lookup('env','PROBE_DELAY') | default(0, true) }}"
        probe_timeout: "{{ lookup('env','PROBE_TIMEOUT') | default (180, true) }}"
    - name: Message
      debug: msg="Probing {{ probe_host }}:{{ probe_port }} with delay={{ probe_delay }}s and timeout={{ probe_timeout}}s"
    - name: Waiting for host to respond...
      local_action: >
        wait_for host={{ probe_host }}
        port={{ probe_port }}
        delay={{ probe_delay }}
        timeout={{ probe_timeout }}
      sudo: false

단일 docker-compose up 목표에 대한 한 가지 해결책은 docker 작성에 "워크 플로우" 기능을 도입하고 하나 이상의 docker-compose 명령을 다음과 같이 지정하여 더 복잡하고 제어 된 오케스트레이션 시나리오를 허용하는 선택적 워크 플로우 사양 파일을 포함하는 것입니다. 실행해야하는 "작업":

# The default workflow, specified tasks will be run before docker-compose up
# The "up" task is implicit and automatically invoked for the default workflow
# The "up" task is explicit for custom workflows as some workflows may not want docker-compose up
default:
  tasks:
    - run --rm agent
    - up

# Custom workflows that can be invoked via a new docker-compose command option
# This example:
# 1. Runs agent container that waits until database container is up on port 3306
# 2. Runs Django database migrations from app container
# 3. Runs Django collect static task from app container
# 4. Runs test container that runs acceptance tests against linked app container
# Does not execute a docker-compose up afterwards

test:
  tasks:
    - run --rm agent 
    - run --rm app manage.py migrate
    - run --rm app manage.py collectstatic --noinput
    - run --rm test

오늘 저는 Makefile을 사용하여 위의 작업을 수행합니다. Makefile은 다양한 시나리오에 대해 고유 한 워크 플로우를 정의 할 수있는 고차원 적 기능을 제공합니다.

Docker compose에 "워크 플로" 기능 또는 이와 유사한 기능이 도입되어이 특정 문제에 대한 매우 일반적이고 유연한 솔루션을 제공 할 수 있다면 좋을 것입니다.

문제는 사람들이 docker-compose가 프로덕션 배포에 충분할 것으로 기대한다는 것입니다. 개인적으로 그것이 실현 가능해지기까지는 오랜 시간이 걸릴 것이라고 생각하며 Kubernetes / Helm 은 그 목표에 훨씬 더 가까운 것 같습니다.

@olalonde , 우리는 프로덕션 준비가되도록 작성하는 것을 좋아합니다 ...하지만 컨테이너 링크가 더 이상 사용되지 않는 경우 새 사용자에게 복제되지 않으면 사라질 중요하고 기존 기능을 지원합니다. -생성 된 네트워크 모델. (다시 말하지만,이 요청이이 특정 문제와 완벽하게 일치하지 않을 수 있습니다. 컨테이너 시작 주문이 여기에 "속한다"인지 아니면 문제 # 686에 있는지는 아직 명확하지 않습니다.)

HEALTCHECK Docker 지시문을 사용하면 depends_on 기능은 컨테이너 시작 (상태 확인 없음)을 기다리거나 상태 확인 스크립트가 성공적으로 종료 될 때까지 기다릴 수 있습니다 (종료 코드 0 ). 이는 최대한 유연하고 (임의의 로직을 정의 할 수 있음) 상태 확인 로직이 속한 위치 (확인 된 컨테이너 내)를 유지합니다.

@delfuego 는 개발 및 테스트에도 도움이 될 것입니다. 개인적으로 저는 docker-compose run test 을 (를) 할 수 있고 서비스를 미리 가져 와서 수동으로 기다리지 않고도 작동하도록하고 싶습니다. 이것이 가능하지만 프로젝트를 시작하는 것이 조금 더 고통스럽고 테스트가 실패 할 수있는 더 많은 방법을 추가합니다.

+1

해결책은 중간 방법이 필요하다고 생각합니다. compose는 응용 프로그램을 사용할 수 있는지 여부를 고려할 수있는 모든 다른 방법을 설명 할 수 없습니다. 건강 검진의 개념은 사람마다 다른 의미를 가질 것이며 "일어나는지 아닌지"만큼 간단하지 않을 수도 있습니다. 프로덕션에서 HTTP 검사를 통과 했더라도 응답 시간이 비정상적으로 긴 경우 컨테이너를 중단 할 수 있습니다.

따라서 HTTP 응답, 열린 포트, 생성 된 파일 또는 생성 된 로그 라인에 대한 기본 지원이 개발에 충분해야한다고 생각합니다. 그보다 더 진보 된 것은 거의 즉시 애플리케이션에 따라 달라집니다. 또한 개발자가 애플리케이션 스택의 개별 부분을보다 강력하게 만들도록 권장하는 아이디어도 마음에 듭니다.

@pugnascotia 감사합니다. 건설적인 의견이며 합리적인 접근 방식입니다 ( "양쪽 세계에서 최고"?)

현재 논의 된 솔루션은 서비스를 사용할 수있을 때까지 기다리지 않고 서비스가 종료 될 때까지 기다리는 훨씬 단순한 _ 원래보고 된 _ 문제를 실제로 해결하지 않는 것 같습니다.

동일한 포트를 노출하는 두 개의 컨테이너가있는 사용 사례가 있습니다. 첫 번째는 15-60 초 동안 실행 된 다음 종료됩니다. 그런 다음 두 번째 서비스가 시작됩니다. 포트 충돌을 감지하고 종료 할 것이므로 오늘날 compose에서이를 수행하는 (명백한?) 방법은 없습니다. '다시 시작 : 항상'도 해결책이 아닙니다.

예, Compose는 해당 사용 사례에 맞게 설계되지 않았습니다. Compose는 빌드 파이프 라인이 아닌 런타임 환경에 중점을 둡니다. 나는 그것이 원래보고 된 문제에 관한 것이라고 생각하지 않습니다.

더 많은 빌드 지향 기능에 대한 몇 가지 요청이 있었지만 작성에는 의미가 없다고 생각합니다. 두 기능은 매우 다르며 동일한 구성 형식에 맞추려고하면 많은 혼란과 나쁜 사용자 경험으로 이어질 수 있습니다.

@ewindisch 사용 사례를 일련의 일괄 작업 실행으로 일반화 할 수 있습니다. Compose는 서비스 (예 : 체인) 간의 종속성을 유지하기 때문에이 경우에 유용합니다 (용으로 설계되지 않았음에도 불구하고). 그러나 그것은 시퀀싱과 IMHO를 처리하지 않습니다. Compose는 컨테이너의 _outside_이고 컨테이너가 _inside_ 프로세스가 무엇을할지 전혀 모르기 때문입니다.

Compose 설명서의이 부분에서는 Compose에이 기능이없는 이유에 대한 질문을 다룹니다.

https://docs.docker.com/compose/faq/#how -do-i-get-compose-to-wait-for-my-database-to-be-ready-before-starting-my-application

그러나 다음 페이지는 문제를 전혀 언급하지 않습니다.

https://docs.docker.com/compose/django/
https://docs.docker.com/compose/rails/
https://docs.docker.com/compose/wordpress/

최소한 이러한 페이지에는 Compose가 데이터베이스 컨테이너가 준비 될 때까지 기다리지 않는다는 승인이 포함되어야합니다. 또한 그것을 다루는 방법의 예를 포함 할 수 있습니다.

@ewindisch 사실, 이것이 바로 제가 https://github.com/docker/compose/issues/374#issuecomment -126312313에서 제안한 것입니다. _that_ 문제를 해결하면 사용자에게 시작 순서 문제를 해결할 수있는 도구도 제공된다는 가설이 있습니다. 장기적인 탄력성의 문제가 아니라면).

다른 사람이 있다면 그 솔루션 공간을 탐색하는 데 여전히 관심이 있습니다.

나는.

나도.

+1

+3

+1

엄청나게 찬성!
현재 이것은 컨테이너에서 실행되지만 도커 이벤트 (예 : jwilder / nginx-proxy)에 의존하는 도구 사용에 영향을줍니다. 내가하는 방법은 수동으로 리스너를 도커 구성하고 나중에 다른 모든 컨테이너를 실행하는 것입니다 (도커의 모든 아름다움을 망치고 단일 진입 점으로 구성).

@meetmatt 나중에 jwilder / nginx-proxy를 실행 해 보셨습니까? 시작 순서는 중요하지 않습니다. 시작될 때 기존 (실행중인) 컨테이너를 선택합니다.

+1

+1

투명한 채널 기반 솔루션을보고 싶습니다. 기본적으로 libchan과 같습니다. 이렇게하면 데이터베이스를 쿼리하면 데이터베이스가 준비 될 때까지 요청이 버퍼링됩니다.

분산 시스템에서는로드 순서가 충분한 솔루션이라고 생각하지 않습니다. 예를 들어 데이터베이스를 다시 시작해야하지만 결과적으로 다른 서비스가 중단 될 수있는 경우 어떻게해야합니까? 실제 솔루션은이 사용 사례도 처리합니다.

실행 파이프 라인의 예측 가능성은 우리가 업무에서하는 일의 핵심이기 때문입니다. +1

+1

뭔가 빠졌 나봐요.

도커 실행 (도커 엔진 자체)에 "기다리기"를 추가하는 것을 옹호하지 않는 이유는 무엇입니까? 내가 생각할 수있는 모든 경우에 종속 컨테이너는 "준비"된시기를 알고 있지만 도커는이를 존중하지 않습니다.

원래의 경우 (mysql이 대규모 데이터 세트 및 야외를로드하는 경우) mysql 컨테이너는 준비가되었을 때 반환하거나 신호를 보낼 수 있으며 그때까지 야외 컨테이너가 시작되지 않습니다.

내가 결정한대로 (예 : 로그에 특정 메시지가 나타날 때-> 신호 CONTAINER_UP) 임의의 논리를 실행하고 도커에 신호를 보내고 싶습니다.

net: "container:[name or id]" 내 컨테이너의 스타트 업을 주문하지 않는 이유는 무엇입니까? 더 이상 사용되지 않을 것이며 전체 스택이 net: "host" 네트워킹을 사용하기를 원하기 때문에 links 를 삭제해야했습니다. 불행히도 links 에서는 허용되지 않습니다. 컨테이너의 부팅 순서를 변경하는 다른 방법이 있습니까? 아니면 컨테이너간에 불필요한 볼륨을 공유해야합니까?

최신 정보:

links 대신 쓸모없는 볼륨으로 재주문했습니다.

base:
  build: ./base
  net: "host"
  volumes:
    - /root/lemp_base
phpmyadmin:
  build: ./phpmyadmin
  net: "host"
  volumes_from:
    - base
  volumes:
    - /root/lemp_phpmyadmin
ffmpeg:
  build: ./ffmpeg
  net: "host"
  volumes_from:
    - phpmyadmin
  volumes:
    - /root/lemp_ffmpeg
mariadb:
  build: ./mariadb
  net: "host"
  volumes_from:
    - ffmpeg
  volumes:
    - /root/lemp_mariadb
php:
  build: ./php
  net: "host"
  volumes_from:
    - mariadb
  volumes:
    - /root/lemp_php
nginx:
  build: ./nginx
  net: "host"
  volumes_from:
    - php
  volumes:
    - /root/lemp_nginx

(스택에서 다른 공유 볼륨과 container_name, 포트와 같은 다른 정보를 지 웠습니다.)

net: "container:base 와 함께 사용하려는 경우 docker-compose build 명령에 오류 메시지가 표시됩니다.

ERROR: Service "mariadb" is trying to use the network of "lemp_base", which is not the name of a service or container.

이 솔루션에 대해 내가 싫어하는 점은 다른 모든 컨테이너가 base /var/www 폴더에 웹 서버 파일을 갖게된다는 것입니다.

편집하다:
어떤 이유로이 스택은 시작시 전체 /var/www 폴더를 삭제합니다.

내 겸손한 의견은 Docker Compose로 끝나는 모든 메커니즘이 컨테이너 간의 종속성에 대해 알고있는 모든 메커니즘이 우려 사항 분리에 위배된다는 것입니다. Docker Compose는 컨테이너 A와 B를 실행합니다. 컨테이너 A와 B는 자체 서비스를 담당합니다. B가 A에게 올바르게 작동하는 경우 A가 작동 상태가 될 때까지 기다리는 것은 B의 책임입니다. 토론에서 말했듯이 이것은 시간 초과, 재시도 등을 통해 수행 할 수 있지만 이것은 Docker Compose 나 A가 아닌 B의 문제입니다. SoC는 서비스 독립성과 적절한 확장을 위해 가장 중요합니다.

아이디어 3 @aanand 에 대한 작업이 있습니까? 진행 상황이 있는지 아는 것이 좋을 것입니다. 완벽한 솔루션은 아니지만 몇 가지 매우 일반적인 사용 사례를 도울 수있는 유망한 시작처럼 들렸습니다.

+1

+1

내가 틀렸을 수도 있지만 args: buildno:docker-compose.yml 버전 2에서 컨테이너를 주문할 수 있습니까?

나는 이것이 Compose에 속하지 않는 문제라는 데 동의하는 경향이 있습니다. @jwilder 의 우수한 Dockerize는 종속 컨테이너를 기다리는 지원 을 받았으며 대기중인 프로토콜 / 포트를 지정할 수 있습니다. 여기에 설명 된 대부분의 사용 사례에 적합하다고 제안합니다.

api:
  build: .
  ports:
   - "8000:80"
  expose:
  - "80"

test:
  build: test
  command: dockerize -wait http://api:80 -wait tcp://db:5432 somecommand -some arg -another arg2
  links:
    - api:api

이상적으로는 Docker Events API를 사용하여이를 자동으로 감지하지만, 이는 모든 컨테이너가 아마도 실행 가능하지 않거나 우리가 원하는 것 같은 Docker 런타임에 액세스해야 함을 의미합니다.

기다림은 compose 밖에서해야한다고 생각합니다. 제 개발자에서는 @mefellows가 제안한 것과 timercheck.io 상태 페이지의 하이브리드를 사용할 것입니다. RabbitMQ 또는 이와 유사한 것을 사용하는 번거 로움없이 필요한 것을 정확히 제공합니다.

우리는 15 초의 타임 아웃으로 열린 포트를 기다리는 쉘 스크립트 진입 점을 사용하고 있습니다.

#!/usr/bin/env bash

# wait for db to come up before starting tests, as shown in https://github.com/docker/compose/issues/374#issuecomment-126312313
# uses bash instead of netcat, because netcat is less likely to be installed
# strategy from http://superuser.com/a/806331/98716
set -e

echoerr() { echo "$@" 1>&2; }

echoerr wait-for-db: waiting for db:5432

timeout 15 bash <<EOT
while ! (echo > /dev/tcp/db/5432) >/dev/null 2>&1;
    do sleep 1;
done;
EOT
RESULT=$?

if [ $RESULT -eq 0 ]; then
  # sleep another second for so that we don't get a "the database system is starting up" error
  sleep 1
  echoerr wait-for-db: done
else
  echoerr wait-for-db: timeout out after 15 seconds waiting for db:5432
fi

exec "$@"

이것은 다가오는 (그리고 업데이트되는 문서와 함께 분명히 임박한) depend_on 의해 해결되어야합니다. 예?

아니. depends_on 는 주문 전용입니다. 실제로 다른 컨테이너의 시작을 지연 시키려면 프로세스가 자체 초기화를 완료 한시기를 감지하는 방법이 필요합니다.

아, 해명 해주셔서 감사합니다. =)

아마도 이것이 도움이 될 수 있습니다. http://www.onegeek.com.au/articles/waiting-for-dependencies-in-docker-compose

서비스 배포를 동기화하는 데 도움이되도록 docker 배포에 포함될 수있는 wait-for-it 이라는 순수한 bash 명령 줄 유틸리티를 작성했습니다.

나에게 임의의 "가용성 검사"모음을 하드 코딩하는 것은 좋은 생각이 아닙니다. 한 종류의 배포에만 국한되는 여러 상황이 있으며 모두 다 다룰 수는 없습니다. 예를 들어, 멀티 컨테이너 앱에서 특정 로그 파일에 특정 로그 메시지가 나타날 때까지 기다려야합니다. 그래야만 컨테이너 서비스가 준비됩니다.
대신 필요한 것은 구현할 수있는 SPI입니다. Docker가 가장 빈번한 사용 사례 (예 : TCP 연결)에 대한 몇 가지 예제 구현을 제공한다면 괜찮습니다. 하지만 내 자신의 기능을 연결하고 Docker가 호출하도록하는 방법이 있어야합니다.
Docker Compose는 컨테이너를 안정적으로 가동하고 실행할 수 없다면 전체 제품으로서 나에게 거의 쓸모가 없습니다. 따라서 안정적이고 균일 한 "컨테이너 서비스 준비 SPI"가 필요합니다. 그리고 "ready"는 더 많은 준비 수준 (예 : "now you can read"및 "now you can write")이있을 수 있으므로 부울이 아니어야합니다.

@realulim 좋은 글입니다. 나는 플러그인을 통해 서비스의 "준비"상태가 의미하는 바를 정의 할 수 있다는 생각에 전적으로 동의합니다. 또한 서비스가 http / tcp 연결을 수신하는지 확인하는 플러그인에 대한 기본값을 갖는 것도 좋은 생각이라고 생각합니다. 그것은 바로 거기에서 대부분의 경우를 다룰 것입니다.

이것이 제가 진입 점 파일에서 생각 해낸 것입니다.

until netcat -z -w 2 database 5432; do sleep 1; done
# do the job here, database host on port 5432 accepts connections

@kulbida ,
MySQL과 매우 유사한 작업을 수행합니다. 이 경우 "데이터베이스"는 작성 파일의 링크입니다.

if [[ "$APP_ENV" == "local" ]]; then
    while ! mysqladmin ping -h database --silent; do
        sleep 1
    done
    # Load in the schema or whatever else is needed here.
fi

이 스레드에는 시작 순서가 응용 프로그램 수준 오류 복구의 하위 집합 일 뿐이며 응용 프로그램이 처리해야한다고 주장하는 몇 가지 의견이 있습니다. 나는 이것이 항상 그런 것은 아닐 수도있는 곳을 설명하기 위해 한 가지 예를 제공하고 싶습니다. 일부 서비스가 클러스터 된 데이터베이스에 의존하고 충돌 등으로 인해 쿼럼이 손실 될 때마다 앱에서 자동으로 재 시도하고 싶지는 _ 않습니다 _. 예를 들어 데이터베이스 복구에 몇 가지 수동 단계가 필요하고 해당 단계가 수행 될 때까지 명확하게 중단 된 서비스가 필요한 경우에 해당 할 수 있습니다.

이제 앱의 오류 처리 로직이 시작 로직과 상당히 다를 수 있습니다.

  • 방금 시작하기 때문에 db가 다운 된 경우 사용할 수있을 때까지 기다리십시오.
  • 충돌로 인해 db가 다운 된 경우 심각한 오류를 기록하고 죽습니다.

가장 일반적인 시나리오는 아닐 수 있지만 가끔이 패턴이 나타납니다. 이 경우 클러스터링은 일반적인 경우의 "네트워크가 신뢰할 수 없음"문제를 해결하는 데 사용되며, 이는 앱에서 오류 조건을 재 시도해야하는 일부 기대치를 변경합니다. 클러스터 충돌은 거의 발생하지 않을 수 있으며 자동으로 다시 시작하는 것이 위험 할 수 있으므로 응용 프로그램에서 다시 시도하는 것보다 수동으로 서비스를 다시 시작하는 것이 좋습니다. 재시도시기에 대한 가정에 도전 할 수있는 다른 시나리오도 있다고 생각합니다.

좀 더 일반적으로 저는 시작 순서와 오류 처리가 항상 동일하지는 않으며 프레임 워크가 시작 순서를 관리하는 (선택적) 기능을 제공하는 것이 적절하다고 주장합니다. 그래도 이것이 구성하는 것이 아니라 도커 엔진에 속하는지 궁금합니다. compose 사용 여부에 관계없이 docker가 시작될 때마다 필요할 수 있습니다.

상태 확인 지원을 추가하기 위해 제안서 https://github.com/docker/docker/issues/21142 에서 도커 엔진 리포지토리에서 시작하는 토론이 있습니다. 이 지원을 사용할 수있게되면 Compose에서 구성 방법을 제공하고 지연된 시작에 사용할 수 있습니다.

파일 시스템을 사용하여 파일의 존재를 확인하는 것은 어떻습니까?

ready_on: /tmp/this_container_is_up_and_ready

이렇게하면 언제 작동하는지 결정하는 것은 컨테이너 개발자의 몫이지만 compose는 컨테이너가 자체적으로 준비를 선언 할 때까지 기다릴 수 있습니다. 명시적인 규칙이지만 해당 동작이없는 이미지에 추가 레이어로 쉽게 추가 할 수 있습니다.

상태 확인에 대한 기본 제공 지원이 좋습니다. 그 동안 로컬 도커 작성 설정에서 작업 한 해킹이 있습니다.

    nginx:
        image: nginx:latest
        command: /bin/bash -c "sleep 2 && echo starting && nginx -g 'daemon off;'"
        ...

(프로덕션에서 내 앱은 proxy_pass 사용하여 이미 실행중인 몇 개의 업스트림 서버로 프록시합니다. daemon off 것은 nginx를 단일 프로세스로 유지합니다. 그렇지 않으면 docker는 부모 프로세스가 데몬 자식을 생성하는 즉시 컨테이너를 중지합니다.)

내 2 센트를 추가하기 위해 ANT 빌드 도구를 사용하는 경우 특정 소켓이 열릴 때까지 실행을 지연시키는 기본 지원이 제공됩니다.

Jenkins CI 서버는 Docker Compose를 사용하여 프로젝트 컨테이너를 회전 한 다음 다음과 같이 기본 컨테이너 내에서 ANT를 실행합니다.

docker-compose up -d
docker exec -it projectx-fpm-jenkins ant -f /var/www/projectX/build.xml

이것은 docker-compose.yml 파일의 관련 구성 부분입니다. 위에서 논의했듯이 fpm을 mysql에 의존시키는 것으로는 MySQL 서비스가 실제로 필요할 때 준비가되었음을 보장하기에 충분하지 않습니다.

version: '2'
services:
  nginx:
    build: ./docker/nginx
    depends_on:
      - fpm
  fpm:
    build: ./docker/fpm
    depends_on:
      - mysql
  mysql:
    image: mysql:5.7
    environment:
      - MYSQL_ROOT_PASSWORD=projectx
      - MYSQL_DATABASE=projectx

그러나 ANT 작업 중에 기다릴 수 있습니다.

<!-- other targets... -->

<target name="setup db">
    <!-- wait until the 3306 TCP port in the "mysql" host is open -->
    <waitfor>
        <socket server="mysql" port="3306"/>
    </waitfor>

    <exec executable="php">
        <arg value="${consoledir}/console"/>
        <arg value="doctrine:database:create"/>
        <arg value="--no-interaction"/>
    </exec>
</target>

@kulbida 그게 트릭을 했어, 고마워. 좀 더 빠른 것 :

while ! nc -w 1 -z db 5432; do sleep 0.1; done

_depends_on_ 이 문제를 해결할 수 있습니다.
docker-compose 문서에서.
두 가지 효과가있는 서비스 간의 종속성을 표현합니다.

  1. docker-compose up은 종속성 순서대로 서비스를 시작합니다. 다음 예에서 db 및 redis는 웹보다 먼저 시작됩니다.
  2. docker-compose up SERVICE는 SERVICE의 종속성을 자동으로 포함합니다. 다음 예제에서 docker-compose up web은 db 및 redis도 만들고 시작합니다.

버전 : '2'
서비스:
편물:
짓다: .
Depend_on :
-db
-레디 스
redis :
이미지 : redis
db :
이미지 : postgres

@alexch : 고객 측 성능 테스트에서 (nginx +를 통해 라우팅되는 마이크로 서비스). Dockerized nginx 테스트-매우 높은 수준에서 거의 0에 가까운 낮은 수준으로 부하 감소가 1-2 분마다 반복되었습니다. 마지막으로 VM으로 실행되는 독하지 않은 Nginx를 사용하기로 결정했습니다 (대단한 성능 차이 때문에). 네트워크 드라이버 플러그인 / libNetwork 문제 일 수 있습니다.

@syamsathyan depends_on 이 (가) 도움이되지 않는 것 같습니다.

@skorokithakis , @kulbida 이것은 좋은 해결책입니다. 안타깝게도 netcat 는 데이터베이스에 연결해야하는 서비스 ( postgres )에서 기본적으로 사용할 수 없습니다. 대체 방법을 알고 있습니까?

@nottrobin 나는 두려워하지 않는다. 나는 단지 내 이미지에 그것을 설치했다 : /

@nottrobin 우리 팀이이 작업을 진행 중입니다. 하루나 이틀 후에 알려 드리겠습니다!

최근 bash를 사용하는 사용자를 위해 netcat이없는 솔루션이 있습니다 (http://stackoverflow.com/a/19866239/1581069에서 영감을 얻음).

while ! timeout 1 bash -c 'cat < /dev/null > /dev/tcp/db/5432'; do sleep 0.1; done

또는 덜 자세한 버전 :

while ! timeout 1 bash -c 'cat < /dev/null > /dev/tcp/db/5432' >/dev/null 2>/dev/null; do sleep 0.1; done

완벽하게 작동하는 @typekpb . 감사!

이제 HEALTHCHECK 지원이 https://github.com/docker/docker/pull/23218에 따라 업스트림에 병합되었으므로 다음 순서를 시작하기 전에 컨테이너가 정상 상태인지 확인하는 데 고려할 수 있습니다. 퍼즐의 절반이 해결되었습니다. :)

이제 HEALTHCHECK 지원이 docker / docker # 23218에 따라 업스트림으로 병합되었으므로 다음 순서를 시작하기 전에 컨테이너가 정상 상태인지 확인하는 것으로 고려할 수 있습니다. 퍼즐의 절반이 해결되었습니다. :)

좋아 보인다. docker-compose.yml 에서 구현하는 방법

좋아 보인다. docker-compose.yml에서 구현하는 방법은 무엇입니까?

퍼즐의 다른 부분은 건강한 컨테이너에 대한 docker-compose watch를 가지고 있으며, 이번 호에서 더 언급 된 depends_on 구문과 같은 것을 사용하는 것입니다. 작업을 수행하려면 docker-compose 패치가 필요합니다.

또한 Docker의 상태 확인 기능은 현재 릴리스되지 않았으므로 Docker / Docker Compose 릴리스주기와 일치해야 할 수도 있습니다.

.waitForPort() 메서드가있는 js 라이브러리를 작성했습니다. 이전에 언급했듯이 모든 상황에서 작동하지 않을 수도 있지만 대부분의 사용 사례에서는 잘 작동 할 수 있습니다.
내 블로그를 참조하십시오 .

HEALTHCHECK 병합은 좋은 소식입니다.

그 동안 이 문서 에서는 문제와 몇 가지 해결책에 대해 설명합니다.

이것으로 충분하지 않습니까?

https://docs.docker.com/compose/startup-order/

@pablofmorales 아니요, depends_on 는 컨테이너가 작동 중인지 확인하기 때문입니다.

일부 데몬은 자신을 부트 스트랩하고 할당 된 포트와 주소, 특히 MySQL을 수신하는 데 약간의 추가 시간이 필요합니다.

여전히 "READY_ON"선언이 전반적으로 최고라고 생각합니다. 이미지에 관계없이 컨테이너 자체에 무언가 준비가되었는지에 대한 결정은 남겨두고 Docker Remote API의 리소스 경로 (컨테이너 내) 기능은 필요한 최소한의 변경을 보장합니다.

컨테이너가 "업"상태 일 때의 동작이 이것이 가져야하는 유일한 영향입니다. READY_ON 파일이있을 때만 "up"으로보고됩니다.

나는 이것이 모든 사람들이 논의한 행동의 90 %라고 생각합니다. 여기에서 "건강 체크"가 2 개의 다른 이벤트로 합쳐지고 있다고 생각하지만,이를 하나로 묶으려고합니다. 하나는 인프라를 가동 할 때 일련의 이벤트에 대해 "준비"되고 다른 하나는 인프라가 유지 될 수 있도록 "상태"입니다.

"ready"는도 커가 도와주기에 전적으로 적절한 장소입니다. "건강"은 시스템 측면에서 매우 다양하므로이를 처리하는 것은 컨테이너에 달려 있다고 생각합니다.

상태 확인에 대한 더 나은 대안으로 상태뿐만 아니라 서비스 검색 및 모니터링도 포함하는 containerpilot과 같은 것을 살펴볼 수 있습니다. https://github.com/joyent/containerpilot

예, 이것은 정확하고 중요한 구별입니다. 그러나 컨테이너는 이미지가 훨씬 더 복잡해지지 않고 어떻게 해당 파일을 작성합니까? 이것을 사용하려는 모든 단일 컨테이너에 대해 래퍼 스크립트가 필요한 것 같습니다.

어쨌든 인스턴스를 초기화하려면 스크립트를 시작해야합니다. 스크립트가 마지막으로해야 할 일은 파일을 터치하는 것입니다. 나에게 그것은 상태 확인을 위해 원격 컴퓨터에서 exec를 실행하는 것보다 훨씬 쉬운 것 같습니다. 적어도 터치 파일을 사용하면 컨테이너의 컨텍스트를 입력 할 필요없이 수동적으로 API를 통해 완전히 감시 할 수 있습니다.

동의하지만 많은 컨테이너가 스크립트를 사용하지 않고 Postgres 또는 Redis와 같은 서비스를 설치하고이를 보지 않고 시작하도록합니다.

제 경우에는 Kong API Gateway를 사용하고 있습니다.

콩 컨테이너를 실행하기 전에 Cassandra가이 스크립트로 작동하는지 확인합니다.

while true; do
    CHECK=`kong-database/check`
    if [[ $CHECK =~ "system.dateof" ]]; then
        break
    fi
    sleep 1;
done

체크 파일은 이것을 포함합니다

#!/bin/bash
docker cp cassandra-checker kong-database:/root/
docker exec -i kong-database cqlsh -f /root/cassandra-checker

cassandra-checker는 단순한 쿼리입니다.

SELECT dateof(now()) FROM system.local ;

물론입니다.하지만 대체 방법은 상태 확인으로, 어쨌든 작성해야하는 스크립트가 필요하므로 오버 헤드 차이가 없습니다. 또한 명시적인 옵트 인으로,이 동작을 원한다는 것을 의미합니다. 스크립트를 실행하지 않는 것에 관해서는 항상 pid 파일이나 유닉스 소켓에 대해 ready_on 경로 검사를 할 수 있습니다. 스크립트가 필요하지 않습니다.

사실입니다. 당신 말이 맞습니다.

파일의 존재를 확인하는 것은 많은 경우에 괜찮을 수 있지만 컨테이너가 필요하지 않을 때 시작 스크립트를 사용하도록 강제하는 것은 성가신 일입니다. 다른 매우 간단한 조건에 대한 검사도 할 수없는 이유는 무엇입니까? 특히 유용한 것은 프로세스가 특정 tcp 포트에서 수신 대기 할 때까지 기다리는 것입니다.

이 아이디어는 옵트 인이므로 어떠한 강제도 없습니다. 사실 당신은 무엇을 기대해야하는지 명시 적으로 말하고 있습니다.

실행이 필요한 설정 데이터가 많을 수 있으므로 컨테이너가 초기화 된시기를 알려주기에는 TCP 포트 수신 대기가 충분하지 않을 수 있습니다. 도대체 tcp를 통해서도 postgres 컨테이너에 너무 빨리 연결하면 db가 아직 준비되지 않았다는 오류가 표시됩니다.

내가 정확하게 이해한다면 "선택하지 않으면이 기능을 사용할 수 없습니다"입니다. 이 기능이 필요하고 내 앱이 pid 파일을 사용하지 않는 경우 강제로 시작 스크립트를 사용해야합니다.

MySQL의 경우 (OP의 경우) 일단 듣고 나면 준비가 된 것입니다. 그들은 이것이 사실인지 확인하기 위해 많은 문제를 겪습니다. 내 생각에는 이러한 조건에 대해 준비된 검사를 구성하는 "옵트 인"할 수 있도록 열거 할 수있는 조건의 짧은 목록이있을 수 있습니다. 나는 그것이 단 하나의 방법으로 이루어져야 할 이유가 없다고 생각합니다.

mysql의 경우 일단 수신되면 준비되지 않았습니다. 간단한 하나의 노드의 경우 준비가되지만 노드가 두 개 이상이면 아직 준비되지 않은 것입니다. "유일한 방법"이 의미하는 바를 이해합니다.하지만 기본 추상화로서 완벽하다고 생각합니다. 원하는 툴링을 적용 할 수있는 지점으로 더 많이 봅니다. 스크립트는 외부 서비스와 통신하고 컨테이너를 확인하도록 할 수도 있습니다.이 경우 외부 서비스는 컨테이너 에이전트가 파일을 작성하도록 신호를 보낼 수 있습니다. 유연성 ftw.

이 "조건"목록에있는 것을 시도하면 항상 작동하지 않는 경우가 있습니다. 그러나 파일을 건 드리면 항상 작동합니다. 이미지가 언제 준비되었다고 생각하는지 알기 때문에 (오, 다른 호스트에서 기다려야하고, 파일을 다운로드해야하고, $ external_service도 사용할 수 있는지 확인해야합니다. 제대로,하지만 어떤 이유로 데이터베이스에 대한 올바른 권한이 없습니다.이 이미지가 읽기 전용 인 이유 등.

이런 종류의 스크립트는 이미 도처에 존재합니다. 전에는 이와 같은 기능이 없었기 때문에 이러한 스크립트를 작성하는 것이 이미 필요했습니다. 따라서 스크립트가 이미 존재할 가능성이 높기 때문에 이와 같은 스크립트를 삽입하는 것은 최소화됩니다.

또 다른 가능한 경우는 해당 호스트에 대해 chef 또는 ansible과 같은 것을 실행 한 다음 파일을 작성하는 것입니다.

Docker 측 검사의 문제라면 다음과 같습니다.

UPCHECK --port=7474 --interval=0.5s --response="Please log in"

기록을 위해 파일 솔루션이 많은 장점을 가지고 있다고 생각하지만 복잡성도 도입합니다.
80 %의 시간 동안 tcp 응답을 확인하면 잘 작동합니다.

글쎄 ... 내 생각 엔 :

UPCHECK --file=/tmp/container_is_ready --interval=0.5s --timeout=2m

똑같습니다.

실제로 특정 조건을 기다리는 기능을 추가하는 docker-compose의 재 구현 작업을하고 있습니다. libcompose를 사용하고 (그래서 도커 상호 작용을 다시 빌드 할 필요가 없습니다)이를 위해 많은 구성 명령을 추가합니다. 여기에서 확인하세요 : https://github.com/dansteen/controlled-compose

코드가 완성되었지만 실제로 사용되기 전에 몇 가지 업스트림 문제가 해결되기를 기다리고 있습니다.

Goss 는 컨테이너 시작을 지연시키기 위해 상당히 유연한 shim으로 사용할 수 있습니다. 여기에 이미지를 약간 변경하여 이것이 수행되는 방법을 설명하는 블로그 게시물을 작성했습니다.

Kubernetes에는 init-containers 라는 개념이 있습니다. compose / swarm이 비슷한 개념의 이점을 얻을 수 있는지 궁금합니다.

+1

컨테이너에 노출하는 서비스가 준비되었는지 또는 서비스를 노출 할 수 있는지 여부를 결정하도록하는 것이 더 낫다고 생각합니다.

예를 들어 PHP 애플리케이션의 경우 MySQL의 연결에 따라 달라질 수 있습니다. 그래서 PHP 컨테이너의 ENTRYPOINT 에 다음과 같이 썼습니다.

#!/bin/bash
cat << EOF > /tmp/wait_for_mysql.php
<?php
\$connected = false;
while(!\$connected) {
    try{
        \$dbh = new pdo( 
            'mysql:host=mysql:3306;dbname=db_name', 'db_user', 'db_pass',
            array(PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION)
        );
        \$connected = true;
    }
    catch(PDOException \$ex){
        error_log("Could not connect to MySQL");
        error_log(\$ex->getMessage());
        error_log("Waiting for MySQL Connection.");
        sleep(5);
    }
}
EOF
php /tmp/wait_for_mysql.php
# Rest of entry point bootstrapping

이런 식으로 내가 노출하는 서비스의 종속성, 즉 php가 해결되었는지 확인하는 로직을 추가 할 수 있습니다.

Nabin Nepal schrieb :

컨테이너에 노출하는 서비스가 준비되었는지 또는 서비스를 노출 할 수 있는지 여부를 결정하도록하는 것이 더 낫다고 생각합니다.

물론이 동작을 사용하는 모든 컨테이너에 하드 코딩 할 수 있습니다.
MySql 컨테이너. 그러나 MySql 서비스의 내용이 변경되면
반복적 인 코딩은 말할 것도없고 모든 종속 컨테이너 변경
각각에 필요합니다. 이것은 DRY가 아니며 안정적인 계약이 없으므로
부서지기 쉬운 시스템으로 이어집니다.

소프트웨어 장인의 관점에서 볼 때
컨테이너 개발자가 구현할 수있는 "컨테이너 준비 SPI". 의 위에
다른쪽에는 "Container Readiness API"가 있어야합니다.
서비스에 의존 할 수 있습니다.

Ulrich

@realulim MySQL 컨테이너의 모든 변경 사항은 영향을 받거나 연결된 모든 컨테이너에 복제되거나 전파되어야한다는 데 동의합니다.

그러나 변경 사항이 DB_HOST, DB_NAME, DB_USER 및 DB_PASSWORD와 같은 매개 변수에 관한 것입니다. 이들은 ARG (인수)로 전달 될 수 있으며 모든 관련 컨테이너에서 공유 될 수 있습니다. docker-compose.yml 파일을 사용하는 경우 한 파일에서 변경 사항이 발생합니다.

그리고 컨테이너의 준비 상태를 확인하는 API가이 문제를 해결하는 실제 방법이라는 데 전적으로 동의하지만, 노출되는 서비스가이를 선언하기에 더 나은 후보가 될 것이라고 믿습니다.

해결 방법 until nc -z localhost 27017; do echo Waiting for MongoDB; sleep 1; done

@ piotr-s-brainhub 위의 주석에서 포트가 열려 있다고해서 서비스가 준비되었음을 의미하지는 않는다고 언급합니다.

로그, 포트 개방 또는 시간 지연에 의해 트리거 될 수있는 선택적 준비 상태를 가질 수 있습니까? 다음과 같은 것 :

ready_when:
  in_logs: `MySQL init process done`
  ports_open:
  - 3306

의존성 컨테이너가 준비 될 때까지 기다리는 것이 ansible과 같은 도구로 쉽게 구현 될 수 있다는 것을 방금 깨달았습니다. 누구든지 그 접근 방식을 사용 했습니까? docker-compose를 ansible / chef / puppet으로 쉽게 대체 할 수 있습니까? 이 접근 방식을 보여주는 github의 프로젝트가 있습니까?

참고 : 현재 종속성을 사용할 수없는 경우에도 실행할 수있는 강력한 서비스 작성의 중요성을 이해합니다. 그것은 질문이 아닙니다.

나는 요즘 내가 작성한 도구로 이것을 해결했다 : https://github.com/betalo-sweden/await

주어진 리소스 목록을 사용할 수있을 때까지 기다렸다가 암시 적으로 다음 명령으로 이동하거나 명시 적으로 호출하여 계속하려는 작업을 계속할 수 있습니다.

@djui , 주어진 리소스를 기다리는 동안 await는 무엇을합니까?

@derekmahar 그것은 투표합니다. 기본 시간 제한은 60 초입니다. 리소스를 볼 수 없을 때마다 1 초 간격으로 재 시도합니다. 현재는 동시 리소스 감지를 수행하지 않으므로 순차적이지만 충분한 것으로 판명되었으며 수정할 수 있습니다.

다음 시나리오에서 사용합니다.

도커 구성 인프라를 가동 한 다음 통합 테스트 드라이버를 실행합니다. 드라이버 서비스는 await를 사용하여 인프라의 모든 구성 요소를 사용할 수있는 경우에만 시작됩니다. 그래서 await는 결국 드라이버의 실행 명령을 호출합니다.

다음은 make를 사용하여 새로운 Docker HEALTHCHECK 지시문으로이를 수행하는 방법입니다.

https://gist.github.com/mixja/1ed1314525ba4a04807303dad229f2e1

[업데이트 : Docker 1.12가 중지 된 컨테이너의 Healthcheck 상태를 "시작"으로 다소 어리석게 보고하므로 컨테이너가 오류 코드와 함께 종료되는 경우 처리 할 요점 업데이트]

감사합니다 @mixja , 좋은 솔루션.

@mixja , 좋은 솔루션! 이것이 바로 제가 상자에서 나올 것으로 기대하는 기능입니다. 그러나 이제 문제는 컨테이너를 수동으로 시작하는 경우 왜 docker-compose가 필요합니까?

테스트를 위해 https://github.com/avast/docker-compose-gradle-plugin 을 사용하고 Docker 상태 확인도 사용합니다.

@korya -Docker compose는 실제로 오케스트레이션 도구가 아닙니다. 환경 사양 및 관리 도구에

@mixja 글쎄, 당신이 옳을 수 있습니다. 그러나 많은 사람들이이 스레드에서 지적했듯이 테스트 환경에서는 오케스트레이션 기능이 매우 필요하며, 도구 상자에 docker-compose가있는 경우 docker-compose에서 이러한 종류의 기능을 요구하는 것이 매우 유혹적입니다.

실제로 "Compose는 다중 컨테이너 Docker 애플리케이션을 정의하고 실행하기위한 도구입니다"라는 문서에 따르면. compose가 오케스트레이션 도구라고 말하지는 않지만 사용자의 관점 (예 : 나 자신)에서 "멀티 컨테이너 Docker 애플리케이션을 정의하고 실행하는 도구"에서 관리되는 컨테이너 간의 기본 종속성 관리를 지원하는 것이 당연하다고 생각합니다. 상자 밖으로.

나는 도구가 그것을 지원해야한다고 말하는 것이 아니다. 내가 말하는 것은 그것을 기대하는 것이 매우 당연하다는 것입니다. 그렇지 않으면 모든 사람이이를 수행 할 수있는 매우 현명한 방법을 찾아야합니다. 사실, 우리는 makefile이하는 것과 비슷한 일을하는 bash 스크립트를 사용합니다.

@mixja @korya 내 도구 개선하고자하는 await를을 하고 메이크 버전 즉 이상 가능 / / 더 편리 실종 제공하는 어떤 의견을 부탁드립니다 await .

healthcheck + make 버전이 "글로벌"보기 인 것 같고 단일 컨테이너가 글로벌 상태를 알지 못하며 (그러나 makefile은 알 수 있음) await 는 "로컬"보기이며, 활성화 된 각 컨테이너는 (유일한) depends_on 또는 links 와 유사하게 알아야 할 사항입니다. 또한 상태 확인에 필요한 도구 (때로는 기본값, 예 : mysqlshow )와 함께 컨테이너를 제공하고 그렇지 않으면 Dockerfile을 그대로 둡니다. 또한 Docker-compose를 더 이상 구성에 주로 사용하지 않고 주로 유연한 구성에 사용하는 것 같습니다 (예 : docker-compose up -d mysqldocker run -d -e ... -v ... -p ... mysql 와 동일해야 함).

안녕하세요 @djui- 아마도 철학적 인 관점 일 것입니다.하지만 HEALTHCHECK의 전체 전제는 올바른 동작을 촉진하는 것이라고 생각합니다. 즉, 컨테이너는 외부 종속성없이 컨테이너 상태를 설정하는 수단을 제공 할 수 있습니다.

이것은 외부에서 연결을 확인하는 것의 가치를 결코 손상 시키지는 않지만 일반적으로 연결 및 훨씬 더 많은 (예 : 응용 프로그램 기능)을 확인하려는 경우이를 다루기 위해 일련의 수용 테스트를 실행합니다. 물론 전체 환경이 설정되고 await 도구의 범위와 내가 과거에 사용한 다른 접근 방식 ( agent 래핑 된 Ansible 플레이 북)이 설정 될 때까지 일반적으로이 수준의 테스트를 실행할 수 없습니다 await agent 컨테이너)는 실제로 환경 설정을 올바르게 조정하는 데 초점을 맞추고 있으며 (수락 테스트의 최종 목표가 아님) 지금까지 Docker 세계에서 사용할 수있는 유일한 접근 방식이었습니다.

Docker 1.12를 통해 이제 컨테이너가 자체 상태 확인을 정의하는 한 Docker 환경을 조사 할 수있는 수단과 잘 설정된 구조 (예 : bash / shell 메커니즘)를 사용하여 특정 상태를 "대기"할 수 있습니다. . 플랫폼의 기본 기능을 활용하고 컨테이너 소유자가 자신의 상태 확인을 정의하도록 권장하는 것이 더 많은 가치를 봅니다. 기존의 외부 (응용 프로그램 프로세스를 시작했지만 더 이상 문제가 아닙니다) 접근 방식에 의존하지 않습니다. 의지하십시오.

관련 비유로 AWS CloudFormation과 그룹 자동 확장 및 롤링 업데이트 오케스트레이션 개념을 고려하십시오. CloudFormation은 새 인스턴스가 "정상"상태인지 여부를 어떻게 알 수 있으며 이전 인스턴스를 종료하고 다른 새 인스턴스를 롤인 할 수 있습니까? 외부 상태 확인을 작성합니까 아니면 인스턴스 자체에 의존하여 상태를 신호합니까? 대답은 후자입니다. 이는 인스턴스 소유자가 자신의 인스턴스에 필요한 모든 성공 기준을 설정 한 다음 가장 중요한 오케스트레이션 시스템 (예 : CloudFormation)에 인스턴스가 "정상"임을 알릴 수 있음을 의미합니다.

Docker Compose에 대한 귀하의 의견과 관련하여 언급 한 두 가지 측면을 모두 제공 할 수있는 도구입니다. docker-compose.yml 부분은 원하는 상태 구성 환경 사양이며, 다양한 docker-compose 명령은 다양한 방식으로 환경과 상호 작용하는 기능을 제공합니다. 기본적으로 docker-compose 는 서비스 간의 종속성 관리를 충분히 수행하지 않기 때문에 현재로서는 외부 조정 도구가 필요합니다. docker-compose 기본 상태 확인 지원과 같은 기능이 제공되므로 단일 docker-compose up 명령의 목표는 예를 들어 이전에 정상으로 표시되어야하는 서비스를 지정할 수 있다고 가정하면보다 현실적입니다. 이는 "업"으로 간주되며 이는 종속 서비스가 종속성이 정상이 될 때까지 효과적으로 대기 함을 의미합니다.

@mixja 자세한 설명을

플랫폼의 기본 기능을 활용하는 데 더 많은 가치가 있습니다.

좋은 / 요점입니다. Docker Compose가 Depends_on 또는 새 키에서 기본적으로 상태 확인을 활용할 때까지 기다리면됩니다. 예를 들어 --abort-on-container-exit 가 설정되어 있고 런타임 중 상태 확인이 상태 확인 레이블을 _unhealthy_로 설정하면 기본적으로 연결된 컨테이너를 가져 와서 그보다 한 단계 더 나아가 야 / 할 것인지 궁금합니다.

테스트를 실행하기 위해 delay 기능을 원하는 사용자를위한 임시 해결 방법 :

두 개의 docker-compose yml 파일이 있습니다. 하나는 테스트 용이고 다른 하나는 개발 용입니다. 차이점은 docker-compose.test.yml sut 컨테이너가 있다는 것입니다. sut 컨테이너는 pytest 합니다. 내 목표는 docker-compose 테스트를 실행하는 것이었고 sut 컨테이너의 pytest 명령이 실패하면 개발을 실행하지 마십시오 docker-compose . 내가 생각해 낸 것은 다음과 같습니다.

# launch test docker-compose; note: I'm starting it with -p argument
docker-compose -f docker-compose.test.yml -p ci up --build -d
# simply get ID of sut container
tests_container_id=$(docker-compose -f docker-compose.test.yml -p ci ps -q sut)
# wait for sut container to finish (pytest will return 0 if all tests passed)
docker wait $tests_container_id
# get exit code of sut container
tests_status=$(docker-compose -f docker-compose.test.yml -p ci ps -q sut | xargs docker inspect -f '{{ .State.ExitCode  }}' | grep -v 0 | wc -l | tr -d ' ')
# print logs if tests didn't pass and return exit code
if [ $tests_status = "1" ] ; then
    docker-compose -f docker-compose.test.yml -p ci logs sut
    return 1
else
    return 0
fi

이제 위의 코드를 원하는 함수 (내는 test 라고 함)에서 사용할 수 있으며 다음과 같이 할 수 있습니다.

test_result=$?
if [[ $test_result -eq 0 ]] ; then
    docker-compose -f docker-compose.yml up --build -d
fi

나를 위해 잘 작동하지만 여전히 docker-compose 이러한 종류의 기본 지원을 기대하고 있습니다. :)

+1

아마도 docker-compose의 핵심 외부에서 고려되는 것들은 플러그인을 허용함으로써 지원 될 수 있습니까? 요청 # 1341과 유사하게 일부는 유용하다고 생각할 수있는 추가 기능이 있지만 반드시 현재 비전과 완전히 일치하지는 않습니다. 아마도 # 3905에서 제안한 것과 같은 플러그인 시스템을 지원하면 핵심 기능 집합에 초점을 맞출 수있는 방법을 제공 할 수 있으며 이것이 아닌 경우 특정 사용 사례에 대해 원하는 사람들은 up 수행을 처리하는 플러그인을 작성할 수 있습니다.

docker-compose 을 (를) 기본 진입 점 대신 기본 진입 점 역할을하기 위해 모든 앞에 앉아있는 스크립트를 추가 할 필요없이 docker env 설정과 관련하여 로컬에있는 모든 프로젝트에 대한 진입 점으로 사용할 수 있으면 좋을 것입니다. 이상한 경우에 스크립트를 실행하는 것을 기억해야하는 사람들.

다음은 healthcheck 및 docker-compose 2.1+ .

version: "2.1"
services:
  db:
    image: mysql:5.7
    environment:
      MYSQL_ROOT_PASSWORD: password
    healthcheck:
      test: mysqladmin -uroot -ppassword ping
      interval: 2s
      timeout: 5s
      retries: 30
  web:
    image: nginx:latest # your image
    depends_on:
      db:
        condition: service_healthy

여기서 docker-compose up 는 db 컨테이너가 정상으로 간주 된 후에 만 ​​웹 컨테이너를 시작합니다.

이미 언급 된 경우 미안하지만 전체 솔루션이 게시 된 것 같지 않습니다.

다음은 PostgreSQL을위한 방법입니다.

감사합니다 @Silex 👍

version: '2.1'
services:
  db:
    image: postgres:9.6.1
    healthcheck:
      test: "pg_isready -h localhost -p 5432 -q -U postgres"
      interval: 3s
      timeout: 5s
      retries: 5

@Silex 버전 "3"및이 형식 :

    image: nginx:latest # your image
    depends_on:
      db:
        condition: service_healthy

ERROR: The Compose file './docker-compose.yml' is invalid because: depends_on contains an invalid type, it should be an array

2.1은 계속해서 지원하며 더 이상 사용되지 않을 것입니다. 3.x는 주로 swarm 서비스 모드 (비 로컬) 용입니다.

  From: Vlad Filippov <[email protected]>

받는 사람 : docker / compose [email protected]
참조 : mbdas [email protected] ; [email protected]
전송 : 2017 년 3 월 8 일 수요일 오전 11:45
제목 : Re : [docker / compose] 더 긴 시작 시간으로 종속 서비스를 지원하기 위해 컨테이너 시작을 지연하는 방법이 있습니까 (# 374)

@Silex 버전 "3"및이 형식 : 이미지 : nginx : latest # 이미지
Depend_on :
db :
조건 : service_healthy
ERROR : The Compose file './docker-compose.yml'is invalid because : services.auth.depends_on contains an invalid type, it should be an array-
당신이 언급 되었기 때문에 이것을 받고 있습니다.
이 이메일에 직접 답장하거나 GitHub에서 보거나 스레드를 음소거하십시오.

2.1은 계속해서 지원하며 더 이상 사용되지 않을 것입니다. 3.x는 주로 swarm 서비스 모드 (비 로컬) 용입니다.

감사!

@vladikoff : https://github.com/docker/compose/issues/4305 에서 버전 3에 대한 자세한 정보

기본적으로 지원되지 않으므로 Docker-compose에 의존하는 대신 컨테이너를 내결함성으로 만들어야합니다.

나는 이것이 지금 닫힐 수 있다고 믿는다.

불행히도 v3에서는 더 이상 조건이 지원되지 않습니다 . 내가 찾은 해결 방법은 다음과 같습니다.

website:
    depends_on:
      - 'postgres'
    build: .
    ports:
      - '3000'
    volumes:
      - '.:/news_app'
      - 'bundle_data:/bundle'
    entrypoint: ./wait-for-postgres.sh postgres 5432

  postgres:
    image: 'postgres:9.6.2'
    ports:
      - '5432'

wait-for-postgres.sh :

#!/bin/sh

postgres_host=$1
postgres_port=$2
shift 2
cmd="$@"

# wait for the postgres docker to be running
while ! pg_isready -h $postgres_host -p $postgres_port -q -U postgres; do
  >&2 echo "Postgres is unavailable - sleeping"
  sleep 1
done

>&2 echo "Postgres is up - executing command"

# run the command
exec $cmd

@ slava-nikulin 사용자 지정 진입 점은 일반적인 관행이며, 컨테이너에서 앱을 시작하기 전에 필요한 모든 조건을 정의하고 확인할 수있는 거의 유일한 (도커 네이티브) 방법입니다.

사실은 많은 논쟁이 있었고, 상태 확인과 기본적으로 통합하고 스타트 업을 주문하는 조건부 지원에 대한 2.x 지원이 훨씬 필요한 지원이라고 생각합니다. Docker는 기본적으로 컨테이너의 로컬 포드를 지원하지 않으며, 지원할 때 예를 들어 kubernetes가 의미를 제공하는 것처럼 유사한 것을 다시 지원해야합니다.

Docker 3.x는 구성에 무리 지원을 제공하는 시리즈이므로 분산 된 특성을 염두에두고 많은 옵션이 삭제되었습니다.

2.x 시리즈는 원래의 작성 / 로컬 토폴로지 기능을 유지합니다.

Docker는 이러한 두 버전을 병합하는 방법을 알아야합니다. compose의 기능 집합을 줄여서 swarm을 compose로 강제하는 것은 환영할만한 방향이 아니기 때문입니다.

2017 년 5 월 10 일 오후 8시 15 분에 Slava Nikulin [email protected] 은 다음과 같이 썼습니다.

불행히도 v3에서는 더 이상 조건이 지원되지 않습니다. 내가 찾은 해결 방법은 다음과 같습니다.

웹 사이트 :
Depend_on :
- '포스트그레스'
짓다: .
포트 :
- '3000'
볼륨 :
- '. : / news_app'
- 'bundle_data : / bundle'
진입 점 : ./wait-for-postgres.sh postgres 5432

postgres :
이미지 : ' postgres : 9.6.2 '
포트 :
- '5432'
wait-for-postgres.sh :

! / bin / sh

postgres_host = $ 1
postgres_port = $ 2
cmd = "$ @"

postgres도 커가 실행될 때까지 기다립니다.

동안 ! pg_isready -h $ postgres_host -p $ postgres_port -q -U postgres; 하다

& 2 echo "Postgres를 사용할 수 없습니다-잠자기"
수면 1
끝난

& 2 echo "Postgres가 작동 중입니다-명령 실행 중"

명령을 실행

exec $ cmd

당신이 언급 되었기 때문에 이것을 받고 있습니다.
이 이메일에 직접 답장하거나 GitHub에서 보거나 스레드를 음소거하십시오.

나는 이런 식으로 할 수 있었다
// start.sh

#!/bin/sh
set -eu

docker volume create --name=gql-sync
echo "Building docker containers"
docker-compose build
echo "Running tests inside docker container"
docker-compose up -d pubsub
docker-compose up -d mongo
docker-compose up -d botms
docker-compose up -d events
docker-compose up -d identity
docker-compose up -d importer
docker-compose run status
docker-compose run testing

exit $?

// status.sh

#!/bin/sh

set -eu pipefail

echo "Attempting to connect to bots"
until $(nc -zv botms 3000); do
    printf '.'
    sleep 5
done
echo "Attempting to connect to events"
until $(nc -zv events 3000); do
    printf '.'
    sleep 5
done
echo "Attempting to connect to identity"
until $(nc -zv identity 3000); do
    printf '.'
    sleep 5
done
echo "Attempting to connect to importer"
until $(nc -zv importer 8080); do
    printf '.'
    sleep 5
done
echo "Was able to connect to all"

exit 0

// 내 도커에서 파일 작성

  status:
    image: yikaus/alpine-bash
    volumes:
      - "./internals/scripts:/scripts"
    command: "sh /scripts/status.sh"
    depends_on:
      - "mongo"
      - "importer"
      - "events"
      - "identity"
      - "botms"

비슷한 문제가 있지만 약간 다릅니다. MongoDB가 복제 세트를 시작하고 초기화 할 때까지 기다려야합니다.
도커에서 모든 절차를 수행하고 있습니다. 즉, 복제 세트 생성 및 인증. 하지만 복제본 세트의 기본 노드에 연결해야하는 또 다른 Python 스크립트가 있습니다. 거기에 오류가 있습니다.

docker-compose.txt
Dockerfile.txt
그리고 파이썬 스크립트에서 이와 같은 작업을 시도합니다.
for x in range(1, 4): client = MongoClient(host='node' + str(x), port=27017, username='admin', password='password') if client.is_primary: print('the client.address is: ' + str(client.address)) print(dbName) print(collectionName) break

그렇게하는 데 어려움이 있습니다. 누구든지 아이디어가 있습니까?

@patrickml Docker compose를 사용하지 않으면
내 build_all.cql을 실행하려면 'cqlsh'가 필요합니다. 그러나 'cqlsh'는 준비되지 않았습니다 ... 60 초 동안 기다려야합니다.

고양이 Dockerfile

저장소 / datastax / dse- 서버에서 : 5.1.8

USER 루트

apt-get 업데이트 실행
apt-get install -y vim 실행

db-scripts-2.1.33.2-RFT-01.tar / docker / cms / 추가
entrypoint.sh /entrypoint.sh 복사

WORKDIR /docker/cms/db-scripts-2.1.33.2/
cqlsh -f build_all.cql 실행

사용자 dse

=============

8/9 단계 : cqlsh -f build_all.cql 실행
---> 08c8a854ebf4에서 실행
연결 오류 : ( 'Unable to connect to any servers', { '127.0.0.1': error (111, "Tried connections to [( '127.0.0.1', 9042)]. 마지막 오류 : 연결이 거부되었습니다.")})
'/ bin / sh -c cqlsh -f build_all.cql'명령이 0이 아닌 코드를 반환했습니다. 1

필요 = var-lib-libvirt.mount var-lib-libvirt-images-ram.mount

이 페이지가 도움이 되었나요?
0 / 5 - 0 등급