🙌

docker-composeでvolumesを設定する

2022/03/01に公開

【環境】
MacBook Air (M1, 2020)
OS: MacOS Big Sur version11.6
Docker Desktop for Mac version4.5.0

Dockerのvolumesを設定するでホストとコンテナのvolumeをバインドさせることができました。
今回はdocker-compose.ymlでvolumesを設定します。

ディレクトリ構成

./volumes_test
├── Dockerfile
├── docker-compose.yml
└── volumes_test_dir
    └── test.txt

test.txt

test

単純なtxtファイルです。

Dockerfile

FROM alpine:latest

alpineサーバーのコンテナを作るためのDockerfileです。

docker-compose.yml

service内に記述

version: "3.8"

services:
  app:
    build:
      context: .
      dockerfile: Dockerfile
    volumes:
      - ./volumes_test_dir:/volume_dir

services > app > build > contextはDockerfileのあるPathです。(今回は同じ階層)
services > app > build > dockerfileは対象のDockerfile名です。
appサービス内にvolumesオプションを記述しています。
[ホスト側の相対Path]:コンテナの絶対Path
という形で設定します。
Dockerのvolumesを設定するで使ったDockerコマンド-vオプションではホスト側のvolumeは絶対Pathを記述しました。
docker-composeの場合はdocker-compose.ymlからの相対Pathを記述します。

それではdocker-composeのrunコマンドでコンテナを立ち上げ、txtファイルが存在するか確認します。

% docker-compose run --rm app /bin/ash
/ # ls
bin          etc          lib          mnt          proc         run          srv          tmp          var
dev          home         media        opt          root         sbin         sys          usr          volume_dir
/ # cat volume_dir/test.txt
test

volume_dirディレクトリのマウントが確認できました。
永続化されているのでコンテナを破棄してもファイルは保持されます。
またtest.txtファイルの編集はホストとコンテナで共有されます。

service外に記述

volumesはservice外に記述することもできます。
以下はtest-volumeという名前のvolumeを指定したdocker-compose.ymlです。

version: "3.8"

services:
  app:
    build:
      context: ./dockerfile_dir
      dockerfile: Dockerfile
    volumes:
      - test-volume:/volume_dir

volumes:
  test-volume:

service外(最下部のvolumes)にtest-volumeという名前のvolumeを記述し、そのtest-volumeをservice内(services > app > volumes)で使っています。
[volume名]:[コンテナの絶対Path]
という形で記述します。
ここで定義したvolumeはdocker-compose実行時に自動で作成されます。
それではdocker-composeを実行します。

% docker-compose run --rm app /bin/ash
/ # ls
bin         etc         lib         mnt         proc        run         srv         tmp         var
dev         home        media       opt         root        sbin        sys         usr         volume_dir
/ # ls volume_dir
/ # 

/volume_dirというディレクトリが作成されていました。
今回はホストとマウントしているわけではないので中身は空ですが、volume_dir内で作成したデータはtest-volumeという名前のvolumeとして永続化しています。

volumeの名前を指定する

ホスト側に戻りvolumeの名前を確認してみます。

/ # exit
% docker volume ls
DRIVER    VOLUME NAME
local     volumes_test_test-volume

volumeが自動作成される場合は
[docker-compose.ymlのあるディレクトリ名]_[volume名]
という名前が自動的に割り当てられるようです。
volumeの名前を指定するnameオプションを使ってみます。

version: "3.8"

services:
  app:
    build:
      context: ./dockerfile_dir
      dockerfile: Dockerfile
    volumes:
      - test-volume:/volume_dir

volumes:
  test-volume:
    name: named-test-volume

volumeの名前が"named-test-volume"に変わったか確認します。

% docker-compose run --rm -d app /bin/ash
52bc14c6bfd3f7c82f1a4a55e62ac2efe5ed10d7dd370b8bf2a1b7b4d11ca975
% docker volume ls
DRIVER    VOLUME NAME
local     named-test-volume

docker-compose runの-dオプションを指定するとコンテナはバックグラウンドで起動します。
volumeの名前は無事"named-test-volume"となりました。

service外に記述(volumeを事前に作成)

volumeを事前に作成した上でvolumeをバインドさせることもできます。
まずはexternal-test-volumeという名前のvolumeを事前に作成します。

% docker volume create external-test-volume
external-test-volume

docker-compose.ymlのvolumesにexternalオプションを追記します。

version: "3.8"

services:
  app:
    build:
      context: ./dockerfile_dir
      dockerfile: Dockerfile
    volumes:
      - "external-test-volume:/volume_dir"

volumes:
  external-test-volume:
    external: true

externalオプションによってdocker-composeの外で既に作成済みのvolumeを使うことができるようになります。
services > app > volumesで指定するvolume名をexternal-test-volumeに修正しdocker-composeを実行すると、事前に作成したvolumeが有効であることが確認できます。

volumesを複数行で書く

https://zenn.dev/sarisia/articles/0c1db052d09921
こちらの記事でvolumesを複数行に分けて書ける(long syntax)ことを知りました。

version: "3.8"

services:
  app:
    build:
      context: .
      dockerfile: Dockerfile
    volumes:
      - type: bind
        source: ./volumes_test_dir
        target: /volume_dir

typeには、Docker上のvolumeを使う場合はvolumeを、ホストのディレクトリをコンテナにバインドさせる場合はbindを指定します。(他にもtmpfs, npipeアリ)
bindのsourceにはホストのディレクトリを、targetにはコンテナのディレクトリを記述します。
volumeのsourceにはvolume名を、targetにはコンテナのディレクトリを記述します。

単行(short syntax)だと自動でディレクトリを作成され予期せぬエラーが発生してしまうことがあるので、基本的にはlong syntaxで記述しておけば良いようです。

参考

https://amateur-engineer-blog.com/docer-compose-volumes/
https://qiita.com/satodoc/items/188a387f7439e4ec394f

Discussion