docker-compose　volumes定義とは？

# volumes定義とは？

トップレベルエレメントのvolumesについてまとめます。

複数のserviceで共通して使用できる名前付きボリュームを定義できます。

```docker-compose.yml
services:
  backend:
    image: awesome/database
    volumes:
      - db-data:/etc/data

  backup:
    image: backup-service
    volumes:
      - db-data:/var/lib/backup/data

volumes:
  db-data:
```

## オプション

### driver

ボリュームに使用するボリュームドライバーを指定します。
デフォルト値と使用可能な値はプラットフォーム固有です。
ドライバーが利用できない場合、Compose実装はエラーを返し、アプリケーションのデプロイを停止します。

以下で使用できるプラグインの一覧を見ることができます。

[Use Docker Engine plugins | Docker Documentation](https://docs.docker.com/engine/extend/legacy_plugins/#volume-plugins)

localを割り当てている例です。

```docker-compose.yml
volumes:
  db_data:
    driver: local
```
 
`docker volume ls`コマンドを使用して、使っているvolumeの一覧を見ることできます。

また、`docker system info`でデフォルトで使用されているvolumeの確認もできます。

```info.yml
Client:
 Context:    default
 Debug Mode: false
 Plugins:
  buildx: Docker Buildx (Docker Inc., v0.8.1)
  compose: Docker Compose (Docker Inc., v2.3.3)
  scan: Docker Scan (Docker Inc., v0.17.0)

Server:
 Containers: 0
  Running: 0
  Paused: 0
  Stopped: 0
 Images: 3
 Server Version: 20.10.13
 Storage Driver: overlay2
  Backing Filesystem: extfs
  Supports d_type: true
  Native Overlay Diff: true
  userxattr: false
 Logging Driver: json-file
 Cgroup Driver: cgroupfs
 Cgroup Version: 2
 Plugins:
  Volume: local
  Network: bridge host ipvlan macvlan null overlay
  Log: awslogs fluentd gcplogs gelf journald json-file local logentries splunk syslog
 Swarm: inactive
 Runtimes: io.containerd.runc.v2 io.containerd.runtime.v1.linux runc
 Default Runtime: runc
 Init Binary: docker-init
 containerd version: 2a1dxxxxxxxxxxxxxxxxxxxxxxxxxxxx
 runc version: v1.0.3-0-gf46b6ba
 init version: de40ad0
 Security Options:
  seccomp
   Profile: default
  cgroupns
 Kernel Version: 5.10.104-linuxkit
 Operating System: Docker Desktop
 OSType: linux
 Architecture: x86_64
 CPUs: 4
 Total Memory: 7.774GiB
 Name: docker-desktop
 ID: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
 Docker Root Dir: /var/lib/docker
 Debug Mode: false
 HTTP Proxy: http.docker.internal:3128
 HTTPS Proxy: http.docker.internal:3128
 No Proxy: hubproxy.docker.internal
 Registry: https://index.docker.io/v1/
 Labels:
 Experimental: false
 Insecure Registries:
  hubproxy.docker.internal:5000
  127.0.0.0/8
 Live Restore Enabled: false
```

個々のボリュームの詳細情報については以下のコマンドで参照できます。

```sh
❯ docker volume inspect srcs_db_data
[
    {
        "CreatedAt": "2022-03-24T23:58:17Z",
        "Driver": "local",
        "Labels": {
            "com.docker.compose.project": "srcs",
            "com.docker.compose.version": "2.2.3",
            "com.docker.compose.volume": "db_data"
        },
        "Mountpoint": "/var/lib/docker/volumes/srcs_db_data/_data",
        "Name": "srcs_db_data",
        "Options": null,
        "Scope": "local"
    }
]
```

### driver_opts

driver_optsは、ボリュームのドライバーに渡すキーと値のペアとしてオプションのリストを指定します。

```docker-compose.yml
volumes:
  example:
    driver_opts:
      type: "nfs"
      o: "addr=10.40.0.199,nolock,soft,rw"
      device: ":/docker/example"
```

#### volumes定義で使用されるdriver_optsの設定項目について

volumes定義で使用されるdriverのdriver_optsには0個以上のオプションがあります。

例えばデフォルトで設定されているdriverのlocalだと、以下で書かれているようにmountコマンドのオプションと互換があります。

> The built-in local driver on Linux accepts options similar to the linux mount command.
> 参考: [docker volume create | Docker Documentation](https://docs.docker.com/engine/reference/commandline/volume_create/#driver-specific-options)

`docker-compose.yml`を読んでいてわからないオプションが設定されていたら、`man mount`を参照するとわかります。


#### ERROR: create db: missing required option: "type"

typeがないと言われたら、linuxで一般的なext4を指定して試してみましょう。
noneでも良いようです。ここらへん私の理解が浅いので、詳しい方いらっしゃったら教えていただきたいです。

```
volumes:
  db_data:
    driver: local
    driver_opts:
      type: ext4
```

### external

externalは、ボリュームがプラットフォーム上にすでに存在し、そのライフサイクルがアプリケーションのライフサイクルの外部で管理されていることを指定します

```docker-compose.yml
services:
  backend:
    image: awesome/database
    volumes:
      - db-data:/etc/data

volumes:
  db-data:
    external: true
```

### labels

ラベルは、メタデータをボリュームに追加するために使用されます。配列または辞書のいずれかを使用できます。
ラベルが他のソフトウェアで使用されているラベルと競合しないように、逆DNS表記を使用することをお勧めします。

```docker-compose.yml
labels:
  com.example.description: "Database volume"
  com.example.department: "IT/Ops"
  com.example.label-with-empty-value: ""
```

```docker-compose.yml
labels:
  - "com.example.description=Database volume"
  - "com.example.department=IT/Ops"
  - "com.example.label-with-empty-value"
```

### name

nameは、ボリュームのカスタム名を設定します。名前フィールドは、特殊文字を含むボリュームを参照するために使用できます。名前はそのまま使用され、スタック名でスコープされません。

```docker-compse.yml
volumes:
  data:
    name: "my-app-data"
```

また、`external`プロパティと組み合わせて使用​​することもできます。そうすることで、プラットフォームで実際のボリュームを検索するために使用されるボリュームの名前が、作成ファイル内でそれを参照するために使用される名前とは別に設定されます。

```docker-compose.yml
volumes:
  db-data:
    external:
      name: actual-name-of-volume
```

これにより、このルックアップ名を作成ファイルのパラメーターにすることができるため、ボリュームのモデルIDはハードコーディングされますが、プラットフォーム上の実際のボリュームIDは、デプロイメント中の実行時に設定されます。

```docker-compose.yml
volumes:
  db-data:
    external:
      name: ${DATABASE_VOLUME}
```

## 参考

[compose-spec/spec.md at master · compose-spec/compose-spec](https://github.com/compose-spec/compose-spec/blob/master/spec.md#volumes-top-level-element)