📑

Dockerでmysqlがrestartingの状態になり立ち上がらない

2023/04/24に公開

表題通りですが、Dockerを利用してMySQLサービスを立ち上げようとして、restartingの状態のループになってしまって立ち上がらなかったので、その解決方法を調べました。

環境

マシン

macOS Big Sur
プロセッサ Intel

ディレクトリ

.
├── docker
│   ├── db
│   │   ├── init
│   │   │   └── init.sql
│   │   └── mydata
│   ├── web
│   │   ├── conf
│   │   │   └── my.cnf
│   │   ├── log
│   │   ├── Dockerfile
│   │   └── php.ini
│   ├── .env
│   └── docker-compose.yml
└── www
    └── myroot

my.cnf

[mysqld]
character_set_server = utf8mb4
collation_server = utf8mb4_general_ci

[mysql]
default-character-set = utf8mb4

[client]
default-character-set = utf8mb4

Dockerfile

FROM php:apache

COPY ./php.ini /usr/local/etc/php/php.ini

RUN apt-get update \
&& apt-get install -y libonig-dev libzip-dev unzip locales\
# コンテナ内で日本語が打てるようにlocalを変更
&& sed -i -E 's/# (ja_JP.UTF-8)/\1/' /etc/locale.gen \
&& locale-gen \
&& update-locale LANG=ja_JP.UTF-8 \
# 不要ファイルを削除
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/* \
# phpのモジュールとxdebug
&& docker-php-ext-install pdo_mysql mbstring zip bcmath\
&& pecl install xdebug\
&& docker-php-ext-enable xdebug

ENV LC_ALL ja_JP.UTF-8

## ドキュメントルートを変更する
RUN sed -ri -e 's!/var/www/html!${DOCUMENT_ROOT}!g' /etc/apache2/sites-available/*.conf

RUN echo 'ServerName localhost' | tee /etc/apache2/conf-available/fqdn.conf
RUN a2enconf fqdn

.env

WEB_PORT=81
DOCUMENT_ROOT_DIR=myroot

DB_DATABASE=mydatabase
DB_ROOT_HOST=%
DB_ROOT_USER=root
DB_ROOT_PASSWORD=myroot
DB_HOST=mydb
DB_PORT=3307
TZ=Asia/Tokyo

PHPMYADMIN_PORT=8081

docker-compose.yml

version: "3.0"
services:
  web:
    container_name: web
    image: php
    build:
      context: ./web
      dockerfile: Dockerfile
    ports:
      - "${WEB_PORT}:80"
    environment:
      DOCUMENT_ROOT: "/var/www/html/${DOCUMENT_ROOT_DIR}/"
    volumes:
      - ../www:/var/www/html/
      - ./web/log:/var/log
    depends_on:
      - db
    networks:
      - mynetwork

  db:
    container_name: db
    image: mysql:8.0
    command: --default-authentication-plugin=mysql_native_password
    restart: always
    ports:
      - "${DB_PORT}:3306"
    environment:
      MYSQL_DATABASE: "${DB_DATABASE}"
      MYSQL_ROOT_HOST: "${DB_ROOT_HOST}"
      MYSQL_ROOT_USER: "${DB_ROOT_USER}"
      MYSQL_ROOT_PASSWORD: "${DB_ROOT_PASSWORD}"
      MYSQL_HOST: "${DB_HOST}"
      TZ: "${TZ}"
    volumes:
      # データ永続化
      - ./db/mydata:/var/lib/mysql
      # 初期化
      - ./db/init:/docker-entrypoint-initdb.d
      # 設定
      - ./web/conf/my.cnf:/etc/my.cnf
    networks:
      - mynetwork

  phpmyadmin:
    container_name: phpmyadmin
    image: phpmyadmin/phpmyadmin
    ports:
      - "${PHPMYADMIN_PORT}:80"
    environment:
      PMA_HOST: db
    depends_on:
      - db
    links:
      - db
    networks:
      - mynetwork

networks:
  mynetwork:
    driver: bridge

エラーログのメッセージ

Failed to find valid data directory.
Data Dictionary initialization failed.
Aborting.

行ったこと

  1. コンテナのストップ&削除
docker-compose down
  1. 使用していないイメージとボリュームを削除
docker system prune --all

※コマンドライン上で警告が出ますが、他の停止中のコンテナなども削除されるので注意してください。

  1. mydataディレクトリを削除
cd /path_to_this_root_dir/docker/db
rm -rf mydata
  1. 起動
docker-compose up -d

不明点...

mysqlのイメージの説明には以下とあります。

注意事項

データの保存場所
重要な注意事項: Docker コンテナーで実行されるアプリケーションで使用されるデータを保存するには、いくつかの方法があります。画像のユーザーは、mysql次のような利用可能なオプションに慣れることをお勧めします。

独自の内部ボリューム管理を使用してホスト システム上のディスクにデータベース ファイルを書き込むことにより、 Docker がデータベース データのストレージを管理できるようにします。これはデフォルトで、簡単で、ユーザーにとってかなり透過的です。欠点は、ホスト システム上で直接実行されるツールやアプリケーション、つまりコンテナの外部で実行されるツールやアプリケーションの場合、ファイルを見つけるのが難しい場合があることです。
ホスト システム (コンテナーの外部) にデータ ディレクトリを作成し、これをコンテナー内から見えるディレクトリにマウントします。これにより、データベース ファイルがホスト システム上の既知の場所に配置され、ホスト システム上のツールやアプリケーションがファイルに簡単にアクセスできるようになります。欠点は、ユーザーがディレクトリが存在することを確認する必要があること、およびホスト システム上のディレクトリのアクセス許可やその他のセキュリティ メカニズムが正しく設定されていることなどです。

Docker のドキュメントは、さまざまなストレージ オプションとバリエーションを理解するための出発点として最適です。また、この分野について議論し、アドバイスを提供するブログやフォーラムへの投稿が複数あります。ここでは、上記の後者のオプションの基本的な手順を簡単に示します。

ホスト システムの適切なボリュームにデータ ディレクトリを作成します/my/own/datadir。

次のようにコンテナを起動しますmysql。

$ docker run --name some-mysql -v /my/own/datadir:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=my-secret-pw -d mysql:tag
-v /my/own/datadir:/var/lib/mysqlコマンドの一部は、基礎となるホスト システムからディレクトリをコンテナ内としてマウントします。/my/own/datadirデフォルト/var/lib/mysqlでは、MySQL がそのデータ ファイルを書き込みます。

https://hub.docker.com/_/mysql

データを保存しておくために /my/own/datadir ディレクトリを作成し、コンテナの /var/lib/mysql ディレクトリに紐づけていると思うのですが、僕の場合は上記手順の3を行わないと起動できなかったです。
なんでなんだろう...解決できておりません。

参考

https://hub.docker.com/_/mysql
https://qiita.com/touhu70/items/eb773351e4b707e6dae5
https://qiita.com/gobtktk/items/ea76422acc614830583b
https://qiita.com/sun33/items/398479ba586e39dcee13

Discussion