はい、承知いたしました。Docker環境からMySQLへ接続するための詳細な入門記事を作成します。約5000語を目指し、背景知識から実践的な手順、トラブルシューティングまで幅広くカバーします。
【入門】Docker環境からMySQLへ接続する簡単ステップ
導入:開発環境構築の現代的なアプローチ
ソフトウェア開発において、データベースは不可欠な要素です。特にWebアプリケーションやバックエンドシステムでは、データの永続化のためにリレーショナルデータベースであるMySQLがよく利用されます。開発を進める上で、ローカルマシンにMySQLサーバーをインストールして環境を構築することも可能ですが、OS環境による違い、依存関係の衝突、バージョンの管理といった問題が発生しやすく、開発チーム間での環境差異が生まれやすいという課題があります。
そこで近年注目されているのが、コンテナ技術であるDockerを活用した開発環境の構築です。Dockerを使うことで、アプリケーションやデータベース、その他のミドルウェアといった開発に必要な要素を「コンテナ」という独立した環境で実行できます。コンテナは、OSの差異や依存関係の影響を受けにくく、誰でも同じ環境を簡単に再現できるという大きなメリットがあります。
この記事では、Dockerを使ってMySQLデータベースを起動し、さらに別のDockerコンテナ(例えば、開発中のWebアプリケーションコンテナ)からそのMySQLコンテナへ接続するための具体的なステップを、初心者の方にも分かりやすいように詳細に解説します。DockerとMySQLの組み合わせは、開発環境構築のベストプラクティスの一つと言えるでしょう。この記事を通じて、Dockerを使った効率的でポータブルな開発環境構築の基礎をマスターしてください。
この記事の対象読者:
- Dockerを触り始めたばかりで、コンテナ連携について知りたい方
- Dockerコンテナ上で動作するアプリケーションからMySQLデータベースへ接続したい方
- 開発環境構築の効率化に興味がある方
- DockerとMySQLの基本的な概念は知っているが、実際にどう連携させるか分からない方
この記事で学べること:
- Dockerを使ってMySQLコンテナを起動する方法 (
docker run
および Docker Compose) - MySQLコンテナのデータ永続化の重要性と実現方法
- Dockerネットワークの基本と、コンテナ間通信の仕組み
- 別のDockerコンテナからMySQLコンテナへ接続するための具体的な設定方法
- 接続に必要なMySQLユーザーの作成と権限設定
- 実践的なシナリオ(例: WebアプリケーションとDBの連携)
- 接続時の一般的なトラブルシューティング
さあ、Dockerを使ったMySQL環境構築の世界へ足を踏み入れましょう。
前提知識:DockerとMySQLの基本をおさらい
本格的な手順に入る前に、DockerとMySQLに関する最低限の基本概念を確認しておきましょう。既にこれらの概念に馴染みがある方は、このセクションをスキップしても構いません。
Dockerの基本:
- コンテナ (Container): アプリケーションとその実行に必要な全ての要素(コード、ランタイム、システムツール、ライブラリなど)をパッケージ化した、軽量で独立した実行環境です。他のコンテナやホストOSから隔離されています。
- イメージ (Image): コンテナを作成するための「設計図」または「テンプレート」です。アプリケーションを実行するためのファイルシステムや設定などが含まれています。イメージ自体は不変(Immutable)であり、一度作成されると変更されません。Docker Hubなどのコンテナレジストリから公式イメージや自作イメージを取得できます。
- Dockerfile: イメージを作成するための命令を記述したテキストファイルです。ベースイメージの指定、ファイルのコピー、コマンドの実行、ポート公開などを記述します。
- Docker Compose: 複数のコンテナで構成されるアプリケーションを定義し、一括で管理するためのツールです。YAMLファイル (
docker-compose.yml
) にサービス(コンテナ)の設定、ネットワーク、ボリュームなどを記述し、一つのコマンドでまとめて起動、停止、削除などが行えます。複雑なアプリケーション構成(Webサーバー、データベース、キャッシュサーバーなど)を扱う場合に非常に便利です。 - ボリューム (Volume): コンテナ内のデータを永続化するための仕組みです。コンテナは一時的なものであるため、コンテナが削除されると内部のデータも失われます。ボリュームを使うことで、コンテナのライフサイクルとは独立してデータを保存できます。データベースのように状態を持つサービスには必須です。
- ネットワーク (Network): Dockerコンテナ間の通信を可能にする仕組みです。デフォルトでいくつか利用可能なネットワークタイプがあり、ユーザー定義ネットワークを作成することも可能です。コンテナを同じネットワークに接続することで、お互いに名前解決や通信ができるようになります。
MySQLの基本:
- データベース (Database): 関連するデータの集まりを論理的にまとめたものです。MySQLサーバーには複数のデータベースを作成できます。
- テーブル (Table): データベース内で、構造化されたデータを格納するための基本的な単位です。行と列で構成され、スプレッドシートのようなイメージです。
- ユーザー (User): MySQLサーバーに接続し、データベースやテーブルにアクセスするための認証情報です。ユーザーごとにアクセス権限(データベースの作成、テーブルの読み書き、ユーザー管理など)を設定します。
- 権限 (Privileges): 特定のユーザーがどのデータベース、どのテーブルに対して、どのような操作(SELECT, INSERT, UPDATE, DELETE, CREATE, DROPなど)を行えるかを定義したものです。
- 接続情報: MySQLサーバーに接続するために必要な情報です。
- ホスト名/IPアドレス: MySQLサーバーが稼働しているマシンのネットワーク上のアドレス。
- ポート番号: MySQLサーバーがリクエストを待ち受けているネットワークポート(デフォルトは3306)。
- ユーザー名: 接続に使用するユーザーアカウント名。
- パスワード: 接続に使用するユーザーアカウントのパスワード。
- データベース名: 接続後、デフォルトで使用するデータベースの名前(指定しない場合もあります)。
これらの基本を踏まえて、DockerとMySQLを連携させる具体的な手順を見ていきましょう。
ステップ1:DockerでMySQLコンテナを起動する (docker run
)
まずは、最も基本的な方法として、docker run
コマンドを使って単一のMySQLコンテナを起動してみましょう。これにより、MySQLサーバーがDocker環境で利用可能になります。
公式のMySQLイメージはDocker Hubで提供されています。最新版または特定のバージョンを指定して利用できます。特別な理由がない限り、公式イメージの利用を推奨します。
基本的な docker run
コマンドの構造:
bash
docker run [OPTIONS] IMAGE [COMMAND] [ARG...]
MySQLコンテナ起動に必要なオプション:
MySQLコンテナを実用的に利用するためには、いくつかの重要なオプションを指定する必要があります。
-d
(または--detach
): コンテナをバックグラウンドで実行します。このオプションがないと、コンテナのログが現在のターミナルに表示され続け、ターミナルが専有されます。--name <コンテナ名>
: コンテナに分かりやすい名前を付けます。名前を付けることで、後続のコマンド(docker ps
,docker logs
,docker exec
など)でコンテナを指定しやすくなります。例:--name mysql-container
-p <ホストポート>:<コンテナポート>
(または--publish
): ホストマシンのポートとコンテナのポートをマッピングします。これにより、ホストマシンから直接コンテナ内のサービスにアクセスできるようになります。MySQLのデフォルトポートは3306です。例:-p 3306:3306
- 注意: 他のコンテナから接続する場合、必ずしもホストのポートを公開する必要はありません。コンテナ間の通信はDockerネットワーク経由で行われるのが一般的です。しかし、ホストからGUIクライアントなどで接続したい場合にはポート公開が必要です。
-e <環境変数>=<値>
(または--env
): コンテナ内で使用する環境変数を設定します。MySQLイメージでは、初期設定のためにいくつかの重要な環境変数が用意されています。MYSQL_ROOT_PASSWORD
:root
ユーザーのパスワードを指定します。この環境変数は必須です。 これを設定しないとコンテナが起動しません。例:-e MYSQL_ROOT_PASSWORD=mysecretpassword
MYSQL_DATABASE
: コンテナ起動時に自動的に作成されるデータベース名を指定します。例:-e MYSQL_DATABASE=mydatabase
MYSQL_USER
,MYSQL_PASSWORD
: 上記とは別に、指定したデータベースへのアクセス権限を持つユーザーとパスワードを自動的に作成できます。例:-e MYSQL_USER=myuser -e MYSQL_PASSWORD=mypassword
-v <ホストパス or ボリューム名>:<コンテナパス>
(または--volume
): ボリュームをマウントし、コンテナ内のデータを永続化します。MySQLのデータディレクトリはコンテナ内の/var/lib/mysql
です。このディレクトリをボリュームにマウントすることで、コンテナが削除されてもデータが失われるのを防ぎます。例:-v mysql-data:/var/lib/mysql
(名前付きボリュームの場合) または-v /path/on/host/mysql_data:/var/lib/mysql
(ホストディレクトリマウントの場合)- 名前付きボリューム (
mysql-data:/var/lib/mysql
): Dockerが管理するボリュームです。ホストOS上の特定の場所にデータが保存されますが、ユーザーが直接その場所を意識する必要はありません。Dockerによる管理が容易で、推奨される方法です。 - ホストディレクトリマウント (
/path/on/host/mysql_data:/var/lib/mysql
): ホストOS上の指定したディレクトリにコンテナ内のデータが保存されます。ホスト側からデータにアクセスしやすいというメリットがありますが、OS間の互換性問題や権限設定の問題が発生する可能性があります。
- 名前付きボリューム (
--rm
: コンテナ停止時に自動的にコンテナを削除します。一時的なテストなどで便利ですが、データを永続化しない場合は注意が必要です。
実践的な docker run
コマンド例:
以下のコマンドは、mysql-container
という名前でMySQLコンテナをバックグラウンドで起動し、root
パスワードを設定、mydatabase
というデータベースを作成、myuser
というユーザーを作成し、データを mysql-data
という名前付きボリュームに永続化します。ホストの3306ポートにもマッピングしています。
bash
docker run \
-d \
--name mysql-container \
-p 3306:3306 \
-e MYSQL_ROOT_PASSWORD=mysecretpassword \
-e MYSQL_DATABASE=mydatabase \
-e MYSQL_USER=myuser \
-e MYSQL_PASSWORD=mypassword \
-v mysql-data:/var/lib/mysql \
mysql:latest # 使用するイメージ名とタグ
- 注:
-e MYSQL_USER
と-e MYSQL_PASSWORD
を指定すると、MYSQL_DATABASE
で指定したデータベースへのアクセス権限を持つユーザーが作成されますが、このユーザーはrootユーザーと同じ権限を持つわけではありません。より詳細な権限設定は、コンテナ起動後にMySQLクライアントからSQLコマンドで実行する必要があります。
コンテナの起動確認:
コマンドを実行後、以下のコマンドでコンテナが正常に起動しているか確認できます。
bash
docker ps
STATUS
列に Up ...
と表示されていれば起動成功です。
ログを確認したい場合は、以下のコマンドを実行します。
bash
docker logs mysql-container
起動処理中のメッセージやエラーメッセージが表示されます。Init process may not be the primary process
や mysqld: ready for connections.
といったメッセージが表示されれば、MySQLサーバーが起動している可能性が高いです。
コンテナ内からの接続テスト:
MySQLコンテナが起動したら、コンテナ内に入って標準のMySQLクライアントコマンドで接続テストができます。
bash
docker exec -it mysql-container mysql -u root -p
docker exec -it <コンテナ名>
: 実行中のコンテナ内でコマンドを実行します。-it
オプションはインタラクティブなシェルを起動するために使用します。mysql -u root -p
: MySQLクライアントコマンドです。-u root
でユーザー名を指定し、-p
でパスワード入力を促します。
コマンド実行後、-e MYSQL_ROOT_PASSWORD
で設定したパスワード (mysecretpassword
) を入力します。パスワード認証に成功すれば、MySQLのプロンプト (mysql>
) が表示されます。
sql
mysql> SHOW DATABASES;
上記SQLを実行して、起動時に指定したデータベース (mydatabase
) が表示されることを確認してみましょう。
テストが完了したら、exit;
または quit;
と入力してクライアントを終了します。
コンテナの停止と削除:
コンテナを停止するには:
bash
docker stop mysql-container
コンテナを削除するには(停止後のみ可能):
bash
docker rm mysql-container
名前付きボリューム (mysql-data
) はコンテナ削除後も残ります。ボリュームを確認するには docker volume ls
、削除するには docker volume rm mysql-data
を実行します。データを保持したい場合はボリュームを削除しないでください。
ステップ2:Docker Composeを使った方法
単一のコンテナだけでなく、Webアプリケーション、データベース、その他のサービスなど、複数のコンテナを連携させて開発環境を構築する場合、Docker Composeを使うのが一般的です。Docker Composeを使うことで、これらのコンテナの設定を docker-compose.yml
という1つのファイルにまとめて記述し、コマンド一つで管理できます。
docker-compose.yml
ファイルの作成:
プロジェクトのルートディレクトリなどに docker-compose.yml
という名前のファイルを作成します。YAML形式で記述します。
基本的な docker-compose.yml
の構成要素:
“`yaml
version: ‘3.8’ # 使用するDocker Composeファイルのバージョン
services:
# ここに各サービスの定義を記述
mysql:
image: mysql:latest
container_name: myapp-mysql # コンテナ名(任意)
environment:
MYSQL_ROOT_PASSWORD: mysecretpassword_compose
MYSQL_DATABASE: myapp_db
MYSQL_USER: myapp_user
MYSQL_PASSWORD: myapp_password
# MySQL 8.0 以降の認証プラグイン問題に対応する場合(詳細後述)
# MYSQL_AUTHENTICATION_PLUGIN: mysql_native_password
ports:
– “3306:3306” # ホストの3306ポートとコンテナの3306ポートをマッピング(ホストからの接続用)
volumes:
– mysql_data_compose:/var/lib/mysql # 名前付きボリュームをデータディレクトリにマウント
ボリュームの定義(services セクションの同階層)
volumes:
mysql_data_compose: # 名前付きボリュームの名前
driver: local # ローカルストレージを使用
“`
各項目の説明:
version
: Docker Composeファイルのバージョンを指定します。通常は最新版を使用します。services
: ここに、アプリケーションを構成する各コンテナ(サービス)を定義します。mysql
: サービスの名前です。他のサービスからこの名前で参照できます(Docker Composeの内部ネットワークの場合)。image
: 使用するDockerイメージを指定します。container_name
: 生成されるコンテナに付ける名前です。指定しない場合はプロジェクト名_サービス名_連番
の形式で自動生成されます。environment
: コンテナに渡す環境変数を指定します。ports
: ホストのポートとコンテナのポートをマッピングします。volumes
: ボリュームをマウントします。左側がホスト側(ボリューム名またはパス)、右側がコンテナ内のパスです。
volumes
: 名前付きボリュームを定義します。services
セクションで使用するボリュームの名前をここで宣言します。
Docker Composeでの起動:
docker-compose.yml
ファイルがあるディレクトリで、以下のコマンドを実行します。
bash
docker compose up -d
docker compose up
:docker-compose.yml
ファイルに基づいてサービスを起動します。-d
: バックグラウンドで起動します(デタッチドモード)。
初回実行時は、指定されたイメージがローカルにない場合、自動的にDocker Hubなどからダウンロードされます。
起動確認:
起動したサービス(コンテナ)を確認するには:
bash
docker compose ps
State
列が Up
になっていれば正常に起動しています。
ログを確認するには:
bash
docker compose logs mysql
mysql
はサービス名です。
コンテナ内からの接続テスト:
docker run
の場合と同様に、docker exec
を使ってMySQLコンテナ内に入り、クライアントコマンドで接続テストができます。
bash
docker compose exec mysql mysql -u root -p
パスワード (mysecretpassword_compose
) を入力し、SHOW DATABASES;
などで確認してみてください。
停止と削除:
サービスを停止するには:
bash
docker compose stop
サービスを停止し、コンテナを削除するには:
bash
docker compose down
docker compose down
コマンドは、デフォルトではボリュームは削除しません。ボリュームも削除したい場合は、-v
オプションを付けます(注意: データが全て失われます!)。
bash
docker compose down -v
Docker Composeを使うことで、複数のコンテナ構成をファイルで管理でき、再現性が高く、起動・停止も容易になります。
ステップ3:別のDockerコンテナからMySQLコンテナへ接続する
いよいよ本題です。Webアプリケーションやその他のサービスを別のDockerコンテナで実行し、そこから先ほど起動したMySQLコンテナへ接続する方法を解説します。
Dockerコンテナ間で通信を行うには、Dockerネットワークを使用するのが最も安全で一般的な方法です。Dockerはデフォルトでいくつかのネットワークタイプを提供しており、ユーザー定義ネットワークを作成することも可能です。
方法1:Docker Composeの内部ネットワーク(推奨)
Docker Composeで複数のサービスを定義し、まとめて起動すると、デフォルトでそれらのサービスは同じネットワークに接続されます。 この内部ネットワークでは、サービス名がホスト名として名前解決できます。
これが、Docker Composeを使ってアプリケーションとデータベースの環境を構築する最大のメリットの一つです。アプリケーションコンテナからMySQLコンテナに接続する際に、IPアドレスを調べたり、ホストのポートを公開したりする必要がありません。単にMySQLサービスのサービス名とコンテナの内部ポート番号(デフォルト3306)を指定すれば接続できます。
docker-compose.yml
の例:
Webアプリケーションサービス (web
) とMySQLサービス (mysql
) を定義します。
“`yaml
version: ‘3.8’
services:
web:
build: . # または image: your_app_image
container_name: myapp-web
ports:
– “8000:80” # 例: ホストの8000ポートをコンテナの80ポートにマッピング
environment:
# アプリケーションからMySQLへの接続情報
DATABASE_HOST: mysql # ★ここが重要! サービス名で指定
DATABASE_PORT: 3306 # MySQLのコンテナ内部ポート
DATABASE_NAME: myapp_db # 接続するデータベース名
DATABASE_USER: myapp_user # 接続ユーザー名
DATABASE_PASSWORD: myapp_password # 接続パスワード
depends_on:
– mysql # mysqlサービスが起動してからwebサービスを起動するよう指定
mysql:
image: mysql:latest
container_name: myapp-mysql
environment:
MYSQL_ROOT_PASSWORD: mysecretpassword_compose
MYSQL_DATABASE: myapp_db
MYSQL_USER: myapp_user
MYSQL_PASSWORD: myapp_password
# MySQL 8.0 以降の認証プラグイン問題に対応する場合(詳細後述)
# MYSQL_AUTHENTICATION_PLUGIN: mysql_native_password
# ports: – “3306:3306” # ★このシナリオではホストへのポート公開は必須ではない
volumes:
– mysql_data_compose:/var/lib/mysql
volumes:
mysql_data_compose:
driver: local
“`
接続文字列/情報の設定:
Webアプリケーション側では、環境変数や設定ファイルでデータベースの接続情報を指定します。上記の例では環境変数で渡していますが、DATABASE_HOST
に mysql
(MySQLサービスのサービス名) を指定している点がポイントです。
アプリケーションの接続コードでは、これらの環境変数を使ってデータベースに接続します。例えば、PythonのSQLAlchemyであれば以下のような接続URLになります(PostgreSQLの場合の例だが、MySQLでも同様の形式)。
“`
例: MySQLの場合の接続URL形式
mysql+mysqlconnector://user:password@host:port/database?param=value
上記の環境変数を使うと…
DATABASE_HOST=mysql
DATABASE_PORT=3306
DATABASE_USER=myapp_user
DATABASE_PASSWORD=myapp_password
DATABASE_NAME=myapp_db
DATABASE_URL = f”mysql+mysqlconnector://{DATABASE_USER}:{DATABASE_PASSWORD}@{DATABASE_HOST}:{DATABASE_PORT}/{DATABASE_NAME}”
“`
アプリケーションがこの接続URLを使って接続しようとすると、Docker Composeの内部DNSが mysql
というホスト名を解決し、同じネットワーク内の myapp-mysql
コンテナのIPアドレスを返します。これにより、アプリケーションコンテナはMySQLコンテナと通信できるようになります。
MySQLユーザーの接続元ホスト設定:
この方法で接続する場合、MySQLコンテナ内のユーザー (myapp_user
) の接続元ホストを正しく設定する必要があります。
- もし
-e MYSQL_USER=myapp_user -e MYSQL_PASSWORD=myapp_password
でユーザーを作成した場合、そのユーザーはデフォルトでmyapp_user@'%'
(どのホストからでも接続可能) の権限を持つことがあります(MySQLイメージのバージョンによる)。この設定であれば、Docker Compose内部ネットワークからの接続も可能です。 - もし自分で
CREATE USER
コマンドでユーザーを作成する場合、接続元ホストとして'%'
を指定するか、よりセキュアにアプリケーションコンテナの名前やIPアドレスを指定したいと思うかもしれません。しかし、Docker Compose内部ネットワークではコンテナのIPアドレスは動的に変わる可能性があるため、サービス名で指定するのが最も確実です。- 残念ながら、MySQLの
CREATE USER 'user'@'host'
構文では、host
の部分に動的なホスト名(サービス名)を直接指定することはできません。host
はIPアドレス、ホスト名パターン (%
,localhost
, ワイルドカードを含む名前)、またはネットマスク付きIPアドレスで指定する必要があります。 - したがって、Docker Composeの内部ネットワークから接続する場合、最も簡単なのは 接続ユーザーのホストとして
'%'
を許可する ことです。これにより、同じDockerネットワーク内のどのコンテナからでも接続できるようになります。ただし、これは開発環境や信頼できる内部ネットワークに限るべきであり、本番環境ではより厳格なIPアドレス制限などを検討する必要があります。 - あるいは、アプリケーションコンテナに固定IPアドレスを割り当てる方法(Docker Compose v2.1以降、ネットワークの
ipam
設定で可能ですが、設定が複雑になります)や、カスタムスクリプトで起動時にアプリケーションコンテナのIPアドレスを取得してMySQLユーザーのホスト設定を動的に変更するなどの高度な対応が必要になります。
- 残念ながら、MySQLの
簡単な開発環境であれば、MySQLユーザーのホストを '%'
に設定するのが最も手軽な方法です。
MySQLコンテナ起動後に、docker compose exec mysql mysql -u root -p
でコンテナに入り、rootユーザーでログインして以下のSQLを実行してユーザーを作成または権限を確認・変更できます。
“`sql
— ユーザー作成(もし環境変数で作成されない場合や権限を細かく設定したい場合)
CREATE USER ‘myapp_user’@’%’ IDENTIFIED BY ‘myapp_password’;
— データベースへの権限付与
GRANT ALL PRIVILEGES ON myapp_db
.* TO ‘myapp_user’@’%’;
— 権限変更を反映
FLUSH PRIVILEGES;
“`
方法2:ユーザー定義ネットワーク
docker run
コマンドで複数のコンテナを起動し、それらを連携させたい場合は、ユーザー定義ネットワークを作成して各コンテナをそのネットワークに接続します。Docker Composeのデフォルトネットワークは、実質的にユーザー定義ネットワークと同様の機能を提供します。
ネットワークの作成:
bash
docker network create my-app-network
コンテナの起動(各コンテナを同じネットワークに接続):
MySQLコンテナを起動する際に、作成したネットワークを指定します。
bash
docker run \
-d \
--name mysql-container \
--network my-app-network \
# ホストへのポート公開は不要(他のコンテナからの接続が目的の場合)
# -p 3306:3306 \
-e MYSQL_ROOT_PASSWORD=mysecretpassword \
-e MYSQL_DATABASE=mydatabase \
-e MYSQL_USER=myuser \
-e MYSQL_PASSWORD=mypassword \
-v mysql-data:/var/lib/mysql \
mysql:latest
アプリケーションコンテナを起動する際も、同じネットワークを指定します。
“`bash
例: 仮のWebアプリケーションイメージ my-web-app
docker run \
-d \
–name web-app-container \
–network my-app-network \
# このコンテナからMySQLコンテナへ接続するためのホスト名を指定
# ネットワークエイリアスを使うと便利
–network-alias mysql-host-alias \
-p 8000:80 \
-e DATABASE_HOST=mysql-host-alias \
-e DATABASE_PORT=3306 \
-e DATABASE_NAME=mydatabase \
-e DATABASE_USER=myuser \
-e DATABASE_PASSWORD=mypassword \
my-web-app:latest
“`
--network my-app-network
: 作成したユーザー定義ネットワークにコンテナを接続します。--network-alias mysql-host-alias
: このコンテナ (mysql-container
) が、同じネットワーク上の他のコンテナからmysql-host-alias
という名前で参照できるようにします。アプリケーションコンテナはこのエイリアス名でMySQLに接続できます。これはDocker Composeのサービス名による名前解決と同様の機能です。
接続情報の設定:
アプリケーションコンテナからは、環境変数などで指定された DATABASE_HOST
(ここでは mysql-host-alias
) と DATABASE_PORT
(3306) を使ってMySQLに接続します。
MySQLユーザーの接続元ホスト設定:
ユーザー定義ネットワークの場合も、基本的にはDocker Composeの場合と同様です。アプリケーションコンテナはネットワーク内のIPアドレスでMySQLコンテナにアクセスしますが、IPアドレスは動的に変わる可能性があります。安定した接続のためには、接続ユーザーのホストとして '%'
を許可する のが最も手軽です。あるいは、アプリケーションコンテナに設定した --network-alias
の名前(例: 'myapp_user'@'mysql-host-alias'
)をユーザー定義のホストとして使用できる 場合もあります が、これはDockerのバージョンやネットワーク構成に依存する可能性があります。最も互換性が高く推奨されるのはやはり '%'
です。
方法3:ホストネットワーク(非推奨)
--network host
オプションを使うと、コンテナはホストOSのネットワークスタックを共有します。つまり、コンテナはホストOSと同じIPアドレスを持ち、ホストOSからアクセスできるポートにはコンテナからもアクセスできます。
使用例 (非推奨):
“`bash
ホストネットワークでMySQLコンテナを起動
docker run \
-d \
–name mysql-container \
–network host \ # ホストネットワークを使用
-e MYSQL_ROOT_PASSWORD=mysecretpassword \
-e MYSQL_DATABASE=mydatabase \
-e MYSQL_USER=myuser \
-e MYSQL_PASSWORD=mypassword \
-v mysql-data:/var/lib/mysql \
mysql:latest
ホストネットワークでアプリケーションコンテナを起動
docker run \
-d \
–name web-app-container \
–network host \ # ホストネットワークを使用
-p 8000:80 \ # ホストネットワークのため、コンテナのポートはホストのポートとして直接利用可能だが、ポートマッピングを明示することも可能
-e DATABASE_HOST=127.0.0.1 # またはホストの実際のIPアドレス
-e DATABASE_PORT=3306 \ # ホスト上でMySQLが待ち受けているポート
-e DATABASE_NAME=mydatabase \
-e DATABASE_USER=myuser \
-e DATABASE_PASSWORD=mypassword \
my-web-app:latest
“`
この方法のメリットは、コンテナがホストOSからMySQLにアクセスするのとほとんど同じ感覚で接続できることです。アプリケーションコンテナから見ると、MySQLはホストOSの 127.0.0.1
またはホストのプライベートIPアドレスで待ち受けているように見えます。
しかし、ホストネットワークはセキュリティ上のリスクが高く、非推奨です。
* コンテナはホストのネットワークに完全にアクセスできるため、隔離が失われます。
* ポートの衝突が発生しやすくなります(ホストですでに使用されているポートをコンテナが使おうとするとエラーになります)。
* コンテナ名による名前解決ができなくなります。
特別な理由がない限り、ユーザー定義ネットワークまたはDocker Composeのデフォルトネットワークを使用することを強く推奨します。
方法4:コンテナのIPアドレスを直接指定(一時的/デバッグ用)
Dockerネットワークに接続されたコンテナはIPアドレスを持っています。このIPアドレスを調べて、直接接続する方法も考えられます。
コンテナのIPアドレスを調べる:
bash
docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' mysql-container
このコマンドで、指定したコンテナ (mysql-container
) のIPアドレスが表示されます。
接続情報の設定:
アプリケーション側で、DATABASE_HOST
にこのIPアドレスを指定します。
“`bash
アプリケーションコンテナ起動時の環境変数
-e DATABASE_HOST=172.18.0.2 # 上記コマンドで調べたIPアドレス
-e DATABASE_PORT=3306
…
“`
問題点:
- IPアドレスは動的: Dockerはコンテナを再起動したり、ネットワーク構成を変更したりすると、IPアドレスが変わる可能性があります。したがって、この方法は永続的な接続には向いていません。
- 手動での設定: アプリケーションの環境変数に毎回手動でIPアドレスを設定する必要があり、自動化やチーム開発には不向きです。
- MySQLユーザーの接続元ホスト設定: MySQL側では、この動的なIPアドレス、あるいはそのIPアドレスが含まれるネットワーク範囲からの接続を許可する必要があります。
この方法は、主にデバッグ目的や一時的な検証に限定して使用するべきです。本番環境や継続的な開発環境では、サービス名やネットワークエイリアスを使った名前解決を利用しましょう。
各接続方法の比較と使い分け
方法 | 設定方法 | 名前解決 | 接続元ホスト設定(MySQL) | メリット | デメリット | 推奨度 |
---|---|---|---|---|---|---|
Docker Compose内部 | docker-compose.yml |
サービス名 | ‘%’ が最も容易、IPは動的 | 簡単設定、サービス名で解決、メンテ容易 | MySQLホストとしてサービス名を直接指定できない | 高 (複数コンテナの場合) |
ユーザー定義ネットワーク | docker network create , docker run --network |
エイリアス名/コンテナ名 | ‘%’ が最も容易、IPは動的 | docker run でもコンテナ間連携、名前解決可能 |
設定コマンドが増える、MySQLホストとしてエイリアス名を直接指定できない場合がある | 中 (単一コンテナ連携の場合) |
ホストネットワーク | docker run --network host |
なし | ホストIPまたは ‘%’ | ホストからのアクセスと同様の感覚 | 非推奨 (隔離なし、セキュリティリスク、ポート衝突) | 低 |
IPアドレス直指定 | docker inspect で確認、環境変数に設定 |
なし | 動的IPまたは範囲指定、’%’ | 一時的なデバッグには使える | 非推奨 (IPが動的、手動設定、管理困難) | 低 |
結論として、Dockerを使った開発環境で複数のコンテナを連携させてMySQLに接続する場合:
- 複数のサービス(Webアプリ、DBなど)をまとめて管理するなら Docker Composeの内部ネットワーク を使うのが最も一般的で推奨されます。MySQLへの接続には、
host
にMySQLサービスのサービス名を指定します。 docker run
コマンドで個別にコンテナを起動する場合でも、コンテナ間連携が必要なら ユーザー定義ネットワーク を作成し、コンテナをそのネットワークに接続して--network-alias
などで名前解決を行うのが良いでしょう。- MySQL側のユーザー設定では、接続元ホストを
'%'
とするのが最も手軽ですが、セキュリティ要件によっては'%'
の使用は開発・テスト環境に限定すべきです。
ステップ4:接続のためのMySQLユーザー設定の詳細
別のDockerコンテナからMySQLコンテナへ接続する際には、接続に使用するユーザーアカウントと、そのアカウントがどのホストからの接続を許可されているか(host
の設定)が非常に重要です。
Dockerコンテナ内のMySQLにデフォルトで存在する root
ユーザーは、通常 'localhost'
からのみ接続が許可されています。これはセキュリティ上の理由からです。そのため、別のコンテナから root
ユーザーで接続しようとしても、デフォルト設定では許可されず、「Access denied」エラーが発生します。
別のコンテナから接続するには、以下のいずれかの方法が必要です。
- 既存ユーザー(例: root)の接続元ホストを
'%'
に変更する (非推奨: root権限を外部に公開することになるため) - 新規にユーザーを作成し、そのユーザーの接続元ホストを適切に設定する (推奨)
docker-compose.yml
の environment
で MYSQL_USER
と MYSQL_PASSWORD
を指定してユーザーを作成した場合、そのユーザーは通常 '%'
からの接続が許可されます。これが最も簡単な方法ですが、このユーザーに付与される権限は、MYSQL_DATABASE
で指定したデータベースへのアクセス権限のみであり、root権限は持ちません。
より柔軟な権限管理や、接続元ホストを細かく設定したい場合は、MySQLクライアントからSQLコマンドを実行してユーザーを作成・設定します。
手順:
- MySQLコンテナが起動していることを確認します。
-
docker exec
またはdocker compose exec
を使って、MySQLコンテナ内でMySQLクライアントを起動し、rootユーザーでログインします。
“`bash
# docker run で起動した場合
docker exec -it mysql-container mysql -u root -pdocker compose で起動した場合
docker compose exec mysql mysql -u root -p
“`
rootパスワードを入力してログインします。 -
新しいユーザーを作成し、接続元ホストを指定します。
“`sql
— ユーザー名: my_app_user
— パスワード: my_app_password
— 接続元ホスト: ‘%’ (どのホストからでも許可)
CREATE USER ‘my_app_user’@’%’ IDENTIFIED BY ‘my_app_password’;— または、特定のネットワーク内からの接続を許可する場合
— Dockerデフォルトネットワークやユーザー定義ネットワークのIPレンジを指定
— 例: 172.18.0.% というIPレンジから許可
— docker network inspectでIPレンジを確認できます
— CREATE USER ‘my_app_user’@’172.18.0.%’ IDENTIFIED BY ‘my_app_password’;— 特定のIPアドレスから許可 (非推奨: IPが変わりうるため)
— CREATE USER ‘my_app_user’@’172.18.0.2’ IDENTIFIED BY ‘my_app_password’;— MySQL 8.0 以降で互換性の高い認証プラグインを指定する場合
— CREATE USER ‘my_app_user’@’%’ IDENTIFIED BY ‘my_app_password’ WITH mysql_native_password;
``
mysql_native_password
**補足: MySQL 8.0 以降の認証プラグインについて**
MySQL 8.0 からデフォルトの認証プラグインがから
caching_sha2_passwordに変更されました。古いクライアントライブラリはこの新しいプラグインに対応していない場合があり、接続エラーの原因となることがあります (
Client does not support authentication protocol requested by server…)。
mysql_native_password
この問題を回避するには、以下の方法があります。
* クライアントライブラリを最新版に更新する。
* MySQLサーバー側で、新しいユーザーに対してプラグインを使用するように指定する (
WITH mysql_native_password)。
mysql_native_password
* MySQLサーバー全体の設定で、デフォルト認証プラグインをに戻す(非推奨だが手軽)。Dockerイメージでは、環境変数
MYSQL_AUTHENTICATION_PLUGIN=mysql_native_password` を指定するか、my.cnf 設定ファイルのマウントなどで実現できます。開発環境ではこの環境変数での対応が手軽です。 -
作成したユーザーに、必要なデータベースおよびテーブルへの権限を付与します。
“`sql
— ユーザー名: my_app_user
— 接続元ホスト: ‘%’
— データベース名: my_application_db (存在しない場合は事前に作成またはCREATE DATABASE権限を付与)— my_application_db データベースの全てのテーブルに対して、SELECT, INSERT, UPDATE, DELETE 権限を付与
GRANT SELECT, INSERT, UPDATE, DELETE ONmy_application_db
.* TO ‘my_app_user’@’%’;— もしデータベースの作成やテーブル作成も許可したい場合は ALL PRIVILEGES を使用(開発環境向け)
— GRANT ALL PRIVILEGES ONmy_application_db
.* TO ‘my_app_user’@’%’;— 特定のテーブルのみ権限を付与する場合
— GRANT SELECT, INSERT ONmy_application_db
.users
TO ‘my_app_user’@’%’;
``
GRANT ALL PRIVILEGES` が手軽ですが、本番環境では必要な最低限の権限のみを付与することがセキュリティ上重要です。
権限の種類については、MySQLのドキュメントを参照してください。開発環境であれば -
権限の変更を反映します。
sql
FLUSH PRIVILEGES;
GRANT
ステートメントを実行しても、権限テーブルがメモリにキャッシュされている場合、すぐに反映されないことがあります。FLUSH PRIVILEGES
コマンドを実行することで、キャッシュされた権限テーブルがリロードされ、変更が即座に有効になります。
これらの手順で、別のコンテナからの接続に必要なユーザー設定が完了します。アプリケーションコンテナ側では、ここで設定したユーザー名、パスワード、接続元ホスト名(Dockerネットワークでの名前解決名)、ポート番号、データベース名を指定して接続を行います。
ステップ5:実践的なシナリオ例(WebアプリケーションとMySQLの連携)
ここでは、簡単なPython (Flask) WebアプリケーションとMySQLをDocker Composeで連携させる具体的な例を示します。アプリケーションはデータベースからデータを読み書きするシンプルなものを想定します。
プロジェクト構成:
my_app/
├── app/
│ ├── app.py # Flaskアプリケーションコード
│ └── requirements.txt # アプリケーションの依存ライブラリ
├── Dockerfile # アプリケーションコンテナ用Dockerfile
└── docker-compose.yml # Docker Compose設定ファイル
app/requirements.txt
:
Flask==2.2.2
mysql-connector-python==8.0.30 # MySQL接続用ライブラリ
app/app.py
:
“`python
from flask import Flask, jsonify
import mysql.connector
import os
app = Flask(name)
環境変数からデータベース接続情報を取得
DB_HOST = os.environ.get(‘DATABASE_HOST’, ‘localhost’)
DB_PORT = os.environ.get(‘DATABASE_PORT’, ‘3306’)
DB_NAME = os.environ.get(‘DATABASE_NAME’, ‘test_db’)
DB_USER = os.environ.get(‘DATABASE_USER’, ‘root’)
DB_PASSWORD = os.environ.get(‘DATABASE_PASSWORD’, ‘password’)
def get_db_connection():
“””データベース接続を確立する関数”””
try:
connection = mysql.connector.connect(
host=DB_HOST,
port=DB_PORT,
database=DB_NAME,
user=DB_USER,
password=DB_PASSWORD
)
return connection
except mysql.connector.Error as err:
print(f”Error connecting to database: {err}”)
return None
@app.route(‘/’)
def index():
return “Flask App connected to MySQL!”
@app.route(‘/users’)
def list_users():
conn = get_db_connection()
if conn is None:
return jsonify({“error”: “Database connection failed”}), 500
cursor = conn.cursor(dictionary=True) # 辞書形式で結果を取得
users = []
try:
# サンプル: users テーブルが存在すると仮定
cursor.execute("SELECT id, name FROM users")
users = cursor.fetchall()
except mysql.connector.Error as err:
return jsonify({"error": f"Database query failed: {err}"}), 500
finally:
cursor.close()
conn.close()
return jsonify(users)
@app.route(‘/create_users_table’)
def create_table():
conn = get_db_connection()
if conn is None:
return jsonify({“error”: “Database connection failed”}), 500
cursor = conn.cursor()
try:
# users テーブルが存在しない場合に作成
cursor.execute("""
CREATE TABLE IF NOT EXISTS users (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(255) NOT NULL
)
""")
conn.commit() # 変更をコミット
return jsonify({"message": "users table created or already exists"})
except mysql.connector.Error as err:
return jsonify({"error": f"Failed to create table: {err}"}), 500
finally:
cursor.close()
conn.close()
@app.route(‘/add_user/
def add_user(name):
conn = get_db_connection()
if conn is None:
return jsonify({“error”: “Database connection failed”}), 500
cursor = conn.cursor()
try:
cursor.execute("INSERT INTO users (name) VALUES (%s)", (name,))
conn.commit()
return jsonify({"message": f"User '{name}' added"})
except mysql.connector.Error as err:
conn.rollback() # エラー時はロールバック
return jsonify({"error": f"Failed to add user: {err}"}), 500
finally:
cursor.close()
conn.close()
if name == ‘main‘:
# 本番環境ではwaitressなどのWSGIサーバーを使用推奨
# Docker環境では通常、開発用サーバー(debug=True)は使わないが、ここでは簡略化
app.run(debug=True, host=’0.0.0.0’, port=80)
“`
Dockerfile
(アプリケーションコンテナ用):
“`dockerfile
Pythonの公式イメージをベースとする
FROM python:3.9-slim
作業ディレクトリを設定
WORKDIR /app
アプリケーションコードと依存ファイルをコンテナにコピー
COPY requirements.txt .
COPY app.py .
Pythonの依存ライブラリをインストール
RUN pip install –no-cache-dir -r requirements.txt
アプリケーションがリッスンするポートを公開
EXPOSE 80
アプリケーションを起動
CMD [“python”, “app.py”]
“`
docker-compose.yml
:
“`yaml
version: ‘3.8’
services:
web:
build: . # 現在のディレクトリにあるDockerfileを使用
container_name: myapp-web
ports:
– “8000:80” # ホストの8000番ポートをコンテナの80番ポートにマッピング
environment:
# アプリケーションからMySQLへの接続情報 – MySQLサービスの「サービス名」を指定
DATABASE_HOST: mysql
DATABASE_PORT: 3306
DATABASE_NAME: myapp_db
DATABASE_USER: myapp_user
DATABASE_PASSWORD: myapp_password_compose
# MySQLサービスが完全に起動するまで待つ(任意だが推奨)
depends_on:
mysql:
condition: service_healthy # MySQLサービスにhealthcheckを設定した場合に使用
# または condition: service_started # 単純な起動確認
networks:
– app_network # ユーザー定義ネットワークに接続
mysql:
image: mysql:8.0 # バージョンを指定
container_name: myapp-mysql
environment:
MYSQL_ROOT_PASSWORD: mysecretpassword_compose
MYSQL_DATABASE: myapp_db
MYSQL_USER: myapp_user
MYSQL_PASSWORD: myapp_password_compose
# MySQL 8.0 以降で古いクライアントに対応する場合
MYSQL_AUTHENTICATION_PLUGIN: mysql_native_password
# ホストへのポート公開は必須ではないが、開発中にホストからGUIツール等で接続したい場合は必要
# ports:
# – “3306:3306”
volumes:
– mysql_data_compose:/var/lib/mysql # データを永続化
# コンテナのヘルスチェックを設定(optionalだが depends_on で healthy を使う場合に必要)
healthcheck:
test: [“CMD”, “mysqladmin”, “ping”, “-h”, “localhost”, “-u”, “root”, “-p${MYSQL_ROOT_PASSWORD}”]
interval: 10s # 10秒ごとにチェック
timeout: 5s # チェックタイムアウト
retries: 3 # リトライ回数
networks:
– app_network # アプリケーションコンテナと同じネットワークに接続
ユーザー定義ネットワークの定義
networks:
app_network:
driver: bridge # デフォルトのブリッジネットワークを使用
ボリュームの定義
volumes:
mysql_data_compose:
driver: local
“`
構築と実行手順:
- 上記のファイル構成と内容でファイルを作成します。
- プロジェクトルート (
my_app/
) ディレクトリでターミナルを開きます。 -
Docker Composeを使ってサービスを起動します。
bash
docker compose up -d --build
--build
オプションは、アプリケーションコンテナのイメージをDockerfileからビルドします。 -
コンテナが起動していることを確認します。
bash
docker compose ps
State
がUp
になっていることを確認します。healthcheck
を設定している場合は、healthy
になるまで少し時間がかかる場合があります。 -
Webブラウザまたは
curl
コマンドでアプリケーションにアクセスします。http://localhost:8000/
にアクセスすると “Flask App connected to MySQL!” が表示されます。http://localhost:8000/create_users_table
にアクセスすると、MySQLに接続してusers
テーブルを作成します。http://localhost:8000/add_user/Alice
にアクセスすると、Aliceという名前のユーザーをデータベースに追加します。http://localhost:8000/add_user/Bob
にアクセスすると、Bobという名前のユーザーをデータベースに追加します。http://localhost:8000/users
にアクセスすると、データベースからユーザーリストを取得して表示します。
この例では、アプリケーションコンテナからMySQLコンテナへの接続に、DATABASE_HOST: mysql
と、MySQLサービスのサービス名 (mysql
) を使用していることが確認できます。Docker Composeの内部ネットワークが、この名前解決を自動的に行います。
また、MySQLコンテナの環境変数で MYSQL_USER
, MYSQL_PASSWORD
, MYSQL_DATABASE
を指定しているため、別途rootユーザーでログインしてユーザー作成や権限付与を行う必要はありません(ただし、より細かい権限設定が必要な場合は、起動後に手動で行う必要があります)。MYSQL_AUTHENTICATION_PLUGIN: mysql_native_password
はMySQL 8.0以降での互換性問題回避のために追加しています。
ステップ6:トラブルシューティング
Docker環境からMySQLへ接続する際に遭遇しやすい一般的な問題とその解決策をまとめます。
接続エラー: Can't connect to MySQL server...
これは、指定したホスト名やポートでMySQLサーバーに到達できない場合に発生します。
-
原因1: MySQLコンテナが起動していない
- 確認:
docker ps
またはdocker compose ps
コマンドでMySQLコンテナのステータスを確認します。State
がUp
になっている必要があります。 - 解決策: コンテナが停止している場合は
docker start <コンテナ名>
またはdocker compose up -d
で起動します。エラーで起動できない場合はdocker logs <コンテナ名>
でログを確認し、起動失敗の原因(設定ミス、ポート衝突など)を特定します。
- 確認:
-
原因2: ホスト名またはIPアドレスの間違い
- 確認: アプリケーション側の接続設定で指定しているホスト名/IPアドレスが正しいか確認します。
- Docker Composeの場合: MySQLサービスのサービス名 (
services
セクションのキー名) を指定しているか確認します。 - ユーザー定義ネットワークの場合:
--network-alias
で設定したエイリアス名、またはコンテナ名、または調査したIPアドレスを指定しているか確認します。 - ホストネットワークの場合: ホストの
127.0.0.1
またはホストのネットワーク上のIPアドレスを指定しているか確認します。
- Docker Composeの場合: MySQLサービスのサービス名 (
- 解決策: 正しいホスト名/IPアドレスに修正します。名前解決の問題が疑われる場合は、アプリケーションコンテナ内でネットワーク診断ツール(例:
ping <ホスト名>
)を使ってみることも有効ですが、コンテナイメージにツールがインストールされていないこともあります。
- 確認: アプリケーション側の接続設定で指定しているホスト名/IPアドレスが正しいか確認します。
-
原因3: ポート番号の間違い
- 確認: アプリケーション側の接続設定で指定しているポート番号が正しいか確認します。MySQLのデフォルトポートは3306です。Docker Composeやユーザー定義ネットワーク経由で接続する場合、指定するのはコンテナ内部のポート番号 (3306) です。ホストのポート番号ではありません(ホストからの接続やホストネットワーク経由の場合を除く)。
- 解決策: 正しいポート番号 (3306) に修正します。
-
原因4: Dockerネットワークの設定ミス
- 確認: アプリケーションコンテナとMySQLコンテナが同じDockerネットワークに接続されているか確認します。
- Docker Composeの場合:
docker-compose.yml
で両方のサービスが同じネットワーク(デフォルトまたは明示的に定義したネットワーク)に属しているか確認します。 docker run
の場合:docker network create
でネットワークを作成し、両方のdocker run
コマンドで--network <ネットワーク名>
を指定しているか確認します。
- Docker Composeの場合:
- 解決策: 両方のコンテナが同じネットワークに接続されるように設定を修正し、コンテナを再起動します。
docker network inspect <ネットワーク名>
コマンドで、そのネットワークに接続されているコンテナを確認できます。
- 確認: アプリケーションコンテナとMySQLコンテナが同じDockerネットワークに接続されているか確認します。
-
原因5: ファイアウォールの問題
- 確認: ホストOSや、もしコンテナ内で動作しているファイアウォールがあれば、MySQLポート (3306) への接続がブロックされていないか確認します。
- 解決策: 必要なポート(特にコンテナ間の通信や、ホストからコンテナへのアクセスで公開しているポート)がファイアウォールで許可されているか確認し、必要に応じて設定を変更します。Dockerのデフォルトネットワークでは通常内部通信は許可されていますが、ホストOSのファイアウォール設定は確認が必要です。
認証エラー: Access denied for user 'user'@'host' (using password: YES)
これは、指定したユーザー名、パスワード、または接続元ホストがMySQLサーバーによって拒否された場合に発生します。
-
原因1: ユーザー名またはパスワードの間違い
- 確認: アプリケーション側の接続設定で指定しているユーザー名とパスワードが、MySQLコンテナの設定(環境変数または手動で作成したユーザー設定)と一致しているか確認します。特にパスワードはタイポしやすいので注意が必要です。
- 解決策: 正しいユーザー名とパスワードに修正します。
-
原因2: 接続元ホストの権限がない
- 確認: 接続に使用しているMySQLユーザーが、アプリケーションコンテナからの接続元ホスト(Dockerネットワークでの名前解決名やIPアドレス)からの接続を許可されていない。
- MySQLクライアントで
SELECT user, host FROM mysql.user;
を実行し、該当ユーザーのhost
列が接続元ホストと一致するか、または'%'
(どのホストからでも許可) になっているか確認します。 - Docker Composeやユーザー定義ネットワークの場合、アプリケーションコンテナはMySQLサービス名やネットワークエイリアス名で名前解決されたIPアドレス、またはそのIPアドレスを含むネットワーク範囲で接続します。MySQLユーザーの
host
設定は、これらのIPアドレスと一致する必要があるか、または'%'
になっている必要があります。最も手軽なのは'%'
です。
- MySQLクライアントで
- 解決策: MySQLコンテナ内でrootユーザーでログインし、
CREATE USER
またはGRANT ... ON ... TO 'user'@'host'
コマンドを使って、接続元ホスト(最も簡単なのは'%'
)からの接続を許可するようにユーザー設定を変更します。変更後はFLUSH PRIVILEGES;
を実行します。
- 確認: 接続に使用しているMySQLユーザーが、アプリケーションコンテナからの接続元ホスト(Dockerネットワークでの名前解決名やIPアドレス)からの接続を許可されていない。
-
原因3: データベースまたはテーブルへの権限がない
- 確認: 接続はできたものの、特定のデータベースやテーブルへの操作(SELECT, INSERTなど)でエラーが発生する場合。
- 解決策: MySQLコンテナ内でrootユーザーでログインし、
GRANT
コマンドを使って、該当ユーザーに必要な権限を付与します。FLUSH PRIVILEGES;
を忘れずに実行します。
-
原因4: MySQL 8.0以降の認証プラグイン問題 (
Client does not support authentication protocol requested by server...
)- 確認: MySQL 8.0以降を使用しており、このエラーメッセージが表示される場合。古いクライアントライブラリがデフォルトの
caching_sha2_password
プラグインに対応していない可能性があります。 - 解決策:
- 推奨: アプリケーション側で使用しているMySQLクライアントライブラリを、
caching_sha2_password
に対応した最新バージョンに更新します。 - 代替: MySQLコンテナ起動時に、環境変数
MYSQL_AUTHENTICATION_PLUGIN=mysql_native_password
を設定するか、ユーザー作成時にWITH mysql_native_password
オプションを指定して、互換性の高い認証プラグインを使用させます。例:CREATE USER 'my_app_user'@'%' IDENTIFIED BY 'my_app_password' WITH mysql_native_password;
- 推奨: アプリケーション側で使用しているMySQLクライアントライブラリを、
- 確認: MySQL 8.0以降を使用しており、このエラーメッセージが表示される場合。古いクライアントライブラリがデフォルトの
その他
-
データが永続化されない: コンテナを停止・削除するとデータが消えてしまう。
- 原因:
docker run
またはdocker-compose.yml
でボリューム (-v
またはvolumes
) が正しく設定されていない。 - 解決策: MySQLのデータディレクトリ (
/var/lib/mysql
) を名前付きボリュームまたはホストディレクトリにマウントするように設定します。docker compose down -v
のようにボリュームも削除するコマンドを使っていないかも確認してください。
- 原因:
-
MySQLコンテナのログが確認できない:
- 確認: コンテナ名が正しいか確認します。
- 解決策:
docker logs <コンテナ名>
またはdocker compose logs <サービス名>
コマンドを使用します。
応用と発展
この記事で解説した内容は、DockerとMySQLを使った開発環境構築の基礎です。さらに進んだ応用や発展的なテーマにも触れておきましょう。
.env
ファイルの利用: Docker Composeでは、環境変数を.env
ファイルに記述して管理できます。機密情報(パスワードなど)をdocker-compose.yml
ファイルに直接書かずに済み、環境ごとに設定を分けやすくなります。- Docker Secrets: よりセキュアな機密情報管理には、Docker Secretsを利用できます。特にSwarmモードやKubernetesなどのオーケストレーション環境で有効です。
- MySQLの設定カスタマイズ: デフォルト設定以外のMySQL設定(文字コード、バッファサイズなど)を行いたい場合、カスタム設定ファイルをホストからコンテナ内の適切な場所(例:
/etc/mysql/conf.d/
)にボリュームマウントすることで実現できます。 - リードレプリカ、クラスタ構成: 冗長性やパフォーマンス向上のために、複数のMySQLコンテナを連携させてリードレプリカ構成やクラスタ構成を構築することも可能です。Docker ComposeやKubernetesなどのオーケストレーションツールが役立ちます。
- マイグレーションツール: アプリケーションのバージョンアップに伴うデータベーススキーマの変更(マイグレーション)は、FlywayやLiquibase、アプリケーションフレームワーク付属のツールなどを使って管理するのが一般的です。これらのツールもDockerコンテナ内で実行できます。
- 他のデータベースへの応用: PostgreSQL、MongoDBなどの他のデータベースも、Docker公式イメージが提供されています。本記事で解説したコンテナ起動、データ永続化、コンテナ間通信、ユーザー設定といった概念は、これらのデータベースにも応用できます。ただし、環境変数やデータディレクトリのパスなどは各データベースイメージによって異なるため、公式ドキュメントを確認してください。
まとめ:DockerとMySQLで加速する開発ワークフロー
この記事では、Docker環境からMySQLデータベースへ接続するための詳細なステップを解説しました。docker run
コマンドによる単一コンテナの起動から、Docker Composeを使った複数コンテナ連携、そして最も重要な「別のDockerコンテナからMySQLコンテナへ接続する方法」について、Dockerネットワークの概念やMySQLユーザー設定の重要性も含めて詳しく見てきました。
Dockerを使うことで、MySQLを含む開発環境を以下のようなメリットを持って構築できます。
- 容易な環境構築: コマンド一つでMySQLサーバーを起動・停止でき、OS環境に依存しません。
- 高い移植性: 同じ
docker-compose.yml
ファイルを使えば、開発メンバー全員が同じ環境を簡単に再現できます。 - 環境の分離: ホストOSや他のプロジェクトの環境に影響を与えることなく、独立したMySQL環境を構築できます。
- バージョン管理の容易さ: 必要なバージョンのMySQLイメージを簡単に切り替えて利用できます。
- データ永続化: ボリュームを使うことで、コンテナのライフサイクルとは独立してデータを安全に管理できます。
Docker Composeの内部ネットワークとサービス名による名前解決は、アプリケーションコンテナとデータベースコンテナを連携させる際のベストプラクティスです。これにより、複雑なIPアドレス管理から解放され、設定ファイルの見通しも良くなります。
また、別のコンテナから接続するためのMySQLユーザー設定、特に接続元ホスト('%'
や特定のネットワーク範囲)の設定が重要であることを理解いただけたかと思います。セキュリティを考慮しつつ、開発・テスト環境では手軽な '%'
を、本番環境ではより厳格な設定を検討することが大切です。
この記事が、Dockerを使ったモダンな開発環境構築の第一歩となり、皆さんの開発ワークフローをより効率的で安定したものにする助けとなれば幸いです。不明な点やさらに深く学びたい点があれば、DockerやMySQLの公式ドキュメントを参照したり、コミュニティに質問したりしてみてください。
Happy Containerizing!