如何在启动服务之前等待mysql docker-entrypoint-initdb

问题描述 投票:0回答:3

我有一个使用 mysql、express 和 React 的 dockerized 应用程序。

在启动 Express 应用程序之前,我需要首先使用

docker-entrypoint-initdb.d
初始化 mysql。但是,当 mysql 服务器启动时,它不会立即执行启动 .sql 脚本,并且
my_database_name
最初是空的。

在这段时间内,我的 Express 应用程序启动并尝试查询空数据库。稍后,初始化脚本按预期工作并填充

my_database_name
,但那时已经太晚了,因为我的 Express 应用程序已经启动了。

我已经尝试了

depends_on/condition
,如下所示,但
Version 3 no longer supports the condition form of depends_on
文档中所述。

version: '3.8'

services:
  api-server:
    build:
      context: ./server
      dockerfile: ./Dockerfile
    image: myapp_server
    env_file: ./server/.env
    stdin_open: true
    tty: true
    depends_on:
      mysqldb:
        condition: service_healthy
    ports:
      - 9000:9000
    networks:
      - mysern-app
    container_name: my_express_app

  mysqldb:
    image: mysql
    restart: always
    environment:
      MYSQL_ROOT_PASSWORD: root
      MYSQL_DATABASE: my_database_name
    volumes:
      - mysql-data:/data/db
      - ./db/backup/:/mysql/backup
      - ./db/init:/docker-entrypoint-initdb.d
    healthcheck:
      test: 'not sure what to write in here as well'
      interval: 1s
      retries: 120
    networks:
      - mysern-app
    ports:
      - 3306:3306
    container_name: my_mysql_app
networks:
  mysern-app:
    driver: bridge
volumes:
  mysql-data:
    driver: local

我最终想做这个序列:

启动 mysqldb > 从脚本填充表 > 启动express应用程序

docker docker-compose
3个回答
2
投票

您可以做几件事:

  1. restart: always
    添加到您的
    api-server
    。如果它因 MySQL 尚不可用而崩溃 - 它将重新启动,直到 MySQL 可用。我假设如果 MySQL 不可用,你的
    api-server
    将会崩溃。
  2. 如果它不会崩溃,请为你的服务实现health-check,这样如果Mysql不可用,它就无法使用。

docker-compose 是您的编排器,它可以帮助您并处理故障。在现实世界中,你的 MySQL 也可能有一秒钟不可用,你必须知道如何处理它。


1
投票

这对我有用:

version: "3.7"
services:
  acme-db:
    image: mysql:5.7
    command: mysqld --sql_mode="" --max_connections=1100 --general-log=1 --general-log-file=/tmp/mysql-general-log.log
    container_name: eventhos-db
    ports:
      - "3306:3306"
    volumes:
      - ./database:/docker-entrypoint-initdb.d
    environment:
      MYSQL_ROOT_PASSWORD: changeme
      MYSQL_PASSWORD: changeme
      MYSQL_USER: "usr_acme"
      MYSQL_DATABASE: "acme"
      TZ: America/Lima
    deploy:
      resources:
        limits:
          memory: 512M
    healthcheck:
      test: 'cat /tmp/mysql-general-log.log | grep "root@localhost on  using Socket"'
      interval: 10s
      retries: 120

说明

没有一种本地方法可以询问 mysql dump 是否已完全导入。

研究时,我发现了一个名为 mysql General_log 的内部 mysql 日志文件,并在 dockerized mysql 中查看其内容,我发现了一种模式:

如果一切正常,最后会出现以下行:“root@localhost on using Socket”一次

因此,如果我们在 docker-compose 中使用 command: 启用此日志:

command: mysqld --sql_mode="" --max_connections=1100 --general-log=1 --general-log-file=/tmp/mysql-general-log.log

健康检查只是搜索这些行

cat /tmp/mysql-general-log.log | grep "root@localhost on  using Socket"

注意:健康检查间隔小于10秒,不起作用!


0
投票
  1. 添加健康检查来测试您的应用程序的一些有意义的内容。而不是“选择 1;”最好为您的应用程序/开发环境编写一个自定义查询。即检查用户表是否存在,以便登录功能正常工作。
  2. 根据步骤一中定义的查询的性能调整间隔、超时和重试。
mysql:   
  build: ...
  ...
  healthcheck:
    test: mysql ${DB_NAME} --user=${DB_USER} --password='${DB_PWD}' --silent --execute "SELECT 1;"
    interval: 30s
    timeout: 10s
    retries: 5
  1. 将数据库变量定义到 docker-compose.yml 文件旁边的“.env”文件中。

示例 .env 文件

DB_HOST=...
DB_NAME=...
DB_USER=...
DB_PWD=...
© www.soinside.com 2019 - 2024. All rights reserved.