8
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Docker化のMySQLサーバーが正常に起動してるかを簡単に確認できると思う僕が甘かった件

Last updated at Posted at 2023-09-04

TL;DR

Docker Composeとかでコンテナー化のMySQLサーバーに正常に接続できたらアプリを起動するという依存関係を実現したいのなら、下記のようなhealthcheckdepends_on構文を使ってください。

app:
  container_name: app
  build:
    context: .
    dockerfile: Dockerfile
  ports:
    - '8080:8080'
  depends_on:
    mysql:
      condition: service_healthy
mysql:
  container_name: mysql
  image: mysql:8.0
  environment:
    MYSQL_ROOT_PASSWORD: password
  healthcheck:
    test: "mysqladmin ping -h 127.0.0.1 -u root -p$$MYSQL_ROOT_PASSWORD"
    timeout: 5s
    interval: 5s
    retries: 10

一時的に立ち上げられたMySQLサーバーによる惨事

いろんな記事は上記のtest文が["CMD", "mysqladmin" ,"ping", "-h", "localhost"]と書いてあるが、それは実に大問題になる。

MySQLコンテナーは起動する時にまず一時的なMySQLサービスを立ち上げて初期化プロセスをするので、もしこのタイミングに上記のテストコマンドが実行されたら、ヘルスチェックが成功になってしまう。でも本当なサービスがまだ起動してないので、MySQLに依存するコンテナーの起動は当然に失敗になるわけ。

一時的なMySQLサーバーと正式なMySQLサーバーにどんな違いがあるか

一時的なサーバーはローカルのsocket connectionしかサポートしていない。
正式的なサーバーはnetwork interfaceもlistenしている。

MySQLのクライエントは指定されるホストがlocalhostであれば自動的にsocket connectionで接続するので、mysqladmin ping -h localhostだと、成功しても一時的なサーバーに接続した可能性もあるので、ヘルスチェックの標準として頼れない。

ドルが足りない環境変数

もしMySQLコンテナーにRootパスワードを指定したら、mysqladmin pingにはパスワードも必要になる。

test: "mysqladmin ping -h 127.0.0.1 -u root -p$MYSQL_ROOT_PASSWORD"

でいいじゃない?

もし単純にシェルで実行すれば、確かにこれで問題なし。でもdocker composeのYAMLであれば、$MYSQL_ROOT_PASSWORD$$MYSQL_ROOT_PASSWORDを変更しなければならない。

test: "mysqladmin ping -h 127.0.0.1 -u root -p$$MYSQL_ROOT_PASSWORD"

原因はこの前に記事で書いたことがある

テスト文のフォーマット

ちなみに、ここには["CMD", "command", "argument"]のようなフォーマットじゃだめそう。なぜなら、CMDはEXECでコマンドを実行するので、コマンド内の環境変数は普通の文字列として扱ってしまう。["CMD", "mysqladmin" ,"ping", "-h", "127.0.0.1", "-p$$MYSQL_ROOT_PASSWORD"]mysqladmin ping -h 127.0.0.1 -p'$MYSQL_ROOT_PASSWORD'になる。つまりここで指定されたRootパスワードが$MYSQL_ROOT_PASSWORDそのままであるわけ。

[]のようなリストフォーマットにこだわれば、CMD-SHELLを使ってください。

test: ["CMD-SHELL", "mysqladmin ping -h 127.0.0.1 -u root -p$$MYSQL_ROOT_PASSWORD"]

ドキュメントによると、

test must be either a string or a list. If it's a list, the first item must be either NONE, CMD or CMD-SHELL. If it's a string, it's equivalent to specifying CMD-SHELL followed by that string.

8
2
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?