dockerに入門してみる(その5)
自分のキャリアが描けてきているような、ぼやけてきているような、とにかくエンジニアリング超楽しい。そんな日々を過ごしています。
前回の記事はこちら↓ ren-opdev.hatenablog.com 今日は、コンテナのライフサイクルを超えてDBを保持するというタスクに挑戦してみます。
コンテナのファイルシステムの独立性
DB保持の前に、コンテナのファイルシステムってどんなだったっけを見てみます。
コンテナを実行するときは、イメージから沢山のレイヤーを使用します。それぞれのコンテナはCRUD処理のために"scratch space"*1も持っているらしいです。また、まったく同一のコンテナを使用していたとしても、他のコンテナからはファイルの変更は見られないみたいです。ほう…。
実際に動かしてみる。
ファイルシステムについての挙動を確かめるため、ubuntu
コンテナを動かしてみます。
このとき、1~10000の中のランダムな数を書き込んだ/data.txt
を生成し、コンテナを動かし続けるためにファイルを監視するコマンドも実行します。
PS C:\Users\530lo\Documents\docker\tutorial\app\app> docker run -d ubuntu bash -c "shuf -i 1-10000 -n 1 -o /data.txt && tail -f /dev/null" Unable to find image 'ubuntu:latest' locally latest: Pulling from library/ubuntu da7391352a9b: Pull complete 14428a6d4bcd: Pull complete 2c2d948710f2: Pull complete Digest: sha256:c95a8e48bf88e9849f3e0f723d9f49fa12c5a00cfc6e60d2bc99d87555295e4c Status: Downloaded newer image for ubuntu:latest 9fd91cf81b48ae334c88d24a4c8cc737f971e685b352ddbcf140a6f1c45b9fe7
成功しました。
正しく実行できたかを確かめるため、ダッシュボードからコンテナのCLIを起動します。
そして、そのCLIから/data.txt
の中身を確認します。
# cat /data.txt 1081
1081が入力されているので、正しく実行できていそうです。
次に、全く同じコンテナイメージを用いてもう一つのubuntu
コンテナを動かしてみます。
このとき、-it
オプションを付けてubuntu
イメージのls
を実行します。
PS C:\Users\530lo\Documents\docker\tutorial\app\app> docker run -it ubuntu ls /
bin dev home lib32 libx32 mnt proc run srv tmp var
boot etc lib lib64 media opt root sbin sys usr
ルート配下にdata.txt
がないですね。つまり、同じコンテナイメージからコンテナを起動しても、それぞれ独立した別のコンテナとして起動することが分かりました。
コンテナボリューム
同じコンテナイメージのscratch spaceがコンテナに閉じているということは、そのコンテナの削除によって、コンテナに対するそれまでの変更も全て削除されてしまうということです。 これではコンテナに変更を加えたいときに不便ですね。
この不便を解決してくれるのが、Volumesです。 コンテナボリュームとは、ホストマシンまで遡ってそのコンテナのファイルシステムに接続する機能を提供するものです。
ちょっと何言ってるか分からないですね。
とにかく、手を動かしてみていきます。
ToDoデータを保持する。
サンプルアプリのToDoデータは/etc/todos/todo.db
のSQLiteデータベースに保存されています。
一つのファイルに保存されているということは、このファイルをホストマシン上に置いて次のコンテナでも使えるようにすれば、コンテナを変更してもデータを保持し続けることが可能となります。なるほど。データ保持の概念を理解できてきた気がする。
ボリュームを作成し、それをデータが保存されているディレクトリに取り付ければ、データ保持を実現できるようです。 そしてこの、ディレクトリにボリュームを取り付けることをマウントするというようです。カッコイイ。
ボリュームを作成し、マウントしてみる。
今回は名前付きボリュームというものを使っていきます。これはシンプルなデータ容器みたいなもので、ボリュームの名前さえ覚えておけばあとはDockerが良しなにディスクをいじってくれるという。素晴らしいですね。 さらに素晴らしいことに、ボリュームを使う度、正しいデータが提供されることをDockerが保証してくれるようです。素晴らしいですね。
ではまず、ボリュームを作成します。
PS C:\Users\530lo\Documents\docker\tutorial\app\app> docker volume create todo-db todo-db
特にログはなく、名前が返されただけです。 次に、一度ToDoアプリのコンテナを止め、ボリュームをマウントした状態で再起動してみます。
PS C:\Users\530lo\Documents\docker\tutorial\app\app> docker run -dp 3000:3000 -v todo-db:/etc/todos getting-started 5f1bae1c1be6ddab33156b9ad77819080d5c097635379e476504767595dee98c
ここで-v
オプションを使用し、todo-db
というボリュームを/etc/todos
にマウントしています。
http://localhost:3000/ を開き、適当にデータを入れてみます。
コンテナを1回削除し、再度コマンドで起動してみます。 おお!今入れたデータがそのまま残っている!!(全く同じなので、スクショは割愛)
今回は名前付きボリュームを使いましたが、Dockerのボリュームには色々種類があるみたいです。おいおい知っていきたいですね。
ボリュームの所在
Dockerが良しなにディスクをいじってくれると言いましたが、実際、どこにデータが格納されているのでしょうか。ボリュームについての情報は、docker volume inspect
コマンドで知ることができるようです。
PS C:\Users\530lo\Documents\docker\tutorial\app\app> docker volume inspect todo-db [ { "CreatedAt": "2020-12-21T16:23:40Z", "Driver": "local", "Labels": {}, "Mountpoint": "/var/lib/docker/volumes/todo-db/_data", "Name": "todo-db", "Options": {}, "Scope": "local" } ]
/var/lib/docker/volumes/todo-db/_data
に格納されていることと、めっちゃローカルなことは分かりましたが、今日は一旦深追いせず"へ~"で終えます。
ボリュームをマウントすることでコンテナを破棄してもデータを保持できることが分かったところで、このチャプターは終わりです。 AndroidのRoomやSQLiteHelperを勉強したときもそうでしたが、データ保持・操作の領域は"一寸先は沼"という感じがしてまだ少し苦手意識がありますが、焦らず一つずつ理解していきたいです。
次のチャプターでは、Bind Mounts
という概念を利用してコンテナイメージの効率的な修正の仕方を学ぶみたいです。
参考
*1:scratch spaceとは、一時的なユーザーデータなどを保持するためのストレージ