Docker で MySQL コンテナを作る方法

この記事は最終更新日から 1年以上 が経過しています。

ほとんどの Web アプリではデータを保存する際に、データベースを使用しています。 XAMPP では、データベースとして MySQL と互換性のある MariaDB が採用されていますが、 Docker を使用するのであればせっかくなので MySQL のコンテナを作成してみましょう。

Docker で MySQL コンテナを作る

コンテナのイメージは、下記の公式イメージを使用します。 イメージのバージョン(タグ)はいろいろありますが、 MySQL はバージョンが 8.0 以上だと、文字コードのデフォルトが utf8mb4 になるのでオススメです。 特にこだわりが無いなら最新版(latest)で良いと思います。

MySQL の root ユーザーのパスワードは、環境変数の MYSQL_ROOT_PASSWORD で指定することができます。

例:MySQL の root ユーザーのパスワードを "password" にする場合
docker-compose.yml
version: "3.8"
services:

  # MySQL コンテナ
  mysql:
    image: mysql:latest
    environment:
      MYSQL_ROOT_PASSWORD: password

ポートを公開する

MySQL のデフォルトのポート番号は 3306 番です。

ホスト側から MySQL Workbench などの管理ツールで接続したい場合は、コンテナ側のポート 3306 番へのマッピングを設定しましょう。 ホスト側のポート番号は、他で使用されていないものなら何番でも良いと思います。

なお、ホスト側から接続しないのであれば、この設定は必要はありません。 MySQL Workbench などの管理ツールをホストにインストールするのが面倒なのであれば、 後述の phpMyAdmin コンテナを作成して利用してみましょう。

例:ホスト側のポート 33060 番と、コンテナ側のポート 3306 番をマッピングする場合
docker-compose.yml
version: "3.8"
services:

  # MySQL コンテナ
  mysql:
    image: mysql:latest
    ports:
      - 33060:3306
    environment:
      MYSQL_ROOT_PASSWORD: password

タイムゾーンを変更する

デフォルトの状態だと MySQL のデータの日時が9時間ずれて表示されます(日本は UTC からの時差が +09:00 なので)。 日本の日時に合わせるためには、タイムゾーンを変更してあげる必要があります。

タイムゾーンを変更するにはいろいろな方法がありますが、環境変数の TZ を使用する方法が一番簡単だと思います。 これは正確に言えば MySQL ではなく、システム(つまり Linux)のタイムゾーンを変更しているのですが、 MySQL はデフォルトだとシステムのタイムゾーンを使用するようになっているので、MySQL にも反映されます。

例:タイムゾーンを "Asia/Tokyo" に変更する場合
docker-compose.yml
version: "3.8"
services:

  # MySQL コンテナ
  mysql:
    image: mysql:latest
    environment:
      TZ: Asia/Tokyo
      MYSQL_ROOT_PASSWORD: password

データが消えないようにする

コンテナが再作成された際などに、MySQL コンテナのデータが消えてしまっては困ると思いますので、データが消えないようにボリュームを設定しておきましょう。 ボリュームを設定しない場合は、勝手にハッシュ名のボリュームが作成されるようなのですが、わかりづらいのでちゃんと設定した方が良いと思います。

MySQL のデータは、デフォルトでは "/var/lib/mysql" ディレクトリ配下に保存されています。

例:名前付きボリュームを使用して、Docker 内部のボリューム "mysql-data" にデータを保存する場合
docker-compose.yml
version: "3.8"
services:

  # MySQL コンテナ
  mysql:
    image: mysql:latest
    volumes:
      - mysql-data:/var/lib/mysql
    environment:
      MYSQL_ROOT_PASSWORD: password

volumes:
  mysql-data:

バインドマウントを使用する

名前付きボリュームを使って Docker 内部にデータを保存しておくこともできますが、 たまに Docker でエラーが発生して、Docker が丸ごと初期化されたりすることがあるので、 バインドマウントを使用してホスト側にデータを保存しておいた方が安全かもしれません。 Windows で処理速度が気になる場合は、「Windows の Docker 環境を高速化する方法」を参考に、WSL 2 にバインドマウントする方法を検討してみてください。

例:バインドマウントを使用して、ホストの "./mysql-data" にデータを保存する場合
docker-compose.yml
version: "3.8"
services:

  # MySQL コンテナ
  mysql:
    image: mysql:latest
    volumes:
      - ./mysql-data:/var/lib/mysql
    environment:
      MYSQL_ROOT_PASSWORD: password

初期データを投入する

コンテナが作成された直後はデータが空っぽの状態です。 手作業でテーブルを CREATE したり、データを INSTERT していくのはとても面倒だと思います。 その場合、MySQL の初期化時に SQL ファイルを実行してくれる機能を使用すると良いでしょう。

