RAKUS Developers Blog | ラクス エンジニアブログ

株式会社ラクスのITエンジニアによる技術ブログです。

dockerコンテナのデータを永続化する方法

logy0704です。 今回は自分のコンテナ知識をアップデートするために調べたことを記事にしようと思います。 動作確認はDocker Desktop for Mac 2.1.0.5, Docker Engine 19.03.5で行なっています。

課題

基本的にコンテナを消すと中の状態を復元することはできません。

しかし、以下のようなケースでデータの永続化を行いたいことがあります。

  • データベースコンテナの状態を保存しておきたい。
  • 別のコンテナにデータ移行したい。

解決策

コンテナのデータを永続化させる方法がdockerの機能として用意されています。 主な手段は次の二つです。

  • volume
    • ホスト側のdocker管理ディレクトリ以下をコンテナにマウントする。
  • bind mount

結局どっち使えば良いの

公式ドキュメントではvolumeを推奨しています。 理由はいくつかありますが、代表的なものとしては、セキュリティ上の懸念があることが挙げられます。 bind mountの場合、コンテナからホスト側のdocker管理領域以外へのアクセスができるため、 コンテナへ侵入を許した際にホスト側にまで被害が拡大する可能性があります。

とはいえ、一部のユースケースではbind mountを使用したほうが望ましいケースもあります。 詳しくは公式ドキュメントを参照してください。

今回はvolumeについてもう少し見ていきます。

volume

docker runコマンドに-v(--volume) or --mountを指定することで、volumeをマウントした状態のコンテナを作成することができます。 volume名とコンテナ側のディレクトリを指定して実行してみます。

$ docker run -d --name sample -v my-vol:/app nginx:latest

docker inspectコマンドでコンテナの情報を確認してみると、以下のようにvolumeがマウントされていることがわかります。

        "Mounts": [
            {
                "Type": "volume",
                "Name": "my-vol",
                "Source": "/var/lib/docker/volumes/my-vol/_data",
                "Destination": "/app",
                "Driver": "local",
                "Mode": "z",
                "RW": true,
                "Propagation": ""
            }
        ],

docker volume lsコマンドで存在するボリュームの一覧を取得することができます。

$ docker volume ls

DRIVER              VOLUME NAME
local               my-vol

コンテナ内にファイルを作成してから、コンテナを消してみます。

$ docker exec -it sample bash

/# echo "hoge" > /app/hoge.txt

$ docker rm -f sample 

$ docker volume ls

DRIVER              VOLUME NAME
local               my-vol

コンテナが消えてもvolumeは消えていません。

再度、コンテナを作成し、先ほど作ったvolumeを指定してみます。

$ docker run -d --name sample -v my-vol:/app nginx:latest

$ docker exec -it sample bash

/# ls /app

hoge.txt

先ほど作成したファイルを残すことに成功しました。

名前付きvolumeと匿名volume

volumeには大きく次の2種類があります。

  • 名前付きvolume
    • その名の通り、名前を持ったvolumeです。先ほどのmy-volの部分が名前にあたります。
  • 匿名volume
    • 名前を指定しなかった場合に作られるvolumeです。docker側でユニークになるようにハッシュ値の名前が振られます。
docker run -d --name sample2 -v /app nginx:latest
        "Mounts": [
            {
                "Type": "volume",
                "Name": "a41506ad65ef324b213c6dd6cb246532a264193e8fe6fcda25829119817a0ec5",
                "Source": "/var/lib/docker/volumes/a41506ad65ef324b213c6dd6cb246532a264193e8fe6fcda25829119817a0ec5/_data",
                "Destination": "/app",
                "Driver": "local",
                "Mode": "",
                "RW": true,
                "Propagation": ""
            }
        ],

名前付きvolumeのほうがなんのためのvolumeなのかわかりやすいため、基本的には名前を指定するほうが良いと思います。

-vと--mount

volume作成には、-vと--mountの二つのオプションが使用できます。 厳密には挙動が異なる部分がありますが、ほとんど同じものです。

サンプルでは-vを使用しましたが、--mountのほうが新たに導入されたオプションで、直感的に記述できるため、こちらを使うのがおすすめです。

まとめ

  • dockerコンテナのデータを永続化するにはvolumeを使う
  • volumeを作成する際には名前をつけよう
  • 使うオプションは--mountがおすすめ
Copyright © RAKUS Co., Ltd. All rights reserved.