「DockerでMySQLを動かしたいけど何から始めればいいかわからない」という方向けに、基本的なコンテナの起動からDocker Composeを使った本格的な構成・データ永続化・バックアップまで順番に解説します。
DockerでMySQLを使うメリット
ローカルに直接MySQLをインストールすると、バージョン管理が面倒だったり、PCを変えたときにまた環境構築が必要になったりします。Dockerを使うとこれらの問題が解消されます。
- 環境の統一:docker-compose.ymlを共有するだけでチーム全員が同じ環境を使える
- バージョン管理が楽:MySQL 5.7と8.0を同時に起動して切り替えられる
- 削除が簡単:コンテナを削除すれば環境がきれいに消える
- PC本体を汚さない:ホストOSにMySQLをインストールしなくていい
MySQLコンテナを起動する
まずdocker runコマンドで素早く起動してみます。
# MySQLコンテナを起動
docker run \
--name my-mysql \
-p 3306:3306 \
-e MYSQL_ROOT_PASSWORD=rootpassword \
-e MYSQL_DATABASE=mydb \
-e MYSQL_USER=myuser \
-e MYSQL_PASSWORD=mypassword \
-d mysql:8.0
# オプションの説明
# --name : コンテナに名前をつける
# -p 3306:3306 : ホストの3306番ポートをコンテナの3306番ポートにマッピング
# -e MYSQL_ROOT_PASSWORD: rootユーザーのパスワード(必須)
# -e MYSQL_DATABASE : 起動時に作成するDB名
# -e MYSQL_USER : 作成するユーザー名
# -e MYSQL_PASSWORD : 作成するユーザーのパスワード
# -d : バックグラウンドで実行
# mysql:8.0 : 使用するイメージとバージョン
起動後に接続確認します。
# コンテナが起動しているか確認
docker ps
# コンテナ内のMySQLに接続
docker exec -it my-mysql mysql -u root -p
# パスワードを入力してEnter
# MySQLプロンプトが表示されれば接続成功
mysql>
# データベース一覧を確認
mysql> show databases;
# 終了
mysql> exit
ポートが使用中でコンテナが起動しない場合は-p 3307:3306のようにホスト側のポートを変えてください。
Docker ComposeでMySQLを管理する
毎回長いdocker runコマンドを打つのは面倒です。Docker Composeを使うと設定をファイルで管理できて、コマンド一つで起動・停止できます。
# docker-compose.yml
version: '3.8'
services:
mysql:
image: mysql:8.0
container_name: my-mysql
environment:
MYSQL_ROOT_PASSWORD: rootpassword
MYSQL_DATABASE: mydb
MYSQL_USER: myuser
MYSQL_PASSWORD: mypassword
ports:
- "3306:3306"
volumes:
- mysql_data:/var/lib/mysql
- ./init:/docker-entrypoint-initdb.d
command: --default-authentication-plugin=mysql_native_password
restart: unless-stopped
volumes:
mysql_data:
# Docker Composeの基本コマンド
# 起動
docker compose up -d
# 停止
docker compose down
# コンテナを削除してボリュームも削除(データが消えるので注意)
docker compose down -v
# ログ確認
docker compose logs mysql
# MySQLに接続
docker compose exec mysql mysql -u root -p
command: --default-authentication-plugin=mysql_native_passwordはMySQL 8.0以降で認証プラグインが変わったことによる接続エラーを回避するための設定です。古いクライアントから接続する場合に必要になることがあります。
データの永続化(ボリューム設定)
Dockerコンテナはデフォルトでは削除するとデータも消えます。ボリュームを設定することでデータを保持できます。
# ボリュームの種類
① Dockerが管理するボリューム(推奨)
volumes:
- mysql_data:/var/lib/mysql
volumes:
mysql_data:
# Dockerが/var/lib/docker/volumes/に保存する
# パーミッションの問題が起きにくい
② ホストのディレクトリをマウント
volumes:
- ./mysql-data:/var/lib/mysql
# ホストのディレクトリに保存する
# パーミッションエラーが発生することがある
# 対処:chmod 777 ./mysql-data(本番環境では厳密に設定すること)
# ボリュームの確認
docker volume ls
# ボリュームの詳細
docker volume inspect mysql_data
ボリュームを使っていてもコンテナを削除するとマウントは外れますが、データは残ります。次回コンテナを起動するときに同じボリュームをマウントすればデータが復元されます。
初期化SQLを自動実行する
コンテナ起動時にテーブル作成やデータ投入を自動で実行できます。
# ディレクトリ構成
.
├── docker-compose.yml
└── init/
├── 01_create_tables.sql
└── 02_insert_data.sql
# 01_create_tables.sql
CREATE TABLE IF NOT EXISTS users (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(100) NOT NULL,
email VARCHAR(100) UNIQUE NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
# 02_insert_data.sql
INSERT INTO users (name, email) VALUES
('田中太郎', 'tanaka@example.com'),
('佐藤花子', 'sato@example.com');
# docker-compose.ymlのvolumes設定
volumes:
- ./init:/docker-entrypoint-initdb.d
/docker-entrypoint-initdb.dに置いたSQLファイルはコンテナの初回起動時に自動実行されます。ファイル名の順番で実行されるので番号プレフィックスをつけると管理しやすいです。
WebアプリとMySQLをDocker Composeで連携する
Node.jsアプリとMySQLを連携させる例です。
# docker-compose.yml(Node.js + MySQL)
version: '3.8'
services:
app:
build: .
ports:
- "3000:3000"
environment:
DB_HOST: mysql # サービス名で接続できる
DB_USER: myuser
DB_PASSWORD: mypassword
DB_NAME: mydb
depends_on:
mysql:
condition: service_healthy
mysql:
image: mysql:8.0
environment:
MYSQL_ROOT_PASSWORD: rootpassword
MYSQL_DATABASE: mydb
MYSQL_USER: myuser
MYSQL_PASSWORD: mypassword
volumes:
- mysql_data:/var/lib/mysql
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
interval: 10s
timeout: 5s
retries: 5
volumes:
mysql_data:
depends_onだけではMySQLの起動完了を待てません。healthcheckとcondition: service_healthyを組み合わせることで、MySQLが準備できてからアプリが起動するようになります。
バックアップとリストア
バックアップ
# mysqldumpでバックアップ
docker exec my-mysql mysqldump \
-u root -prootpassword \
--databases mydb \
> backup_$(date +%Y%m%d).sql
# 全データベースをバックアップ
docker exec my-mysql mysqldump \
-u root -prootpassword \
--all-databases \
> backup_all_$(date +%Y%m%d).sql
リストア
# バックアップファイルからリストア
docker exec -i my-mysql mysql \
-u root -prootpassword \
mydb < backup_20240101.sql
パスワードを-pの直後に書く方法はセキュリティ上好ましくないです。本番環境では環境変数や設定ファイルで管理することを検討してください。
# より安全なバックアップ方法(パスワードをプロンプトで入力)
docker exec -it my-mysql mysqldump \
-u root -p \
--databases mydb \
> backup.sql
パフォーマンスチューニング
MySQLの主要なパフォーマンス設定をカスタマイズする方法です。
# my.cnf(MySQLの設定ファイル)
[mysqld]
# バッファプールサイズ(メモリの50〜80%が目安)
innodb_buffer_pool_size = 512M
# 接続数の上限
max_connections = 100
# クエリキャッシュ(MySQL 8.0では削除済み)
# MySQL 5.7以前の場合のみ有効
# query_cache_size = 64M
# 一時テーブルのメモリサイズ
tmp_table_size = 64M
max_heap_table_size = 64M
# スロークエリログ(1秒以上かかったクエリを記録)
slow_query_log = 1
slow_query_log_file = /var/log/mysql/slow.log
long_query_time = 1
# docker-compose.ymlで設定ファイルをマウント
services:
mysql:
image: mysql:8.0
volumes:
- mysql_data:/var/lib/mysql
- ./my.cnf:/etc/mysql/conf.d/my.cnf:ro
deploy:
resources:
limits:
memory: 1G # コンテナのメモリ上限
cpus: '1.0' # CPU上限
よくあるエラーと対処法
# エラー①:ポートが使用中
Error: Bind for 0.0.0.0:3306 failed: port is already allocated
対処:-p 3307:3306 でホスト側のポートを変える
# エラー②:接続できない(コンテナ起動直後)
ERROR 2002 (HY000): Can't connect to local MySQL server
対処:MySQLの起動に数秒かかるので少し待ってから接続する
healthcheckを設定してdepends_onと組み合わせる
# エラー③:認証エラー
ERROR 1045 (28000): Access denied for user 'root'@'localhost'
対処:パスワードを確認
コンテナを削除してボリュームも削除してから再作成
docker compose down -v && docker compose up -d
# エラー④:ボリュームのパーミッションエラー
mysqld: Can't create/write to file '/var/lib/mysql/'
対処:Dockerが管理するボリュームを使う
ホストディレクトリをマウントする場合はchmod 777を確認
# エラー⑤:YAMLのインデントミス
yaml: line XX: mapping values are not allowed in this context
対処:スペース2つでインデントを統一する
タブ文字を使わない
まとめ
DockerでMySQLを構築する基本の流れをまとめます。
- まず
docker runでMySQLを起動して接続確認する - 設定が固まったらdocker-compose.ymlに移行する
- ボリュームを設定してデータを永続化する
- 初期化SQLで起動時のテーブル作成・データ投入を自動化する
- 定期的にmysqldumpでバックアップを取る
まずはdocker compose up -dでMySQLを起動してみるところから始めてください。