Dockerコンテナ間でデータを共有する方法
序章
Dockerは、実行に必要なすべてのものを含むファイルシステムをソフトウェアアプリケーションに提供するために使用される一般的なコンテナ化ツールです。 Dockerコンテナーを使用すると、ランタイム環境が一貫しているため、ソフトウェアがデプロイされている場所に関係なく、ソフトウェアが同じように動作することが保証されます。
一般に、Dockerコンテナーは一時的なものであり、コンテナーで発行されたコマンドが完了するまで実行されます。 ただし、コンテナが削除された後、アプリケーションがデータへのアクセスを共有したり、データを永続化したりする必要がある場合があります。 データベース、Webサイト用にユーザーが生成したコンテンツ、およびログファイルは、Dockerイメージに含めることが非現実的または不可能であるが、アプリケーションがアクセスする必要があるデータのほんの一例です。 データへの永続的なアクセスは、 DockerVolumesで提供されます。
Dockerボリュームは、コンテナーを作成するのと同じコマンドで作成してアタッチすることも、コンテナーとは別に作成して後でアタッチすることもできます。 この記事では、コンテナー間でデータを共有する4つの異なる方法について説明します。
前提条件
この記事をフォローするには、次のUbuntu20.04サーバーが必要です。
- sudo権限を持つroot以外のユーザー。 Ubuntu 20.04を使用したサーバーの初期設定ガイドでは、これを設定する方法について説明しています。
- Dockerは、 Ubuntu20.04にDockerをインストールして使用する方法のステップ1およびステップ2の手順に従ってインストールされます。
注:前提条件には、Ubuntu 20.04にDockerをインストールするための手順が記載されていますが、 docker
この記事のDockerデータボリュームのコマンドは、Dockerがインストールされ、sudoユーザーがに追加されている限り、他のオペレーティングシステムで機能するはずです。 docker
グループ。
ステップ1—独立したボリュームを作成する
Dockerの1.9リリースで導入された docker volume create
コマンドを使用すると、特定のコンテナに関連付けずにボリュームを作成できます。 このコマンドを使用して、という名前のボリュームを追加します DataVolume1
:
- docker volume create --name DataVolume1
コマンドが成功したことを示す名前が表示されます。
OutputDataVolume1
ボリュームを利用するために、Ubuntuイメージから新しいコンテナを作成します。 --rm
終了時に自動的に削除するフラグ。 また使用します -v
新しいボリュームをマウントします。 -v
ボリュームの名前、コロン、およびボリュームがコンテナ内に表示される場所への絶対パスが必要です。 パス内のディレクトリがイメージの一部として存在しない場合、コマンドの実行時にディレクトリが作成されます。 それらがdo存在する場合、マウントされたボリュームは既存のコンテンツを非表示にします。
- docker run -ti --rm -v DataVolume1:/datavolume1 ubuntu
コンテナ内にいる間に、ボリュームにデータを書き込みましょう。
- echo "Example1" > /datavolume1/Example1.txt
使用したので --rm
フラグを立てると、コンテナは終了時に自動的に削除されます。 ただし、ボリュームには引き続きアクセスできます。
- exit
ボリュームがシステムに存在することを確認できます。 docker volume inspect
:
- docker volume inspect DataVolume1
Output[
{
"CreatedAt": "2018-07-11T16:57:54Z",
"Driver": "local",
"Labels": {},
"Mountpoint": "/var/lib/docker/volumes/DataVolume1/_data",
"Name": "DataVolume1",
"Options": {},
"Scope": "local"
}
]
注:ホスト上のデータを次のようにリストされたパスで確認することもできます。 Mountpoint
. ただし、アプリケーションやコンテナが変更を認識していない場合、データが破損する可能性があるため、変更は避けてください。
次に、新しいコンテナを起動して接続しましょう DataVolume1
:
- docker run --rm -ti -v DataVolume1:/datavolume1 ubuntu
内容を確認します。
- cat /datavolume1/Example1.txt
OutputExample1
コンテナを終了します。
- exit
この例では、ボリュームを作成してコンテナーにアタッチし、その永続性を検証しました。
ステップ2—コンテナが削除されても持続するボリュームを作成する
次の例では、コンテナーと同時にボリュームを作成し、コンテナーを削除してから、ボリュームを新しいコンテナーにアタッチします。
を使用します docker run
ベースのUbuntuイメージを使用して新しいコンテナを作成するコマンド。 -t
私たちにターミナルを与えます、そして -i
私たちがそれと相互作用することを可能にします。 わかりやすくするために、 --name
コンテナを識別するため。
The -v
フラグを使用すると、新しいボリュームを作成できます。これを呼び出します。 DataVolume2
. コロンを使用して、この名前を、ボリュームをコンテナーにマウントする必要があるパスから分離します。 最後に、ベースUbuntuイメージを指定し、UbuntuベースイメージのDockerファイルのデフォルトコマンドに依存します。 bash
、シェルにドロップするには:
- docker run -ti --name=Container2 -v DataVolume2:/datavolume2 ubuntu
注: -v
フラグは非常に柔軟です。 構文を少し調整するだけで、ボリュームをバインドマウントまたは名前付けできます。 最初の引数が /
また ~/
バインドマウントを作成しています。 それを削除すると、ボリュームに名前を付けることになります。 例えば:
-v /path:/path/in/container
ホストディレクトリをマウントし、/path
で/path/in/container
-v path:/path/in/container
名前の付いたボリュームを作成しますpath
ホストとは関係ありません。
ホストからのディレクトリのバインドマウントの詳細については、Dockerコンテナとホスト間でデータを共有する方法を参照してください。
コンテナ内にいる間に、ボリュームにいくつかのデータを書き込みます。
- echo "Example2" > /datavolume2/Example2.txt
- cat /datavolume2/Example2.txt
OutputExample2
コンテナを終了しましょう:
- exit
コンテナを再起動すると、ボリュームが自動的にマウントされます。
- docker start -ai Container2
ボリュームが実際にマウントされ、データがまだ残っていることを確認しましょう。
- cat /datavolume2/Example2.txt
OutputExample2
最後に、終了してクリーンアップしましょう。
- exit
Dockerは、コンテナーによって参照されている場合、ボリュームを削除することを許可しません。 試してみるとどうなるか見てみましょう。
- docker volume rm DataVolume2
このメッセージは、ボリュームがまだ使用中であり、コンテナーIDの長いバージョンを提供していることを示しています。
OutputError response from daemon: unable to remove volume: remove DataVolume2: volume is in use - [d0d2233b668eddad4986313c7a4a1bc0d2edaf0c7e1c02a6a6256de27db17a63]
このIDを使用して、コンテナーを削除できます。
- docker rm d0d2233b668eddad4986313c7a4a1bc0d2edaf0c7e1c02a6a6256de27db17a63
Outputd0d2233b668eddad4986313c7a4a1bc0d2edaf0c7e1c02a6a6256de27db17a63
コンテナを削除しても、ボリュームには影響しません。 ボリュームを次のように一覧表示すると、システムにまだ存在していることがわかります。 docker volume ls
:
- docker volume ls
OutputDRIVER VOLUME NAME
local DataVolume2
そして、私たちは使用することができます docker volume rm
それを削除するには:
- docker volume rm DataVolume2
この例では、コンテナーの作成と同時に空のデータボリュームを作成しました。 次の例では、すでにデータが含まれているコンテナディレクトリを使用してボリュームを作成するとどうなるかを調べます。
ステップ3—データを使用して既存のディレクトリからボリュームを作成する
一般的に、ボリュームを独立して作成する docker volume create
コンテナの作成中にコンテナを作成することは、1つの例外を除いて同等です。 コンテナとの作成と同時にボリュームを作成すると、ベースイメージにデータを含むディレクトリへのパスが提供され、そのデータがボリュームにコピーされます。
例として、コンテナを作成し、次の場所にデータボリュームを追加します。 /var
、ベースイメージのデータを含むディレクトリ:
- docker run -ti --rm -v DataVolume3:/var ubuntu
ベース画像のすべてのコンテンツ /var
ディレクトリがボリュームにコピーされ、そのボリュームを新しいコンテナにマウントできます。
現在のコンテナを終了します。
- exit
今回は、ベースイメージのデフォルトに依存するのではなく bash
コマンド、私たちは私たち自身を発行します ls
コマンド。シェルに入らずにボリュームの内容を表示します。
- docker run --rm -v DataVolume3:/datavolume3 ubuntu ls datavolume3
ディレクトリ datavolume3
これで、ベースイメージのコンテンツのコピーが作成されます /var
ディレクトリ:
Outputbackups
cache
lib
local
lock
log
mail
opt
run
spool
tmp
マウントしたいとは思わない /var/
このようになりますが、独自のイメージを作成し、データを簡単に保存する方法が必要な場合は、これが役立ちます。 次の例では、ボリュームを複数のコンテナ間で共有する方法を示します。
ステップ4—複数のDockerコンテナ間でデータを共有する
これまで、一度に1つのコンテナにボリュームをアタッチしてきました。 多くの場合、複数のコンテナを同じデータボリュームに接続する必要があります。 これは比較的簡単に実行できますが、重要な注意点が1つあります。現時点では、Dockerはファイルロックを処理しません。 ボリュームに複数のコンテナを書き込む必要がある場合、それらのコンテナで実行されるアプリケーションは、データの破損を防ぐために共有データストアに書き込むように設計されている必要があります。
Container4とDataVolume4を作成します
使用する docker run
名前の付いた新しいコンテナを作成するには Container4
データボリュームが接続されている場合:
- docker run -ti --name=Container4 -v DataVolume4:/datavolume4 ubuntu
次に、ファイルを作成してテキストを追加します。
- echo "This file is shared between containers" > /datavolume4/Example4.txt
次に、コンテナを終了します。
- exit
これにより、ホストコマンドプロンプトに戻ります。ここで、データボリュームをマウントする新しいコンテナを作成します。 Container4
.
Container5を作成し、Container4からボリュームをマウントします
作成します Container5
、およびからのボリュームをマウントします Container4
:
- docker run -ti --name=Container5 --volumes-from Container4 ubuntu
データの永続性を確認しましょう。
- cat /datavolume4/Example4.txt
OutputThis file is shared between containers
それでは、からいくつかのテキストを追加しましょう Container5
:
- echo "Both containers can write to DataVolume4" >> /datavolume4/Example4.txt
最後に、コンテナを終了します。
- exit
次に、データがまだ存在することを確認します Container4
.
Container5で行われた変更を表示する
によってデータボリュームに書き込まれた変更を確認しましょう Container5
再起動して Container4
:
- docker start -ai Container4
変更を確認します。
- cat /datavolume4/Example4.txt
OutputThis file is shared between containers
Both containers can write to DataVolume4
両方のコンテナーがデータボリュームからの読み取りと書き込みが可能であることを確認したので、コンテナーを終了します。
- exit
繰り返しになりますが、Dockerはファイルロックを処理しないため、アプリケーションmustはファイルロック自体を考慮します。 Dockerボリュームを読み取り専用としてマウントして、コンテナーが読み取り専用アクセスを必要とするときにデータの破損が誤って発生しないようにすることができます。 :ro
. これがどのように機能するかを見てみましょう。
Container 6を起動し、ボリュームを読み取り専用でマウントします
ボリュームがコンテナにマウントされたら、通常のLinuxファイルシステムのようにマウントを解除するのではなく、代わりに、希望どおりにマウントされた新しいコンテナを作成し、必要に応じて前のコンテナを削除できます。 ボリュームを読み取り専用にするために、次のように追加します :ro
コンテナ名の最後まで:
- docker run -ti --name=Container6 --volumes-from Container4:ro ubuntu
サンプルファイルを削除して、読み取り専用ステータスを確認します。
- rm /datavolume4/Example4.txt
Outputrm: cannot remove '/datavolume4/Example4.txt': Read-only file system
最後に、コンテナを終了し、テストコンテナとボリュームをクリーンアップします。
- exit
完了したので、コンテナとボリュームをクリーンアップしましょう。
- docker rm Container4 Container5 Container6
- docker volume rm DataVolume4
この例では、データボリュームを使用して2つのコンテナー間でデータを共有する方法と、データボリュームを読み取り専用としてマウントする方法を示しました。
結論
このチュートリアルでは、コンテナを削除してもデータを保持できるデータボリュームを作成しました。 コンテナ間でデータボリュームを共有しましたが、データの破損を防ぐためにファイルロックを処理するようにアプリケーションを設計する必要があることに注意してください。 最後に、共有ボリュームを読み取り専用モードでマウントする方法を示しました。 コンテナーとホストシステム間でデータを共有する方法について知りたい場合は、Dockerコンテナーとホスト間でデータを共有する方法を参照してください。