データベースの永続化
もし気づいていない場合、コンテナを起動するたびに、todoリストが空になっています。なぜそうなるのでしょうか?このパートでは、コンテナがどのように動作しているかを詳しく見ていきます。
コンテナのファイルシステム
コンテナが実行されると、ファイルシステムとしてイメージのさまざまなレイヤーを使用します。各コンテナには、ファイルの作成、更新、削除ができる独自の「スクラッチスペース」も与えられます。これらの変更は、同じイメージを使用している他のコンテナでは見られません。
実際に確認する
これを確認するために、2つのコンテナを起動します。1つのコンテナでファイルを作成し、もう1つのコンテナでそのファイルが存在するか確認します。結果として、1つのコンテナで作成したファイルが、別のコンテナには存在しないことがわかります。
-
Alpineコンテナを起動し、シェルにアクセスします。
$ docker run -ti --name=mytest alpine
-
コンテナ内で
greeting.txt
という名前のファイルを作成し、その中にhello
というテキストを入れます。/ # echo "hello" > greeting.txt
-
コンテナを終了します。
/ # exit
-
新しいAlpineコンテナを起動し、
cat
コマンドを使用してファイルが存在しないことを確認します。$ docker run alpine cat greeting.txt
新しいコンテナにファイルが存在しないことを示す、以下のような出力が表示されるはずです。
cat: can't open 'greeting.txt': No such file or directory
-
docker ps --all
コマンドを使用してコンテナのIDを取得し、docker rm -f <container-id>
コマンドでコンテナを削除します。
コンテナボリューム
前の実験で確認したように、各コンテナは起動するたびにイメージの定義から開始されます。コンテナはファイルを作成、更新、削除できますが、コンテナを削除するとそれらの変更は失われ、Dockerはすべての変更をそのコンテナに隔離します。ボリュームを使えば、これを変更することができます。
ボリューム は、コンテナ内の特定のファイルシステムパスをホストマシンに接続する機能を提供します。コンテナ内のディレクトリをマウントすれば、そのディレクトリ内の変更がホストマシンにも反映されます。コンテナを再起動しても、同じディレクトリをマウントすれば、同じファイルが表示されます。
ボリュームには主に2種類あります。最終的には両方を使用しますが、まずはボリュームマウントから始めます。
todoデータの永続化
デフォルトでは、todoアプリはコンテナのファイルシステム内の /etc/todos/todo.db
にSQLiteデータベースとしてデータを保存します。SQLiteに詳しくない場合でも問題ありません。SQLiteは、すべてのデータを1つのファイルに保存するリレーショナルデータベースです。大規模なアプリケーションには最適ではありませんが、小規模なデモには適しています。後で、これを別のデータベースエンジンに切り替える方法も学びます。
データベースが単一ファイルであるため、このファイルをホストに永続化し、次のコンテナで利用できるようにすれば、前回の続きから実行できるはずです。ボリュームを作成してデータを保存しているディレクトリにアタッチ(マウント)することで、データを永続化できます。コンテナが todo.db
ファイルに書き込むと、そのデータはホスト上のボリュームに永続化されます。
前述のように、ボリュームマウントを使用します。ボリュームマウントは、不透明なデータのバケットのようなものと考えてください。Dockerはボリュームを完全に管理し、ディスク上のストレージ場所も含めて管理します。覚えておくべきは、ボリュームの名前だけです。
ボリュームを作成し、コンテナを起動する
CLIまたはDocker Desktopのグラフィカルインターフェースを使用して、ボリュームを作成し、コンテナを起動できます。
docker volume create
コマンドを使用してボリュームを作成します。
$ docker volume create todo-db
-
永続化ボリュームを使用せずにまだ実行中のtodoアプリコンテナを、
docker rm -f <id>
で停止して削除します。 -
--mount
オプションを追加してボリュームマウントを指定し、todoアプリコンテナを起動します。ボリュームに名前を付け、それをコンテナの/etc/todos
にマウントします。このディレクトリに作成されたすべてのファイルがキャプチャされます。
$ docker run -dp 127.0.0.1:3000:3000 --mount type=volume,src=todo-db,target=/etc/todos getting-started
Git Bashを使用している場合、このコマンドの構文が異なります。
$ docker run -dp 127.0.0.1:3000:3000 --mount type=volume,src=todo-db,target=//etc/todos getting-started
Git Bashの構文の違いについての詳細は、Git Bashの使用 を参照してください。
データが永続化されていることを確認する
-
コンテナが起動したら、アプリを開いて、todoリストにいくつかのアイテムを追加します。
-
Docker Desktopまたは docker ps コマンドを使ってIDを取得し、
docker rm -f <id>
コマンドを使用してtodoアプリコンテナを停止して削除します。 -
前の手順を使って新しいコンテナを起動します。
-
アプリを開くと、リストにまだアイテムが残っているはずです。
-
リストを確認し終えたら、コンテナを削除してください。
これでデータを永続化する方法を学びました。
ボリュームの詳細を確認する
「ボリュームを使用しているときにDockerはデータをどこに保存しているのか?」とよく聞かれます。これを確認するには、docker volume inspect
コマンドを使用します。
$ docker volume inspect todo-db
次のような出力が表示されるはずです:
[
{
"CreatedAt": "2019-09-26T02:18:36Z",
"Driver": "local",
"Labels": {},
"Mountpoint": "/var/lib/docker/volumes/todo-db/_data",
"Name": "todo-db",
"Options": {},
"Scope": "local"
}
]
Mountpoint
はディスク上の実際のデータの保存場所です。ほとんどのマシンでは、このディレクトリにホストからアクセスするにはrootアクセスが必要です。
まとめ
このセクションでは、コンテナデータを永続化する方法を学びました。
関連情報:
次のステップ
次は、バインドマウントを使用して、アプリをより効率的に開発する方法を学びます。