Docker で MySQL コンテナを作る方法
ほとんどの Web アプリではデータを保存する際に、データベースを使用しています。 XAMPP では、データベースとして MySQL と互換性のある MariaDB が採用されていますが、 Docker を使用するのであればせっかくなので MySQL のコンテナを作成してみましょう。
Docker で MySQL コンテナを作る
コンテナのイメージは、下記の公式イメージを使用します。
イメージのバージョン(タグ)はいろいろありますが、
MySQL はバージョンが 8.0 以上だと、文字コードのデフォルトが utf8mb4
になるのでオススメです。
特にこだわりが無いなら最新版(latest
)で良いと思います。
MySQL の root ユーザーのパスワードは、環境変数の MYSQL_ROOT_PASSWORD
で指定することができます。
version: "3.8" services: # MySQL コンテナ mysql: image: mysql:latest environment: MYSQL_ROOT_PASSWORD: password
ポートを公開する
MySQL のデフォルトのポート番号は 3306 番です。
ホスト側から MySQL Workbench などの管理ツールで接続したい場合は、コンテナ側のポート 3306 番へのマッピングを設定しましょう。 ホスト側のポート番号は、他で使用されていないものなら何番でも良いと思います。
なお、ホスト側から接続しないのであれば、この設定は必要はありません。 MySQL Workbench などの管理ツールをホストにインストールするのが面倒なのであれば、 後述の phpMyAdmin コンテナを作成して利用してみましょう。
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 にも反映されます。
version: "3.8"
services:
# MySQL コンテナ
mysql:
image: mysql:latest
environment:
TZ: Asia/Tokyo
MYSQL_ROOT_PASSWORD: password
データが消えないようにする
コンテナが再作成された際などに、MySQL コンテナのデータが消えてしまっては困ると思いますので、データが消えないようにボリュームを設定しておきましょう。 ボリュームを設定しない場合は、勝手にハッシュ名のボリュームが作成されるようなのですが、わかりづらいのでちゃんと設定した方が良いと思います。
MySQL のデータは、デフォルトでは "/var/lib/mysql" ディレクトリ配下に保存されています。
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 にバインドマウントする方法を検討してみてください。
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" ファイルも使用できるようです。
複数のファイルがある場合は、ファイル名のアルファベット順に実行されます。
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 の先頭で文字コードを指定しておくと良いでしょう。
SET NAMES 'utf8mb4'; -- 以下 CREATE 文などの初期投入したいSQL
設定ファイルを使用する
MySQL の設定を変更したい場合は、MySQL の設定ファイルである 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 側でそのファイルを編集する際は、いちいち「読み取り専用」のチェックを外したり付けたりする必要があるということなので注意してください。

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 の設定ファイルを変更するたびにビルドし直す必要がありますが、こちらの方がわかりやすくて楽かもしれません。
FROM mysql:latest COPY ./my.cnf /etc/mysql/conf.d/my.cnf RUN chmod 644 /etc/mysql/conf.d/my.cnf
version: "3.8"
services:
# MySQL コンテナ
mysql:
build: ./mysql-custom
environment:
MYSQL_ROOT_PASSWORD: password
Docker で phpMyAdmin コンテナを作る
MySQL のコンテナが作成できたので、今度はその MySQL を管理するためのツールである phpMyAdmin のコンテナを作成してみましょう。 Docker なら簡単に作成することができます。

コンテナのイメージは、下記の公式イメージを使用します。
イメージのバージョン(タグ)はいろいろありますが、特にこだわりが無いなら最新版(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 |
接続するユーザーのパスワード。 |
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 - Official Image | Docker Hub
- MySQL :: MySQL 8.0 リファレンスマニュアル :: 5.1.15 MySQL Server でのタイムゾーンのサポート
- 日々の覚書: MySQL 8.0.1でutf8mb4_ja_0900_as_csが導入された
- [Docker+Windows]mysqlのdockerイメージがmy.cnfのマウントのエラーで起動しない時の対処法 - Qiita
- 📝MySQLのDockerコンテナでconfファイルをマウントしても読み込まれない - Minerva
- phpmyadmin - Official Image | Docker Hub