データベースの保持¶
気を付けなければ、コンテナを起動するたび、todo リストは毎回きれいに消去されます。どうしてでしょうか? このパートではコンテナがどのように動作しているのか、深掘りしましょう。
コンテナのファイルシステム¶
コンテナの実行時、イメージの様々なレイヤーを、コンテナの
実行して確認¶
この処理を見るために、2つのコンテナを起動し、それぞれにファイルを作成します。一方のコンテナで作成されたファイルは、もう一方のコンテナからは見えないと分かるでしょう。
ubuntu
コンテナを起動し、そこに/data.txt
という名前のファイルを作成し、1から10000までのランダムな数を入れます。$ docker run -d ubuntu bash -c "shuf -i 1-10000 -n 1 -o /data.txt && tail -f /dev/null"
このコマンドに興味があれば説明します。これは bash シェルを開始し、2つのコマンド(これが
&&
を使った理由)を実行しました。前半部分はランダムな数を選び、それをファイル./data.txt
に書き出します。後半部分はコンテナを実行し続けるため、単にファイルを見ているだけです。
コンテナのターミナルにアクセスしたら、出力を確認できます。そのために CLI か Docker Desktop のグラフィカルインタフェースを使います。
CLI
コマンドライン上からコンテナにアクセスするには
docker exec
コマンドを使います。コンテナ ID の取得が必要です(取得にはdocker ps
を使います)。Mac や Linux のターミナルで、あるいは、 Windows コマンドプロンプトや PowerShell で以下のコマンドで実行し、内容を確認します。$ docker exec <container-id> cat /data.txt
ランダムな数字が表示されるでしょう。
Docker Desktop
Docker Desktop では Containers* に移動し、 **ubuntu イメージを実行しているコンテナの上にマウスカーソルを移動し、 Show container actions メニューを選びます。下に展開したメニューから Open in terminal を選びます。
ターミナルとして開いているのは、 Ubuntu コンテナ内で実行中のシェルです。
/data.txt
ファイル内の内容を確認するには、次のコマンドを実行します。後ほど終わったら、このターミナルを閉じます。$ cat /data.txt
ランダムな数字が表示されるでしょう。
次に、他の
ubuntu
コンテナ(同じイメージ)を起動しても、同じファイルは見えないでしょう。Mac や Linux のターミナルで、あるいは、 Windows コマンドプロンプトや PowerShell で以下のコマンドで実行し、内容を確認します。$ docker run -it ubuntu ls /
このコマンドの場合、コンテナ内のルートディレクトリ以下のファイルを一覧表示します。確認してください、
data.txt
ファイルは一覧にありません。その理由は、ファイルを書き出したのは、1つめのコンテナのスクラッチ領域だけだからです。
次に進むため、
docker rm -f <コンテナID>
コマンドを使って、1つめのコンテナを削除します。
コンテナの ボリューム ¶
これまで試したように、各コンテナは、イメージの定義からコンテナが起動するのが分かりました。コンテナはファイルの作成、更新、削除ができますが、コンテナを削除したら、それらの変更は消失します。また、コンテナに対する全ての変更とは、
ボリューム は、コンテナ内で指定したファイルシステムのパスを、ホストマシン上へと接続できる機能を備えています。コンテナ内にディレクトリをマウントすると、ディレクトリに対する変更は、ホストマシン上からも見えます。コンテナを再起動する場合にも、同じディレクトリをマウントしていれば、再起動後も同じファイルが見えます。
ボリュームは主に2種類あります。ゆくゆくは両方を使いますが、まずはボリュームのマウントから始めましょう。
todo データを保持する¶
デフォルトでは、todo アプリが自身のデータを保存するのは、コンテナ用ファイルシステム内で /etc/todos/todo.db
にある SQLite Databese の中です。SQLite に不慣れでも、心配は要りません! これはシンプルなリレーショナル データベースで、1つのファイル内に全てのデータを保存します。大きくスケールするアプリケーションには最良ではありませんが、小さなデモには効果的です。これを他のデータベースエンジンに切り替える方法は、後ほどお伝えします。
データベースはたった1つのファイルです。そのため、ホスト上のファイルを次のコンテナで利用できるようにするだけで、データベースを保持できるため、最後に中断したところから継続できるでしょう。ボリュームを作成し、データを保管するディレクトリに todo.db
ファイルは、ホスト上のボリュームに置いておけば、保持できます。
先述の通り、ここではボリュームのマウントを使おうとしています。ボリュームのマウントとは、中身が見えないデータの
ボリュームの作成とコンテナの起動¶
CLI か Docker Desktop のグラフィカルインタフェースを使い、ボリュームの作成とコンテナの起動ができます。
CLI
docker volume create
コマンドを使ってボリュームを作成します。$ docker volume create todo-db
todo アプリのコンテナを再び作り直します。
保存するボリューム を使わずに起動しているため、docker rm -f <tag>
で停止と削除をします。
todo アプリのコンテナを起動しますが、ボリュームのマウントを指定する
--mount
オプションを追加します。ボリューム名を与え、そこをコンテナ内の/etc/todos
にマウントすると、そのパスに作成された全てのファイルを(ボリューム内に)確保します。Mac や Linux のターミナルで、あるいは、 Windows コマンドプロンプトや PowerShell で以下のコマンドで実行します。$ docker run -dp 127.0.0.1:3000:3000 --mount type=volume,src=todo-db,target=/etc/todos getting-started
Docker Desktop
ボリュームを作成します。
Docker Desktop で Volumes を選びます。
Volumes で Create を選びます。
ボリューム名として
todo-db
を指定し、それから Create を選びます。アプリのコンテナを停止・削除します。
Docker Desktop で Containers を選びます。
対象コンテナの Actions 列にある Delete を選びます。
ボリュームを待つのしてアプリコンテナを起動します。
Docker Desktop の一番上にある検索ボックスを選びます。
検索ウインドウで Images タブを選びます。
検索ボックスでコンテナ名を
getting-started
と指定します。Tip
検索でフィルタを使えば local images (ローカルイメージ)のみ表示できます。
自分が作ったイメージを選び、 Run (実行)を選びます。
Optional settings を選びます。
Host path (ホスト側パス)で、ボリューム名
todo-db
を指定しますContainer path (コンテナ側パス)で
/etc/todos
を指定します。Run (実行)を選びます。
ボリュームを深掘り¶
多くの人々が頻繁に尋ねるのは「ボリュームを使う時、 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 権限が必要なので注意してください。まさに、そこにデータがあります!
注釈
Docker Desktop 上で直接ボリュームのデータにアクセスするには
Docker Desktop を実行中に、Docker コマンドが実際に動くのは、マシン上の小さな仮想マシン内です。マウントポイントのディレクトリ内で、実際の内容を見たい場合は、何よりもまず仮想マシン内に入る必要があります。