fig up: Docker-контейнеры запускают синхронизацию

Для одного из моих домашних проектов я решил использовать докер-контейнеры и рис для оркестровки (впервые с помощью этих инструментов).

Вот мой fig.yaml:

rabbitmq:
  image: dockerfile/rabbitmq:latest
mongodb:
  image: mongo
app:
  build: .
  command: python /code/app/main.py
  links:
   - rabbitmq
   - mongodb
  volumes:
   - .:/code

Время запуска Rabbitmq намного медленнее, чем время загрузки моего приложения. Несмотря на то, что контейнер rabbitmq начинает загружаться первым (так как он находится в ссылках приложения), когда мое приложение пытается подключиться к серверу rabbitmq, оно еще не доступно (это определенно проблема с синхронизацией загрузки, поскольку, если я просто вставлю sleep на 5 секунд перед подключением к rabbitmq - все отлично работает). Есть ли какой-нибудь стандартный способ решения проблем синхронизации времени загрузки?

Благодарю.

3 ответа

Решение

Я не думаю, что есть стандартный способ решить эту проблему, но это известная проблема, и у некоторых людей есть приемлемые обходные пути.

На трекере проблем Docker есть предложение не рассматривать контейнер как запущенный, пока он не прослушивает открытые порты. Однако, вероятно, он не будет принят из-за других проблем, которые он может создать в другом месте. На эту же тему есть и фига.

Простое решение - спать, как говорит @jcortejoso. Пример из http://blog.chmouel.com/2014/11/04/avoiding-race-conditions-between-containers-with-docker-and-fig/:

function check_up() {
    service=$1
    host=$2
    port=$3

    max=13 # 1 minute

    counter=1
    while true;do
        python -c "import socket;s = socket.socket(socket.AF_INET, socket.SOCK_STREAM);s.connect(('$host', $port))" \
        >/dev/null 2>/dev/null && break || \
        echo "Waiting that $service on ${host}:${port} is started (sleeping for 5)"

        if [[ ${counter} == ${max} ]];then
            echo "Could not connect to ${service} after some time"
            echo "Investigate locally the logs with fig logs"
            exit 1
        fi

        sleep 5

        (( counter++ ))
    done
}

А потом использовать check_up "DB Server" ${RABBITMQ_PORT_5672_TCP_ADDR} 5672 перед запуском сервера приложений, как описано в ссылке выше.

Другой вариант - использовать docker-wait. В вашем fig.yml,

rabbitmq:
  image: dockerfile/rabbitmq:latest
mongodb:
  image: mongo
rabbitmqready:
  image: aanand/wait
  links:
   - rabbitmq
app:
  build: .
  command: python /code/app/main.py
  links:
   - rabbitmqready
   - mongodb
  volumes:
   - .:/code

Подобные проблемы, с которыми я столкнулся, я решил, используя собственный скрипт, настроенный как CMD в моем Dockerfiles, Затем вы можете запустить любую команду проверки по вашему желанию (sleep какое-то время или ожидающий прослушивания службы, например). Я думаю, что нет стандартного способа сделать это, во всяком случае, я думаю, что лучшим способом было бы, чтобы при запуске приложения можно было просить, чтобы внешняя служба была запущена и работала, и подключиться к ним, но в большинстве случаев это невозможно. случаев.

Для тестирования нашего CI мы создали небольшую утилиту, которую можно использовать в контейнере Docker для ожидания готовности связанных служб. Он автоматически находит все связанные службы TCP по переменным среды и неоднократно и одновременно пытается установить TCP-соединения до тех пор, пока он не завершится успешно или не истечет время ожидания.

Мы также написали пост в блоге, описывающий, почему мы его создали и как мы его используем.

Другие вопросы по тегам