MySQL コンテナの "/docker-entrypoint-initdb.d" ディレクトリに SQL ファイルを置いておくと、 その SQL ファイルを、MySQL の初期化時に実行してくれます。

MySQL の初期化処理は、コンテナを初めて起動する場合や、データを保存しているボリュームを削除して起動した場合など、 データが空っぽな状態の時にコンテナを起動すると実行されます。

なお、ファイルの拡張子は ".sql" もしくは ".sql.gz"(gzip 圧縮した SQL ファイル)である必要があるので注意してください。 もし、初期データを動的に作成して投入したい場合は、".sh" ファイルも使用できるようです。

複数のファイルがある場合は、ファイル名のアルファベット順に実行されます。

例:ホストの "./mysql-init" ディレクトリの中の SQL ファイルを、初期データとして投入する場合
docker-compose.yml
version: "3.8"
services:

  # MySQL コンテナ
  mysql:
    image: mysql:latest
    volumes:
      - ./mysql-init:/docker-entrypoint-initdb.d
    environment:
      MYSQL_ROOT_PASSWORD: password

文字化けを防ぐ

MySQL のバージョンが 8.0 以上だと、文字コードのデフォルトは utf8mb4 のはずなのですが、 初期データを投入する際は何故かそうなっていないようで、日本語などが文字化けしてしまいます。 文字化けを防ぐためには、投入する SQL の先頭で文字コードを指定しておくと良いでしょう。

SQLファイル
SET NAMES 'utf8mb4';

-- 以下 CREATE 文などの初期投入したいSQL

設定ファイルを使用する

MySQL の設定を変更したい場合は、MySQL の設定ファイルである my.cnf を使用すると良いでしょう。

例:文字コードを "utf8mb4"、照会順序を "utf8mb4_ja_0900_as_cs" に変更する場合
my.cnf
[mysqld]
character-set-server=utf8mb4
collation-server=utf8mb4_ja_0900_as_cs

MySQL の設定ファイルは複数の場所に置くことができますが、デフォルトだと "/etc/my.cnf" ファイルを見に行き、そこから "/etc/mysql/conf.d" ディレクトリの配下を見に行くようです。 なので、独自の設定ファイルを置きたい場合は、"/etc/mysql/conf.d" ディレクトリに置くと良いでしょう(例:/etc/mysql/conf.d/my.cnf)。

MySQL の設定ファイルを使用する一番簡単な方法は、バインドマウントを使用することですが、Windows でバインドマウントを使用するとパーミッションの問題が発生します。 MySQL は設定ファイルのパーミッションが誰でも書き込める状態になっていると、そのファイルを読み込んでくれません。 しかし、Windows でバインドマウントを使用すると、そのファイルのパーミッションが 777 になり、誰でも書き込める状態になってしまいます。 そのため、パーミッションをどうにかする必要があります。

解決策は下記の2つです。

解決策1:Windows 側のファイルを「読み取り専用」にしてからバインドマウントする

1つ目の方法は、Windows 側のファイルを「読み取り専用」にする方法です。 実はバインドマウントする際のパーミッションは、常に 777 になるわけではありません。 Windows 側のパーミッションが引き継がれています。 Windows 側で書き込み可能なファイルだから、それをバインドマウントしたら書き込み可能になるのが当然だよねという話らしいです。 言い換えると、Windows 側でそのファイルが書き込めない状態(読み取り専用)であれば、書き込み権限が外れて、パーミッションが 555 になります。

Windows 側でファイルを読み取り専用にするには、右クリックでプロパティを開いて属性欄の「読み取り専用」にチェックを付けるだけです。 簡単ではありますが、今後、Windows 側でそのファイルを編集する際は、いちいち「読み取り専用」のチェックを外したり付けたりする必要があるということなので注意してください。

readonly.png
例:ホストの "./my.cnf" を、コンテナの "/etc/mysql/conf.d/my.cnf" にバインドマウントする場合
docker-compose.yml
version: "3.8"
services:

  # MySQL コンテナ
  mysql:
    image: mysql:latest
    volumes:
      - ./my.cnf:/etc/mysql/conf.d/my.cnf
    environment:
      MYSQL_ROOT_PASSWORD: password

解決策2:Dockerfile を使用してビルドする

2つ目の方法は、Dockerfile を使用してコンテナイメージをビルドする方法です。 Dockerfile の中で、MySQL の設定ファイルをコンテナにコピーして、chmod コマンドでパーミッションを設定します。 MySQL の設定ファイルを変更するたびにビルドし直す必要がありますが、こちらの方がわかりやすくて楽かもしれません。

