Хотите больше хорошего контента? Зарегистрируйтесь на мою рассылку, посетите: alec.coffee/signup
Наличие отличного местного опыта развития имеет решающее значение для счастливых инженеров. Разработчики рады прийти в кодовую базу и начать взломать проблемы, в отличие от ужасных ноутбуков. Поскольку услуги становятся все более и более разделяющимися на отдельные «микросервисные услуги», возникают новые проблемы. Когда я оглядываюсь на мою короткую карьеру, одна проблема, которая вызвала мне большую боль, — это миграции SQL и как они должны работать в Docker Compose. В идеале они должны работать до загрузки ваших веб-приложений, поэтому у них есть доступ к хорошо структурированной базе данных. Ваша стратегия, чтобы это произошло, может отличаться для каждой среды, в этом посте я покрою ваш локальный опыт, который легко простирается в CI, и я также коснусь, как это сделать в производстве.
Немного фона
Я столкнулся с этой проблемой, когда мы начали принять Федерация Аполлона в наш стек. Один шлюз обслуживает перед нашими другими услугами GraphQL (у которых есть собственные базы данных). Этот шлюз — это то, что клиентские приложения («веб-браузер» на диаграмме) запросы, чтобы получить его данные. Для клиентов начать использование API Gateway, каждая зависимая служба должна быть и здоровой.
Моя цель состоит в том, чтобы начать весь набор услуг детерминированным образом, у каждого сервиса ждать до тех пор, пока его не будет работать и здоровый сервис. Я сосредоточусь на базе данных и миграции в этом посте, но концепции здесь распространяются на любое обслуживание, имеющее зависимости от другой услуги.
Типичный Docker Compose файл, который запускает услугу продуктов с ее миграциями, будет выглядеть так:
version: "3.7" postgres: image: yourorg/postgres command: postgres -c 'max_connections=1024' expose: - "5432" environment: POSTGRES_USER: ${DATABASE_USERNAME} POSTGRES_PASSWORD: ${DATABASE_PASSWORD} volumes: - ${YOUR_ORG_INSTALL_PATH}/volumes/services/postgres-data:/var/lib/postgresql/data:delegated products-run-migrations: build: context: ./apps/products/migrations/. image: yourorg/products-run-migrations:${IMAGE_TAG:-latest} env_file: - ./apps/products/products.env depends_on: - postgres products: build: context: ./apps/products/. image: yourorg/products:${IMAGE_TAG:-latest} env_file: - ./apps/products/products.env depends_on: - postgres - products-run-migrations
Несколько вопросов с этой установкой, ориентируясь на Defends_on
:
-
Продукты-пробежные миграции
Сценарий будет работать прямо когдаPostgres
Начинает бегать, а не когда он здоров и готов принять соединения. Есть 99% шанс, чтоPostgres
Контейнер не будет здоров, когда миграции начинают бегать, заставляя их потерпеть неудачу. - Аналогичная ситуация с
Продукты
Сервис, он будет работать прямо когдаПродукты-пробежные миграции
начинает бегать. Если вы запрашиваетеПродукты
Сервис, когда это здорово, есть хороший шанс, что миграции еще не завершены.
Что мы хотим
В настоящее время это не то, что мы хотим, в идеале разработчики должны иметь возможность начать службу продукции и когда она будет здоровой, знает, что миграции успешно работают, и они могут запрашивать его API.
Это требовало меня сделать некоторые исследования.
Я обнаружил, что есть Условия
аргумент для зависит от
Я мог бы использовать для достижения реализации, которую мы хотели. Но следующая вещь, которую я узнал, — это то, где все прошло хайвире.
Нам нужно было понизить нашу версию Docker-Compose.
Оказывается, Docker Compose 3.x версии предназначены для использования в средах Docker Sharm и Kubernetes, где услуги не строго зависят друг от друга. Это способствует большей неисправной среде, где обслуживания работают независимо.
Что я видел, как люди предлагают должен был переключиться на Docker Compose 2.4 и использовать порт ожидания порта, как ждать-за-это Отказ
Наш новый Docker Compose 2.4 файл:
version: '2.4' postgres: image: yourorg/postgres command: postgres -c 'max_connections=1024' expose: - '5432' environment: POSTGRES_USER: ${DATABASE_USERNAME} POSTGRES_PASSWORD: ${DATABASE_PASSWORD} volumes: - ${YOUR_ORG_INSTALL_PATH}/volumes/services/postgres-data:/var/lib/postgresql/data:delegated healthcheck: test: ['CMD-SHELL', 'pg_isready -U root'] interval: 60s products-run-migrations: build: context: ./apps/products/migrations/. image: yourorg/products-run-migrations:${IMAGE_TAG:-latest} entrypoint: - /bin/bash - -c - 'wait-for-it $$DATABASE_HOSTNAME:5432 -s -t 60 -- npm run db-migrate:products restart: on-failure:5 env_file: - ./apps/products/products.env depends_on: postgres: condition: service_healthy products: build: context: ./apps/products/. image: yourorg/products:${IMAGE_TAG:-latest} env_file: - ./apps/products/products.env restart: on-failure:5 depends_on: postgres: condition: service_healthy products-run-migrations: condition: service_started
Несколько новых дополнений:
- Добавил
HealthCheck
кPostgres
контейнер. Это сделало его так, как миграционные сценарии, такие какПродукты-пробежные миграции
Можно запустить только тогда, когда база данных готова принять соединения. - Мы добавили
Выходная точка
вместе сСостояние
arg toDefends_on
на нашими миграционными изображениями. Это убедилось, что запущена не только база данных, но которую порт возвращает 200 ответов. - Добавлено
Состояние
Args для обоихDefends_on
вПродукты
Определение обслуживания.
Это не идеально, но работает намного лучше, чем раньше. Вопрос по-прежнему остается в том, что приложение не ждет миграции, которые будут полностью завершены перед загрузкой. Если они бегут относительно быстро, местные разработчики могут не столкнуться с проблемами. В CI у нас есть полный контроль над окружающей средой, поэтому мы можем добавить дополнительную команду для юбки по этой проблеме.
# .circleci/config.yml test-products: executor: node-docker steps: - test-project: project-name: products pre-test-command: docker-compose run -T products-run-migrations tests: - run-project-test: project-name: products
Проблемы, которые все еще остаются
На что я не трогал, это то, какая наша производственная среда выглядит в плане Docker Compose. Мы решили сохранить две версии нашего составных файлов Docker, один в 2,4 и один в 3.7. Это потому, что мы хотим легко принять Кубернаны в будущем. Вы можете придерживаться одного или другого, но для отличного местного опыта развития мы решили всегда иметь 2,4 файла.
Оригинал: «https://dev.to/aleccool213/running-sql-migrations-before-booting-docker-compose-services-3d3d»