これまでWindowsにVagrantでLinux環境を用意し、VM上にDockerで開発環境を構築していたのだが、このVagrant on Docker環境をこの度Macへ移行することにした。

すると、DockerのMySQLコンテナが急に立ち上がらなくなってしまったのだが、今回はこの問題を解決した方法を紹介する。

exec: client: not found エラー

まず、以下のdocker-compose.ymlを用意し「docker-compose up -d」を実行したがコンテナが立ち上がらない。

services:
  db:
    container_name: db
    build: ./docker/mysql
    ports:
      - '3306:3306'
    volumes:
      - ./docker/mysql/data:/var/lib/mysql
    restart: always
    environment:
      MYSQL_ROOT_PASSWORD: password
      MYSQL_DATABASE: test_db
      MYSQL_USER: root
      MYSQL_PASSWORD: password
      TZ: 'Asia/Tokyo'

「docker-compose logs」でログを確認すると以下のエラーが吐かれていた。

/usr/local/bin/docker-entrypoint.sh: line 376: exec: client: not found

エラー解消法

このエラーについては、docker-compose.ymlに以下のコードを追記することで解消した。

... 省略
    environment:
      MYSQL_ROOT_PASSWORD: password
      MYSQL_DATABASE: test_db
      MYSQL_USER: root
      MYSQL_PASSWORD: password
      TZ: 'Asia/Tokyo'
    
    # 追記
    command: bash -c 'usermod -o -u 1000 mysql; groupmod -o -g 500 mysql; chown -R mysql:root /var/run/mysqld/; /entrypoint.sh mysqld --user=mysql --console'

どうやらパーミッションの関係でentrypoint.shがうまく実行されていなかったようだ。

データの永続化ができない問題

さらにエラーは続く。

先ほどの問題とは別の問題で、まだコンテナは立ち上がらない。

ログを見ると今度は以下のようなエラーが吐かれていた。

Could not open or create the system tablespace. If you tried to add new data files to the system tablespace, and it failed here, you should now edit innodb_data_file_path in my.cnf back to what it was, and remove the new ibdata files InnoDB created in this failed attempt. InnoDB only wrote those files full of zeros, but did not yet use them in any way. But be careful: do not remove old data files which contain your precious data!

どうやらデータの永続化のために記述しているdocker-compose.yml内の下記のコードが問題のようだ。

    volumes:
      - ./docker/mysql/data:/var/lib/mysql

この2行をコメントアウトするとコンテナは立ち上がるのだが、コンテナが消えるたびにデータまで削除されてしまうのは好ましくない。

そこで代替案を考えた。

ボリュームにデータを永続化することにした

Dockerにはデータボリュームという概念があり、コンテナとは独立した形でデータの保持や共有を行うことができる。

そのため、コンテナを削除したり、VMを再起動してもデータをボリュームとして残すことができるのだ。

ボリュームに永続化するため、docker-compose.ymlを下記のように変更した。

services:
  db:
    container_name: db
    build: ./docker/mysql
    ports:
      - '3306:3306'
    volumes:
      # ボリューム名を指定
      - mysql_data:/var/lib/mysql
    restart: always
    environment:
      MYSQL_ROOT_PASSWORD: password
      MYSQL_DATABASE: test_db
      MYSQL_USER: root
      MYSQL_PASSWORD: password
      TZ: 'Asia/Tokyo'
    command: bash -c 'usermod -o -u 1000 mysql; groupmod -o -g 500 mysql; chown -R mysql:root /var/run/mysqld/; /entrypoint.sh mysqld --user=mysql --console'

# 名前付きボリュームの定義
volumes:
  mysql_data:

これで「docker-compose up -d」を実行するとコンテナがうまく立ち上がってくれた。

データの永続化についてはこちらの記事にわかりやすくまとめられているので是非一読して欲しい。