例:ホストの "./mysql-custom/my.cnf" を、コンテナの "/etc/mysql/conf.d/my.cnf" にコピーする場合
./mysql-custom/Dockerfile
FROM mysql:latest

COPY ./my.cnf /etc/mysql/conf.d/my.cnf
RUN chmod 644 /etc/mysql/conf.d/my.cnf
docker-compose.yml
version: "3.8"
services:

  # MySQL コンテナ
  mysql:
    build: ./mysql-custom
    environment:
      MYSQL_ROOT_PASSWORD: password

Docker で phpMyAdmin コンテナを作る

MySQL のコンテナが作成できたので、今度はその MySQL を管理するためのツールである phpMyAdmin のコンテナを作成してみましょう。 Docker なら簡単に作成することができます。

phpmyadmin.png

コンテナのイメージは、下記の公式イメージを使用します。 イメージのバージョン(タグ)はいろいろありますが、特にこだわりが無いなら最新版(latest)で良いと思います。

phpMyAdmin は Web サーバー上で動作しますので、コンテナ側のポート番号は 80 番です。 ホスト側から Web ブラウザ(Chrome など)で接続できるよう、コンテナ側のポート 80 番へのマッピングを設定しましょう。 ホスト側のポート番号は、他で使用されていないものなら何番でも良いと思います。

phpMyAdmin コンテナは、接続先の MySQL コンテナが起動していない状態だと意味が無いと思いますので、 depends_on の項目で、MySQL コンテナの後に起動するように設定しておくと良いでしょう。

MySQL コンテナへの接続情報は、下記の環境変数で設定できます。

項目 説明
PMA_HOST 接続先のホスト。 docker-compose.yml で定義しているサービス名(つまり、services 項目で指定しているキー)をホスト名として使用できます。
PMA_PORT 接続先のポート番号。 省略した場合のデフォルトは 3306 番です。
PMA_USER 接続するユーザーの名前。
PMA_PASSWORD 接続するユーザーのパスワード。
例:ホスト側のポート 33080 番と、コンテナ側のポート 80 番をマッピングする場合
docker-compose.yml
version: "3.8"
services:

  # MySQL コンテナ
  mysql:
    (省略)

  # phpMyAdmin コンテナ
  phpmyadmin:
    image: phpmyadmin:latest
    ports:
      - 33080:80
    depends_on:
      - mysql
    environment:
      - PMA_HOST=mysql
      - PMA_USER=root
      - PMA_PASSWORD=password

参考サイト

関連記事

データベースのソフトウェアとしては MySQL(MariaDB)が人気だと思いますが、PostgreSQL を使用しているサービスを見かけることもあるでしょう。Docker で PostgreSQL のコンテナを作成してみましょう。Docker で PostgreSQL コンテナを作るコンテナのイメージは、下記の公式イ ...
Web アプリではキャッシュやセッションを保存する際に、Redis がよく使われていたりします。Docker で Redis のコンテナを作成してみましょう。XAMPP では Redis をインストールするのはかなり大変でしたが、Docker なら簡単に作成することができます。Docker で Redis コンテナを作 ...
Docker で開発環境を作るのって結構大変です。構成を気軽に組み替えたりできるため自由度が高いですが、その分必要になる知識も多いですし、必要な作業も多いです。まずは、XAMPP でおなじみの Apache と PHP を組み合わせた Web サーバーを作るところから始めてみましょう。Docker で Apache + ...
Docker は、構成を気軽に組み替えたりできるので、とても便利ですよね。Windows で Docker を使って開発している方も多いと思うのですが、個人的にはどうしても気が乗らない理由がありました。それは処理速度です。遅い。遅すぎる。めちゃくちゃ遅い。つらい。耐えられない。。。ということで調査しました。いろいろと調 ...
最近では、アプリケーションの実行環境の構築に Docker を使うことも珍しくなくなりました。Docker は便利ではあるのかもしれませんが、難しく感じて敬遠されている人もいるのではないでしょうか。その感覚はおそらく間違っていません。実際、知れば知るほど奥が深い技術だと感じてしまいます。もはや沼というか深淵を覗いている ...

記事検索

最新記事

人気記事

RSSフィード

お知らせ

フィードバック

要望などあれば、お気軽にどーぞ。 不具合やバグを発見した場合も、連絡をいただけると助かります。

匿名でフィードバックする
匿名でフィードバックする

要望などあれば、お気軽にどーぞ。 不具合やバグを発見した場合も、連絡をいただけると助かります。

なお、このフォームから入力された内容について、管理者から返信はできませんので注意してください。 もし、管理者からの返信が必要であれば、X(Twitter) もしくは、お問い合わせより、お願いします。

  • フィードバックの送信が完了しました。