web-dev-qa-db-ja.com

DockerComposeでMySqlデータベースを初期化する方法

シナリオ:私はSpringでmysql8データベースを使用するマイクロサービスを開発しました。このデータベースは初期化する必要があります(データベース、いくつかのテーブルとデータを作成します)。ホストマシンで、data.sqlおよびschema.sqlスクリプトを使用してデータベースを初期化しました。問題は、私が設定しなければならないことです:

spring.datasource.initialization-mode=always

最初の実行のために。これにより、データベースが希望どおりに初期化されます。今後の実行のために、このコマンドにコメントする必要があります。非常に醜い解決策ですが、より良い解決策を見つけることができず、今のところこれに対する応答はありません 質問 。テストは大丈夫だと思いましたが、間違いなく改善する必要があります。現在、dockercomposeによってdockerを使用してサービスを実行したいと考えています。

Expected:これは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では、私のマイクロサービスはデータベースの初期化よりも高速です。そのため、dbを呼び出そうとすると、エラーが発生します。 restart on failureのため、マイクロサービスが再び起動します。データベースの初期化が終了したため、これで機能します。

解決策:wwwを検索したところ、wait-for-it.shファイル内で解決される可能性のある既知の問題のようです。これは、DockerfileのCOPYに含まれている必要があります。だから私は専門家ではありませんが、次のいずれかの良い解決策を探しています:

  • 春からデータベースを初期化し、mysqlの準備ができるまでサービスを待機させます
  • または、最初の実行時にボリュームを介してコンテナ内からデータベースを初期化し、もちろんこの初期化の問題を解決します。

ここでのベストプラクティスがわからないので、これを構築する方法について助けていただければ幸いです。

3
medTech

最初の実行時にのみ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詳細 を使用して、data.sqlおよびschema.sqlファイルを./docker-entrypoint-initdb.dディレクトリの下に配置する必要があります。

このフォルダ内のSQLファイルは、DBのデータディレクトリが空の場合(dbサービスの最初の実行)にのみロードされます。 (つまり)あなたの場合、./mysql-dataフォルダは空である必要があります

2番目の問題の場合:

wait-for-it.shを使用する代わりに、healthcheckservice_healthyを使用できます。ここで、mysqldbが指定された間隔でusermanagement-serviceを正常に実行すると、["CMD", "mysqladmin" ,"ping", "-h", "localhost"]が開始されます。 healthcheckとdepends_onの詳細については、 ここ を参照してください。

ここ からtestコマンドを取得しました。

8
Thilak