composeファイルのバージョン2以降で、YAMLのトップレベルにvolumes:を置いてボリュームの定義をし、service:内でそのボリューム名を指定するという書き方ができます。
version: "2"
services:
database:
image: mariadb:10
volumes:
- datastore:/var/lib/mysql
...(略)...
volumes:
datastore:
Docker EngineやDocker Composeのドキュメントを見るとこんな感じで書いてあるかと思います。この書き方だとdatastoreはlocalというドライバを使用して/var/lib/docker/volumes/datastore/_data
あたりのディレクトリをコンテナ内にマウントするという動作になります。
消えちゃう問題
この方式は各サービスのvolume:ではホスト側はボリュームの名称を指定するのでいちいちディレクトリパスを書かずに済むのですが、dockerコマンドでボリュームを削除するとホスト側のディレクトリごと削除されてしまうので、うっかりdocker system prune
とかしちゃうとデータベースのデータまで丸ごと消えてしまうといった事案が発生してしまいます。
サービス内で毎回ホスト側のディレクトリパスを指定する書き方ならマウントが解除されるだけで、ホスト側のディレクトリやファイルまでは消えないんですけどね…
マウントだけにする方法
Docker EngineやDocker Composeのドキュメントで見つけることができずマウントのみにする方法はないもんだと思っていたのですが、偶然こんなIssueを見る機会がありまして、こんなコメントがありました。
docker volume create --opt type=none --opt device=<host path> --opt o=bind
さらにはそれをcomposeファイルにしたものが。
volumes:
database:
driver_opts:
type: none
device: /path/is/writable/dir-does-not-exist/
o: bind
type: none
ってなんなのよ… と思いつつまねしてみたら
version: "2"
services:
database:
image: mariadb:10
volumes:
- datastore:/var/lib/mysql
...(略)...
volumes:
datastore:
driver_opts:
type: none
device: /home/docker/data/mariadb
o: bind
2017/04/28 18:06追記)
driver_ops:が抜けていたので修正しました。
docker-compose down
してdocker system prune
しても/home/docker/data/mairadb
やその中のファイルは生き残ってます! これは嬉しい! 以上です。
しかし、これドキュメントのどこに書いてあるんだろう…