訂正
こちら、データヴォリュームの更新を反映するには--force-recreate
も合わせて行う必要がありました。初版では、--force-recreate
は設定せず、--renew-anon-volume
だけすればよいような書き方をしてしまっていた(私自身そう思っていた)ので、訂正しております。
https://docs.docker.jp/engine/userguide/dockervolumes.html
ボリュームはコンテナ作成時に初期化されます。 コンテナのベース・イメージ上で、特定のマウント・ポイント上のデータが指定されている場合、初期化されたボリューム上に既存のデータをコピーします。
GoLand 2022.1.1
Intellij, PyCharmなど、他のJetBrainsのIDEにもおそらく共通するとはおもいます。
クリーンアーキテクチャとGoの勉強用に、良さそうなプロジェクトをクローンして手元で起動したりソースコード読んだりと遊んでいました。
https://github.com/bxcodec/go-clean-arch
docker composeをあまり触ったことがなかったのですが、開発用のDBをこんなに簡単に準備できるのか、と感動しました。
こちらのプロジェクトでは、プロジェクト直下のPdocker-compose.yaml
ファイルにて、アプリケーションとMySQLのコンテナ起動を定義しています。
MySQL部分はこんな感じで、mysql:5.7
のimageをそのまま使い、volumesにて、初期化時に走らせるsql文を渡したり、ユーザーパスワードを設定しています。
- mysqlのDockerイメージ公式 → https://hub.docker.com/_/mysql/ (
Initializing a fresh instance
の項目) - https://qiita.com/NagaokaKenichi/items/ae037963b33a85df33f5 「Docker MySQLコンテナ起動時に初期データを投入する」こちらの記事も分かりやすかったです。
mysql:
image: mysql:5.7
container_name: go_clean_arch_mysql
command: mysqld --user=root
volumes:
- ./article.sql:/docker-entrypoint-initdb.d/init.sql
ports:
- 3306:3306
environment:
- MYSQL_DATABASE=article
- MYSQL_USER=user
- MYSQL_PASSWORD=password
- MYSQL_ROOT_PASSWORD=root
healthcheck:
test: ["CMD", "mysqladmin" ,"ping", "-h", "localhost"]
timeout: 5s
retries: 10
さて、初期データ入れたり、機能追加のためにテーブル増やしたりしたいなと思い、マウント元であるarticle.sql
に変更を加えてdocker compose upを実行しましたが、起動したコンテナを見ると、article.sql
の変更が反映されていないようです。
当初、以下の画像のように
docker compose up 時のオプションとして、
--force-recreate` = 「設定やイメージに変更がなくても、コンテナを再作成する」
をいじってみましたが、やはりデータベースは更新されない。
公式を確認すると、以下のようにありました。https://docs.docker.jp/engine/userguide/dockervolumes.html
データ・ボリュームは、データ保持のために設計されており、コンテナのライフサイクルとは独立しています。そのため、コンテナの削除時、Docker は 決して 自動的にボリュームを消さないだけでなく、コンテナから参照されなくなっても”後片付け”をせず、ボリュームはそのままです。
コンテナのライフサイクルと、データボリュームは別なので、article.sqlの変更をdocker compose upのたびに反映させる場合は、
--renew-anon-volume
以前のコンテナからデータを再利用せず、匿名ボリュームの再作成
--force-recreate
と合わせて、こちらの指定も必要でした。
ただし、この設定をすると、article.sql
に変更を加えていないときにも毎回マウントしなおすことになり無駄です。
なので、この設定をしたRun Configurationに「docker compose up mysql renew-anon-volume」のように名前をつけて、必要なときにだけこちらを使うようにしています。