前人未踏の領域へ アプリ開発編

Android, iOSアプリ開発に関する調査メモ置き場。ほとんどAndroid。はてなダイアリーから移行したため古い記事にはアプリ以外も含まれます。

Data volumeを理解する

Dockerチュートリアルではあまり語られないが実は重要だったりするData Volumeについて学ぶ。

Data volumeとは

Data volumeとは、コンテナ間でデータをやり取りするために特別に設計されたディレクトリのことである。特徴は以下の通り

  • Data volumeはコンテナ間で共有、再利用できる(--volume-fromオプションを使用)。
  • Data volumeへの変更は直接行われる
  • Data volumeへの変更はImageに影響を与えない。
  • Volumeはそれを使用するコンテナが無い場合でも永続化される。

最後の部分が検証しきれていないが、Docker Volumeは特定のディレクトリをImageへの変更に対する影響下から切り離し、かつ別コンテナからの参照を可能にしてくれるものである。

どんな時に使うの?

  • コンテナ内で作業を行い、それを元に新たなImageを作りたい。しかし変更時に増えたログファイルなどは対象外にしたい。
  • 特定のディレクトリの内容をコンテナ間で共有したい。
  • 新しいImageによるDBコンテナに差し替えたいが、DB自体は同じデータを引き継ぎたい。

data volumeの追加

コンテナにdata volumeを追加するにはdocker run コマンドに-vオプションをつけて使用する。1度のdocker runコマンドに対して-vオプションを複数回指定できる。

$ sudo docker run -d -P --name web -v /webapp training/webapp python app.py

これで、コンテナ内に/webappというボリュームが生成される。
また、Dockerfile内に記述しておくこともできる。

VOLUME /var/log

data volumeのマウント

またホストPCのディレクトリをdata volumeとすることもできる。

$ sudo docker run -d -P --name web -v /src/webapp:/webapp training/webapp python app.py

指定方法は以下のようになる。上記の場合ではホストPC上に/src/webappというディレクトリが生成され、コンテナ内の/webappと関連付けられる。

-v ホストPCのディレクトリ:コンテナのディレクトリ

読み取り専用にしたい場合はroをつける。

sudo docker run -d -P --name web -v /src/webapp:/opt/webapp:ro training/webapp python app.py

特定のファイルのみマウントすることもできる。

$ sudo docker run --rm -it -v ~/.bash_history:/.bash_history ubuntu /bin/bash

注意点

Volumeについて理解が進んでいれば当たり前に思えるが、序盤で躓きそうなポイント。

単に-vでVolumeを指定しただけでは共有されない。

--volume-fromで引き継ぎ元を宣言する必要がある。

Volumeを定義した箇所に対する変更はImageに反映されない。

Volumeで定義したディレクトリに対し様々な変更を行ったのちにdocker commitコマンドなどで新たにImageを作っても、Volumeに対して行った変更内容はImageに反映されない。

DockerfileにVolumeを定義した場合、継承先のDockerfileに影響を与える。

<失敗例>
MySQL用のDockerfileを作成する際、MySQLのDB格納先である /var/lib/mysql に対してVOLUMEを定義してImage(例: taker/mysql )を作成。

VOLUME /var/lib/mysql

それを利用した新たなDockerfileを作り、新たにアプリ専用のスキーマ定義を含んだImageを作成しようとする。

FROM taker/mysql
RUN service mysql start && mysql -u root -proot < create_database.sql

しかし、継承元のtaker/mysql で VOLUMEが定義されてしまっているため、新たに定義したDockerfile内でのスキーマ定義はImage生成時に無視され、作ったはずのスキーマ定義のないImageが完成してしまう。