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

med*_*ech 7 mysql init docker spring-boot docker-compose

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

spring.datasource.initialization-mode=always
Run Code Online (Sandbox Code Playgroud)

对于第一次执行。这以我想要的方式初始化我的数据库。对于未来的运行,我必须评论这个命令。非常难看的解决方案,但我找不到更好的解决方案,而且我现在对这个问题没有任何回应。我认为测试它是可以的,但我肯定必须改进它。目前我想通过 docker compose 使用 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"
Run Code Online (Sandbox Code Playgroud)

我期待,我的数据库被一个用户初始化,并且在第一次运行时我的微服务用数据初始化数据库。因此,在下次开始撰写之前,我必须注释该命令并重建映像。(我知道,丑)

问题: 所以除了这个丑陋的解决方案之外,我还遇到了运行时问题。在docker-compose up我的微服务上比数据库的 init 快。所以它试图调用导致错误的数据库。因为restart on failure微服务又出现了。现在它可以工作了,因为 db 的 init 已经完成。

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

  • 从 spring 中初始化数据库并使我的服务等待 mysql 准备就绪
  • 或者在第一次运行时通过一个卷从我的容器中初始化数据库,当然可以解决这个初始化问题。

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

Thi*_*lak 17

仅在第一次运行时加载 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
Run Code Online (Sandbox Code Playgroud)

您必须将您的data.sqlschema.sql文件放在./docker-entrypoint-initdb.dusing 目录下以Volumes 获取更多信息

仅当数据库的数据目录为空(数据库服务的第一次运行)时,才会加载此文件夹中的 SQL 文件。(即)在您的案例./mysql-data文件夹中应该是空的

对于您的第二个问题:

wait-for-it.sh您可以使用healthcheckand代替 using service_healthy。这里usermanagement-service将在指定的时间间隔内mysqldb成功执行 ["CMD", "mysqladmin" ,"ping", "-h", "localhost"]后启动。有关 healthcheck 和 depends_on 的更多详细信息,请参阅此处

test这里得到命令。