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です。
コンテナボリュームとは、ホストマシンまで遡ってそのコンテナのファイルシステムに接続する機能を提供するものです。

f:id:renkataoka:20201222005214p:plain
https://docs.docker.com/storage/volumes/ より

ちょっと何言ってるか分からないですね。
とにかく、手を動かしてみていきます。

ToDoデータを保持する。

サンプルアプリのToDoデータは/etc/todos/todo.dbSQLiteデータベースに保存されています。 一つのファイルに保存されているということは、このファイルをホストマシン上に置いて次のコンテナでも使えるようにすれば、コンテナを変更してもデータを保持し続けることが可能となります。なるほど。データ保持の概念を理解できてきた気がする。

ボリュームを作成し、それをデータが保存されているディレクトリに取り付ければ、データ保持を実現できるようです。
そしてこの、ディレクトリにボリュームを取り付けることをマウントするというようです。カッコイイ。

ボリュームを作成し、マウントしてみる。

今回は名前付きボリュームというものを使っていきます。これはシンプルなデータ容器みたいなもので、ボリュームの名前さえ覚えておけばあとは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/ を開き、適当にデータを入れてみます。

f:id:renkataoka:20201222012432p:plain

コンテナを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とは、一時的なユーザーデータなどを保持するためのストレージ