Как правильно объявлять Volum-ы в длинном синтаксисе Docker-а?

Пример из документации:

version: "3.8"
services:
  web:
    image: nginx:alpine
    ports:
      - "80:80"
    volumes:
      - type: volume
        source: mydata
        target: /data
        volume:
          nocopy: true
      - type: bind
        source: ./static
        target: /opt/app/static

networks:
  webnet:

volumes:
  mydata:

Последние 4 строки издевательски (для новичков) опущены. Для меня, новичка в Docker на момент этого вопроса, неочевидно, чем надо заполнить это пустое значение. Если же опустить volumes целиком, то будет ошибка:

Named volume XXX is used in service "YYY" but no declaration was found in the volumes section.

Если там должно быть что-то вроде:

volumes:
 - /var/lib/mysql
 - /opt/data:/var/lib/mysql

то тоже возникает непонятный момент: вроде как должен быть использоваться ЛИБО длинный синтаксис, ЛИБО короткий, но если выше приведённое валидно, то получается что длинный синтаксис может использоваться только ВМЕСТЕ с коротким?

version: "3.8"
services:
  web:
    image: nginx:alpine
    ports:
      - "80:80"
    volumes:
      - type: volume
        source: mydata
        target: /data
        volume:
          nocopy: true
      - type: bind
        source: ./static
        target: /opt/app/static

networks:
  webnet: # Угадай что!

volumes:
  mydata:
   - /var/lib/mysql
   - /opt/data:/var/lib/mysql

Ответы (1 шт):

Автор решения: Exploding Kitten

Существует несколько типов volume:

  • bind это обычное монтирование ("проброс") папки из хост машины в контейнер.
  • volume это именованная папка, которая монтируется в контейнер (возможно проще воспринимать как некий виртуальный диск, хотя по факту, это все же обычная папка, только которая находится в /var/lib/docker/volumes).

Также как вы и указали есть "короткий" и "длинный" синтаксис монтирования. Их можно использовать независимо друг от друга, просто длинный позволяет настроить больше параметром, но если они не нужны, то короткий просто удобнее. Например, это вполне валидный синтаксис:

volumes:
  - type: volume
    source: mydata
    target: /data
    volume:
      nocopy: true
  - ./static:/opt/app/static
  # это равно:
  # - type: bind
  #   source: ./static
  #   target: /opt/app/static

В первом случае монтируется именованный volume, во втором происходит bind папки из проекта.

Также существует два место объявления volumes на уровне сервиса (контейнера) и на верхнем уровне. Это необходимо для того, чтобы была возможность использовать один volume в нескольких сервисах. Например, в вашем примере, на верхнем уровне создается "общий" volume с именем mydata:

volumes:
  mydata:

а уже на уровне конкретного сервиса web он используется:

volumes:
  - type: volume
    source: mydata
    target: /data

Т.е. этот volume монтируется в папку data внутри контейнера, но также внутри другого сервиса вы можете его примонтировать ещё раз.

Последние 4 строки издевательски (для новичков) опущены. Для меня, новичка в Docker на момент этого вопроса, неочевидно, чем надо заполнить это пустое значение.

Это валидный синтаксис создания сети и volume после двоеточия (:) можно ничего не писать, оно будет работать.

Если же опустить volumes целиком, то будет ошибка:

Да, это происходит из-за того, что вы используете именованный volume, который нигде не объявлен, собственно ошибка про это и говорит.

А вот это код уже не валиден:

volumes:
  mydata:
   - /var/lib/mysql
   - /opt/data:/var/lib/mysql

Т.к. после имени mydata: ожидаются настройки для этого volume, которые можно найти тут.

→ Ссылка