Docker compose полностью запустил mysql db перед запуском фляги - PullRequest
0 голосов
/ 10 ноября 2018

Я только что начал докеризацию своего приложения. Я построил свои Dockerfile и docker-compose.yml, и все, кажется, работает нормально, кроме одной вещи. Иногда приложение фляги запускается слишком быстро и выдает ошибку «отказано в соединении» (потому что база данных MySQL работает не полностью). Я использую healthcheck, чтобы проверить, работает ли БД, но это, кажется, не надежно (я даже проверяю, вижу ли я show databases, но mysql, очевидно, инициализирует больше вещей после прохождения проверки здоровья? Не уверен, что проверка здоровья для потом). В моем выводе я вижу, что база данных создается сначала, но она все еще инициализируется при запуске приложения фляги. В идеале, когда я запускаю docker-compose up, я хочу сначала увидеть эту строку,

db_1_eae741771281 | 2018-11-10T00:50:21.473098Z 0 [Note] mysqld: ready for connections.

и затем запустите мою точку входа в колбу. В настоящее время этого не происходит.

Есть ли более надежный способ убедиться, что MySQL полностью запущен перед запуском моего start.sh?

Dockerfile:

FROM python:3.5-alpine

RUN apk update && apk upgrade

RUN apk add --no-cache curl python build-base openldap-dev python2-dev python3-dev pkgconfig python-dev libffi-dev musl-dev make gcc

RUN pip install --upgrade pip

RUN adduser -D user

WORKDIR /home/user

COPY requirements.txt requirements.txt
RUN python -m venv venv
RUN venv/bin/pip install -r requirements.txt

COPY app app
COPY start.sh ./
RUN chmod +x start.sh

RUN chown -R user:user ./
USER user

EXPOSE 5000
ENTRYPOINT ["./start.sh"]

докер-compose.yml:

version: "2.1"
services:
  db:
    image: mysql:5.7
    ports:
      - "32000:3306"
    environment:
      - MYSQL_DATABASE=mydb
      - MYSQL_USER=user
      - MYSQL_PASSWORD=user123
      - MYSQL_ROOT_PASSWORD=user123
    volumes:
      - ./db:/docker-entrypoint-initdb.d/:ro
    healthcheck:
            test: "mysql --user=user --password=user123 --execute \"SHOW DATABASES;\""
            timeout: 20s
            retries: 20

  app:
    build: ./
    ports:
      - "5000:5000"
    depends_on:
      db:
        condition: service_healthy

start.sh

#!/bin/sh

source venv/bin/activate
# Start Gunicorn processes
echo Starting Gunicorn.

exec gunicorn -b 0.0.0.0:5000 wsgi --chdir my_app --timeout 9999 --workers 3 --access-logfile - --error-logfile - --capture-output --log-level debug

Ответы [ 3 ]

0 голосов
/ 10 ноября 2018

Хотя проверка работоспособности проще, она полностью зависит от того, насколько надежна проверка.

Другой подход заключается в использовании таких проектов, как wait-for-it или wait-for, в контейнере вашего приложения.
Поскольку вы получаете отказ в соединении, эти сценарии могут вернуться только после того, как соединение станет возможным, и ваше приложение может запуститься только после.

Кроме того, в случае, если это тоже не работает, у вас может быть отдельный скрипт (python в вашем случае) для проверки, пока БД не готова, и вы можете вызвать этот скрипт в вашем start.sh перед запуском приложения фляги.

0 голосов
/ 11 ноября 2018

ОК. У меня также были проблемы с health_check ...

Возможно, не самое оптимальное, но наиболее надежное решение - использовать клиент MySQL (mysqladmin) для проверки связи с сервером MySQL перед запуском приложения.

1 - Создайте сценарий wait.sh (db здесь ваше имя службы MySQL):

#!/bin/sh

# Wait until MySQL is ready
while ! mysqladmin ping -h"db" -P"3306" --silent; do
    echo "Waiting for MySQL to be up..."
    sleep 1
done

2 - Получить клиент MySQL из вашего app Dockerfile:

# install mysql client, will be used to ping mysql
apt-get -y install mysql-client

3 - В своем файле docker-compose.yml просто добавьте сценарии в свой контейнер (я использовал тома, но вы можете продолжать использовать COPY) и выполните wait.sh до start.sh:

app:
    build: ./
    ports:
      - "5000:5000"
    depends_on:
      db:
    command: bash -c "/usr/local/bin/wait.sh && /usr/local/bin/start.sh"
    volumes:
      - ./start.sh:/usr/local/bin/start.sh
      - ./wait.sh:/usr/local/bin/wait.sh

Это должно сработать.

Если вы действительно не хотите загружать клиент MySQL, попробуйте это (снова db здесь ваше имя службы MySQL). Он работал в большинстве моих проектов, но не во всех (может зависеть от дистрибутива?):

#!/bin/sh

# Wait until MySQL is ready
while ! exec 6<>/dev/tcp/db/3306; do
    echo "Trying to connect to MySQL at 3306..."
    sleep 5
done

PS: избегайте называть ваши сервисы "app" или "db", у вас могут возникнуть проблемы позже, если у вас есть другие контейнеры с такими же именами сервисов (даже в разных сетях).

0 голосов
/ 10 ноября 2018

Это распространенная проблема с несколькими контейнерами. Трудно контролировать скорость запуска различных контейнеров. В таких случаях вам может помочь решение для управления контейнером, например Kubernetes. В Kubernetes есть концепция init-контейнеров, которые завершаются до того, как ваш зависимый контейнер может запуститься. Вы можете найти образец контейнера init здесь

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

Это видео с YouTube может быть полезным и для вас. https://www.youtube.com/watch?v=n2FPsunhuFc

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...