如何在 Docker Compose 中初始化 MySql 数据库

How to init MySql Database in Docker Compose

场景: 我在 Spring 中开发了一个微服务,它使用 mysql 8 数据库。 这个数据库必须被初始化(创建一个数据库,一些表和数据)。 在我的主机上,我使用 data.sql 和 schema.sql 脚本初始化了数据库。 问题是,我必须设置:

spring.datasource.initialization-mode=always

第一次执行。这会按照我想要的方式初始化我的数据库。 为了将来 运行s 我必须评论这个命令。非常难看的解决方案,但我找不到更好的解决方案,而且我现在没有收到对此 question 的回复。 我认为测试它没问题,但我绝对必须改进它。 目前我想 运行 我的服务 docker 通过 docker 撰写。

预期: 这是 docker-compose 文件。相当简单。我对 docker 的世界是全新的,所以我想一步一步来。

version: '3' 
services:usermanagement-service:
build:
  ./UserManagementService
restart:
  on-failure
ports:
  - "7778:7778"
links:
  - mysqldb
depends_on:
  - mysqldb   mysqldb:
build:
  ./CustomMySql
volumes:
  - ./mysql-data:/var/lib/mysql
restart:
  on-failure
environment:
  MYSQL_ROOT_PASSWORD: root
  MYSQL_DATABASE: userdb
  MYSQL_USER: testuser
  MYSQL_PASSWORD: testuser
expose:
  - "3600"

我原以为我的数据库会用用户初始化,而在第一个 运行 中,我的微服务会用数据初始化数据库。 所以在下一次开始撰写之前,我必须评论命令并重建图像。 (我知道,丑)

问题: 所以除了这个丑陋的解决方案之外,我 运行 进入了 运行 时间问题。 在 docker-compose up 上,我的微服务比数据库的初始化更快。因此,它会尝试调用导致 en 错误的数据库。 由于 restart on failure 微服务再次出现。 现在它可以工作了,因为数据库的初始化已经完成。

解法: 我搜索了 www,因为它似乎是一个已知问题,可以在 wait-for-it.sh 文件中解决。这必须包含在 Dockerfile 中的 COPY 中。 所以我不是专家,但我正在寻找一个好的解决方案:

我不知道这里的最佳实践是什么,我将非常感谢您提供一些帮助来构建它。

仅在第一个 运行 加载您的 sql 文件:

您可以使用下面的合成文件

version: '2.1'
services:

  usermanagement-service:
    build: ./UserManagementService
    restart: on-failure
    ports:
      - "7778:7778"
    depends_on:
      mysqldb:
        condition: service_healthy

  mysqldb:
    image: mysql
    volumes:
      - ./mysql-data:/var/lib/mysql
      - ./mysql-init-files:/docker-entrypoint-initdb.d
    restart: always
    environment:
      MYSQL_ROOT_PASSWORD: root
      MYSQL_DATABASE: userdb
      MYSQL_USER: testuser
      MYSQL_PASSWORD: testuser
    ports:
      - "3600:3306"
    healthcheck:
      test: ["CMD", "mysqladmin" ,"ping", "-h", "localhost"]
      timeout: 20s
      retries: 10

您必须使用 Volumes for more infodata.sqlschema.sql 文件放在 ./docker-entrypoint-initdb.d 目录下。

SQL 仅当 DB 的数据目录为空(第一个 运行 数据库服务) 时才会加载此文件夹中的文件。 (即)在你的情况下 ./mysql-data 文件夹应该是空的

对于你的第二个问题:

您可以使用 healthcheckservice_healthy 而不是使用 wait-for-it.sh。这里usermanagement-service将在mysqldb在指定的时间间隔内成功执行["CMD", "mysqladmin" ,"ping", "-h", "localhost"]后启动。有关健康检查和 depends_on 的更多详细信息,请参阅 here

here 获得了 test 命令。