はじめに
本記事を作成するに至った経緯、およびDocker Desktopのインストール〜コンテナを作成するまでは①コンテナ作成編に記載しております。
本編(②コンテナ接続編)では、MyBatisと連携させたJavaアプリケーションから「①コンテナ作成編」で作成したコンテナ内のDBへ接続する手順を記載しています。
MyBatisとは
MyBatisとはO/Rマッパーと呼ばれるフレームワークで、JavaアプリケーションとRDB(リレーションデータベース)を仲介してデータ連携の手助けをしてくれます。
設定ファイルにDBの環境を定義しておき、MpperインターフェースにSQL構文を記載することで、DBのデータを扱うことができます。
本編ではMyBatisの基本導入(依存関係の追加や、Mapperインターフェースの作成など)については割愛し、あくまでもコンテナとの接続にフォーカスを当てています。
1. mybatis-config.xmlを作成
MyBatisフレームワークの設定ファイルである、mybatis-config.xmlを作成します。
- driverのvalueとしてMySQLを設定
- urlのvalueとしてdocker-compose.ymlに記載したポート番号「3306」とTZを設定
- passwordのvalueとして.envファイルに記載したパスワードを設定
<!-- DBの環境設定部分のみ抜粋 -->
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.cj.jdbc.Driver"/>
<property name="url"
value="jdbc:mysql://localhost:3306/break_spell?serverTimezone=Asia/Tokyo"/>
<property name="username" value="root"/>
<property name="password" value="Your_PW"/>
</dataSource>
</environment>
</environments>
2. 実行確認
ビルドし、実行確認を行います。さて、上手く動いてくれるでしょうか。
Javaアプリケーションは問題なく起動しましたが、DB処理(Mapperインターフェースに記載したSQL文の実行)を実行しようとしたところ、下記のエラーメッセージが出力されました。
### Error querying database. Cause: java.sql.SQLSyntaxErrorException: Unknown database 'break_spell'
構文エラー発生: 'break_spell'という名前のDBはないよ。
指定されたポート番号のMySQLにアクセスしてみたけど、'break_spell'という名前のDBはなかったからアクセスできなかったよ、ということのようです。
3. エラーを解消する(unknown database)
原因
docker-compose.ymlでポート番号を設定する際に、ホストOS上のMySQLと同じポート番号を使用していたことが原因のようです。
ports:
- "3306:3306"
この"3306:3306"
は「ホストOS : コンテナ」の形で指定しており、「ホストOSの3306番ポートにアクセスするとコンテナ内のMySQLが持つ3306番ポートに転送するよ」 という意味です。
この設定により、ポートとポートをマッピングする(結びつける)ことができるので、「ポートマッピング」 と呼ばれています。
Javaアプリケーションは、MyBatisから伝達されたmybatis-config.xmlの内容を基にホストOSのlocalhostの3306番ポートにアクセスします。ところが、localhostの3306番ポートにはホストOS上のMySQLが存在しているため、Javaアプリケーションはコンテナに転送される前にそのホストOS上のMySQLを見つけてアクセスしてしまったようです。
※今回のケースでは、ホストOS上にもMySQLが存在していたため、このような結果となりましたが、ホストOS上にMySQLが存在しない場合は、アプリケーションから送られた処理は正しく転送され、コンテナ内のMySQLにアクセスできていたはずです
解決策
上記のように意図せぬホストOS上のMySQLへのアクセスを防ぐため、ポート番号の設定を変更し、コンテナを作り直します。
まずは、作成済みのコンテナを削除します。
## dockerディレクトリに移動
$ cd {docker}
# -vオプションをつけてvolumeごと削除
$ docker compose down -v
docker compose down
コマンドを実行すると、作成済みのコンテナを削除することができます。
-v
オプションをつけることで、コンテナに保存されていたデータ(docker-compose.ymlで定義した名前付きvolumes、今回のケースではdb_data
)も削除することができ、クリーンな状態からやり直すことができます。
これにより、古いデータが残ってエラーを引き起こすことなどを防ぐことができ、設定変更が確実に反映された状態でコンテナを再構築することができます。
次に、docker-compose.ymlの設定を修正します。
- ホストOSのポート番号を
3307
に変更
services:
db:
image: mysql:8.0.42
container_name: break_spell_db
environment:
MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
MYSQL_DATABASE: break_spell
TZ: Asia/Tokyo
ports:
- "3307:3306"
volumes:
- ./init.sql:/docker-entrypoint-initdb.d/init.sql
- db_data:/var/lib/mysql
command: --default-authentication-plugin=mysql_native_password
volumes:
db_data:
【再掲】
上記の設定コードのうち、command:
に記載した内容は、MySQL8.0以降は非推奨のため、警告メッセージが出力されます。
警告メッセージの詳細は③番外編にて紹介しています。
①コンテナ作成編と同じ手順でコンテナを作成し、コンテナとDBが作成されていることを確認します。
docker-compose.ymlの設定を変更したので、mybatis-config.xmlの設定も同様に変更します。
- urlのvalueを
3307
に変更
<!-- DBの環境設定部分のみ抜粋 -->
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.cj.jdbc.Driver"/>
<property name="url"
value="jdbc:mysql://localhost:3307/break_spell?serverTimezone=Asia/Tokyo"/>
<property name="username" value="root"/>
<property name="password" value="Your_PW"/>
</dataSource>
</environment>
</environments>
こうすることで、Javaアプリケーションから送られた処理は無事にコンテナ内のポート番号に転送され、コンテナ内のDBにアクセスできるはずです。
4. 再び実行確認
再びビルドし、実行確認をしてみます。
Javaアプリケーションを起動し、DB処理(Mapperインターフェースに記載したSQL文の実行)を実行したところ、エラーメッセージは出力されず、コンテナ内のDBへの接続が成功したことを確認できました。
Mapperインターフェースに記載したSQL文の内容については割愛しますが、DBへの接続と基本的なデータ操作(例:データの取得、追加、更新など)が問題なく実行できることを確認し、コンテナ内のDBへの接続が成功したことを検証しています。
おわりに
これで無事に、MyBatisと連携させたJavaアプリケーションからDockerコンテナ内のDBを扱うことができるようになりました。
最後までお読みいただきありがとうございました。
次回、「③番外編」では、コンテナ作成時のログに出力された警告メッセージを紐解きます!