1. 概要

Dockerコンテナーは、分離された環境でアプリケーションを実行するために使用されます。 デフォルトでは、コンテナが停止すると、コンテナ内のすべての変更が失われます。 実行間でデータを保持したい場合は、 Dockerボリュームとバインドマウントが役立ちます。 

このチュートリアルでは、Docker Volumes と、それらを管理してコンテナーに接続する方法について学習します。

2. ボリュームとは何ですか?

2.1. Dockerファイルシステム

Dockerコンテナは、imageで定義されたソフトウェアスタックを実行します。 画像は、UnionFileSystemと呼ばれるファイルシステムで機能する読み取り専用レイヤーのセットで構成されています。 新しいコンテナーを起動すると、Dockerはイメージレイヤーの上に読み取り/書き込みレイヤーを追加し、コンテナーを標準のLinuxファイルシステムのように実行できるようにします。

したがって、コンテナ内でファイルを変更すると、読み取り/書き込みレイヤーに作業コピーが作成されます。 ただし、コンテナーを停止または削除すると、その読み取り/書き込みレイヤーは失われます

ファイルを書き込んでから読み取るコマンドを実行することで、これを試すことができます。

$ docker run bash:latest \ 
  bash -c "echo hello > file.txt && cat file.txt"

結果は次のとおりです。

hello

しかし、ファイルの内容を出力するコマンドだけで同じ画像を実行すると、次のようになります。

$ docker run bash:latest bash -c "cat file.txt" 
cat: can't open 'file.txt': No such file or directory

コンテナの2回目の実行はクリーンなファイルシステムで実行されるため、ファイルが見つかりません。

2.2. バインドマウント

Docker bind mount は、コンテナーからホストマシン上のディレクトリへの高性能接続です。 ホストが独自のファイルシステムをコンテナと共有できるようにします。これにより、読み取り専用または読み取り/書き込みを行うことができます。

これにより、コンテナーを使用して、ホストにインストールしたくないツールを実行しながら、ホストのファイルを操作できるようになります。 たとえば、特定のスクリプトにカスタムバージョンの bash を使用する場合は、現在の作業ディレクトリにマウントされているbashコンテナでそのスクリプトを実行できます。

$ docker run -v $(pwd):/var/opt/project bash:latest \ 
  bash -c "echo Hello > /var/opt/project/file.txt"

v オプションは、すべての形式のマウントに使用でき、この場合、ホスト上のソース– $(pwd)の出力の作業ディレクトリ–およびコンテナ内のターゲットマウントポイント– / var / opt /project

このコマンドを実行すると、ホストマシンの作業ディレクトリにfile.txtが見つかります。 これは、Dockerコンテナーの呼び出しの間に永続ファイルを提供する簡単な方法ですが、コンテナーがホストに代わって作業を行っている場合に最も役立ちます。

これの良いユースケースの1つは、Dockerで言語のビルドツールのさまざまなバージョンを実行して、開発者のマシンでのインストールの競合を回避することです。

$(pwd -W)は、bashシェルがDockerに渡すことができる形式で作業ディレクトリを提供するために、Windowsbashシェルで必要になる場合があることに注意してください。

2.3. Dockerボリューム

バインドマウントはホストファイルシステムを使用しますが、DockerボリュームはDockerにネイティブです。 データは、ホストに接続されたストレージのどこかに保存されます。多くの場合、ローカルファイルシステムです。 ボリューム自体のライフサイクルはコンテナよりも長く、不要になるまで存続できます。 ボリュームはコンテナ間で共有できます。

場合によっては、ボリュームがホストで直接使用できない形式になっていることがあります。

3. ボリュームの管理

Dockerを使用すると、 dockervolumeコマンドセットを介してボリュームを管理できます。 ボリュームに明示的な名前(名前付きボリューム)を付けるか、Dockerがランダムな名前(匿名ボリューム)を生成できるようにすることができます。

3.1. ボリュームの作成

create サブコマンドを使用し、引数として名前を渡すことで、ボリュームを作成できます。

$ docker volume create data_volume
data_volume

名前が指定されていない場合、Dockerはランダムな名前を生成します。

$ docker volume create  
d7fb659f9b2f6c6fd7b2c796a47441fa77c8580a080e50fb0b1582c8f602ae2f

3.2. ボリュームの一覧表示

ls サブコマンドは、Dockerが認識しているすべてのボリュームを表示します。

$ docker volume ls
DRIVER 	VOLUME NAME
local 	data_volume
local   d7fb659f9b2f6c6fd7b2c796a47441fa77c8580a080e50fb0b1582c8f602ae2f

-fまたは–filter フラグを使用してフィルタリングし、 key =valueパラメーターを渡して精度を高めることができます。

$ docker volume ls -f name=data
DRIVER 	VOLUME NAME
local 	data_volume

3.3. ボリュームの検査

1つ以上のボリュームの詳細情報を表示するには、inspectサブコマンドを使用します。

