はじめに
今までコピペでマウントさせてたけど、ちゃんと理解して使ってなかったので勉強することにしました。
私の解釈・言い回しで書いてるところがありますので、間違ってるところもあるかもしれません。
マウントとは
サーバーのディスク領域を共有することで別のサーバーとファイルやディレクトリを共有の仕組みを言います。サーバー間のファイル共有には、NFSマウントといった機能が利用されます。
Dockerの場合、ホストサーバーの領域とコンテナの領域を共有したい。これをvolume
やbindマウント
といった機能を使って実現しています。
マウントしないとどうなるのか
コンテナをダウンさせると、データが消えます。(残らないと言ったほうが正解かもしれない)
例えば、ログファイルやアプリケーションファイルをコンテナ内で作成した場合に、全部消えます。
マウントするメリット
まず、コンテナを落としてもデータが残ります。
アプリケーション構成ファイルをマウントさせれば、同じアプリケーションが動くコンテナを簡単に構築・複製することができます。
他にも、設定ファイルなどをマウントしておけば、ホスト側から設定を変えることもできます。
※変更がないような設定ファイルは、dockerfileでホストからコンテナにコピーする方法もありますが、マウントではないので割愛します。
volumeとは
volumeは、コンテナで扱うデータを永続化する仕組みを言います。
ホストサーバー上に、データを保持する領域を確保します。
bindマウント
下記の例は、ホスト側のcodeディレクトリを、コンテナの/opt/codeディレクトリにマウントさせる書き方になります。
ホスト側にcodeディレクトリがないとエラーになります。
version: "3.8"
services:
web:
image: nginx:latest
container_name: nginx_container
hostname: web_server
ports:
- 80:80
restart: always
environment:
TZ: Asia/Tokyo
volumes:
- type: bind
source: ./code
target: /opt/code
type : マウントタイプ
マウントの種類を記載します。
bindの他にもvolume、tmpfs、npipeといったものがあります。
source : マウント元
ホストサーバーのパスを、絶対パスもしくは、docker-compose.ymlからの相対パスで書きます。
target : マウント先のコンテナパス
コンテナのパスをフルパスで書きます。
1行で記述できる
bindマウントの場合、volumesを1行にまとめて記載することができます。
こっちの書き方の方が一般的かもしれません。
左がホストサーバー側、右がコンテナ側のディレクトリになります。
volumes:
- ./code:/opt/code
この書き方では、ホスト側にディレクトリが存在しない場合、コンテナ側のディレクトリが作成されます。
複数のディレクトリをマウントさせる
以下のように、複数ディレクトリをマウントさせることもできます。
volumes:
- ./code:/opt/code
- ./config:/opt/config
volumeマウント
/var/lib/docker_volumes/
ディレクトリにマウント先を作ってデータを永続化します。
名前付きvolumeと、匿名volumeがあります。
名前付きvolume
名前をつけてvolumeを作った場合、名前付きvolumeが作成されます。
付けた名前で名前解決することができます。
version: "3.8"
services:
web:
image: nginx:latest
container_name: nginx_container
hostname: web_server
ports:
- 80:80
restart: always
environment:
TZ: Asia/Tokyo
volumes:
- type: volume
source: mydata
target: /opt/code
volumes:
mydata:
ホストサーバーのmydataというvolume領域に、コンテナの/opt/codeディレクトリをマウントさせます。
既存volumeをマウントさせる場合
version: "3.8"
services:
web:
image: nginx:latest
container_name: nginx_container
hostname: web_server
ports:
- 80:80
restart: always
environment:
TZ: Asia/Tokyo
volumes:
- type: volume
source: mydata
target: /opt/code
volume:
nocopy: true
volumes:
mydata:
external: true
既存volumeをマウントさせる場合は、external:true
を記述する必要があります。
volume先がない場合は、volumeがない旨のエラーが出ます。
nocopyオプションは、コンテナからホストへのデータコピーを無効にします。
匿名volume
名前指定せずにvolumeを作った場合、volumeの識別のためにハッシュ値が名前として割り当てられます。
結局、ハッシュ値が名前として割り当てられてますので、ハッシュ値で名前解決できます。
version: "3.8"
services:
web:
image: nginx:latest
container_name: nginx_container
hostname: web_server
ports:
- 80:80
restart: always
environment:
TZ: Asia/Tokyo
volumes:
- type: volume
target: /opt/code
volume:
nocopy: true
名前付きvolumeと違って、servicesと同レベルにvolumesを書かない。
また、sourceも書かない。
tmpfsマウント
ディスク上ではなく、メモリ上にストレージを確保します。メモリ上なので一時的な保存となり、サーバーを落とすと消えます。
機密性の高い情報を一時保管するのに使います。
volume確認コマンド
# docker volume ls
DRIVER VOLUME NAME
local 62d2b7d20e4d71b579728bae224ab43bc7567670364ed25f90f8c663e2fbf2b2
名前なしでvolumeマウントさせた状態です。ハッシュ値で登録されています。
volumeを削除する
volumeを指定して削除する
# docker volume rm <volume名>
未使用のvolumeを一括削除する
# docker volume prune
消して良いか聞かれるので、y
選択で消えます。
コンテナをダウンさせるときにvolumeも削除する
-vオプションをつけることで、volumeも削除します。
# docker-compose down -v
ホストとコンテナ、どちらのデータがマウントされるか
- bindマウントの場合、ホストのデータがマウントされる。
- 匿名volumeマウントの場合、コンテナのデータがマウントされる。
- 名前付きvolumeマウントの場合、ホスト側にファイルがあればホストのデータが優先され、なければコンテナのデータがマウントされる。
- dockerfileでvolume指定する場合、コンテナのデータがマウントされる。
※docker-compose.ymlでvolume指定されている場合は、docker-composeの指定が優先される。