$ docker volume inspect ca808e6fd82590dd0858f8f2486d3fa5bdf7523ac61d525319742e892ef56f59
[
  {
    "CreatedAt": "2020-11-13T17:04:17Z",
    "Driver": "local",
    "Labels": null,
    "Mountpoint": "/var/lib/docker/volumes/ca808e6fd82590dd0858f8f2486d3fa5bdf7523ac61d525319742e892ef56f59/_data",
    "Name": "ca808e6fd82590dd0858f8f2486d3fa5bdf7523ac61d525319742e892ef56f59",
    "Options": null,
    "Scope": "local"
  }
]

ボリュームのDriverは、Dockerホストがボリュームを見つける方法を説明していることに注意してください。 たとえば、ボリュームはnfsを介してリモートストレージに置くことができます。 この例では、ボリュームはローカルストレージにあります。

3.4. ボリュームの削除

1つ以上のボリュームを個別に削除するには、rmサブコマンドを使用できます。

$ docker volume rm data_volume
data_volume

3.5. ボリュームの剪定

prune サブコマンドを使用して、未使用のボリュームをすべて削除できます。

$ docker volume prune
WARNING! This will remove all local volumes not used by at least one container.
Are you sure you want to continue? [y/N] y
Deleted Volumes:
data_volume

4. ボリュームを使用したコンテナの開始

4.1. -vの使用

前の例で見たように、 -v オプションを使用して、バインドマウントでコンテナーを開始できます。

$ docker run -v $(pwd):/var/opt/project bash:latest \
  bash -c "ls /var/opt/project"

この構文は、ボリュームのマウントもサポートしています。

$ docker run -v data-volume:/var/opt/project bash:latest \
  bash -c "ls /var/opt/project"

ボリュームが空であるため、これはマウントポイントから何もリストしません。 ただし、コンテナの1回の呼び出し中にボリュームに書き込む場合は、次のようになります。

$ docker run -v data-volume:/var/opt/project bash:latest \
  bash -c "echo Baeldung > /var/opt/project/Baeldung.txt"

その後、このボリュームがマウントされたコンテナを使用すると、ファイルにアクセスできるようになります。

$ docker run -v data-volume:/var/opt/project bash -c "ls /var/opt/project"
Baeldung.txt

-v オプションには、コロンで区切られた3つのコンポーネントが含まれています。

  • ソースディレクトリまたはボリューム名
  • コンテナ内のマウントポイント
  • (オプション)マウントを読み取り専用にする場合は、 ro

4.2. –mountオプションの使用

よりわかりやすい–mount オプションを使用して、マウントするボリュームを指定することをお勧めします。

$ docker run --mount \
  'type=volume,src=data-volume,\
  dst=/var/opt/project,volume-driver=local,\
  readonly' \ 
  bash -c "ls /var/opt/project"

–mount への入力は、コンマで区切られたキーと値のペアの文字列です。 ここで設定しました:

  • type –ボリュームマウントを示すvolumeとして
  • src –ボリュームの名前。ただし、バインドマウントを作成していた場合、これはソースディレクトリであった可能性があります。
  • dst –コンテナ内の宛先マウントポイントとして
  • volume-driver –この場合はlocalドライバー
  • 読み取り専用–このマウントを読み取り専用にします。 読み取り/書き込みにrwを選択することもできます

上記のコマンドは、ボリュームがまだ存在しない場合にもボリュームを作成することに注意してください。

4.3. –volumes-fromを使用してボリュームを共有する

ボリュームをコンテナーにアタッチすると、コンテナーとボリュームの間に長期的な接続が作成されることに注意してください。 コンテナが終了しても、関係は引き続き存在します。 これにより、同じボリュームのセットを新しいボリュームにマウントするためのテンプレートとして終了したコンテナーを使用できます。

echo スクリプトを、data-volumeマウントのコンテナーで実行したとします。 後で、使用したすべてのコンテナリストすることができます。

$ docker ps -a
CONTAINER ID   IMAGE             COMMAND                  CREATED              STATUS                          PORTS      NAMES
4920602f8048   bash              "docker-entrypoint.s…"   7 minutes ago        Exited (0) 7 minutes ago                   exciting_payne

このコンテナで使用されているボリュームをコピーすることで、次のコンテナを実行できます。

$ docker run --volumes-from 4920 \
  bash:latest \
  bash -c "ls /var/opt/project"
Baeldung.txt

実際には、 –volumes-fromは通常、実行中のコンテナー間でボリュームをリンクするために使用されます。 Jenkinsはこれを使用して、Dockerコンテナとして実行されているエージェント間でデータを共有します。

5. 結論

この記事では、Dockerが通常、新しいファイルシステムでコンテナーを作成する方法を説明しましたが、バインドマウントとボリュームにより、コンテナーのライフサイクルを超えてデータを長期間保存できるようになりました。

Dockerボリュームを一覧表示して管理する方法と、コマンドラインを介してボリュームを実行中のコンテナーに接続する方法を確認しました。