Как сохранить файлы тома контейнера Docker?

Я хотел бы поделиться каталогом ~/mydir с хостом, но не заменять каталог контейнера Docker файлами хоста. Итак, у меня docker-compose.yml

version: '2'
services:
  app:
    container_name: mono
    build: .
    volumes:
      # save .composer files on host to keep cache warmed up
      - '/srv/mono/mydir:/root/mydir'
    command: sleep infinity

И Dockerfile

#/bin/bash
FROM php:5.6

RUN mkdir /root/mydir && echo '{}' > /root/mydir/myfile.json

VOLUME /root/mydir

Каталог /srv/mono/mydir пуст. Он был заменен на каталог хоста. Ясно.

Но как сохранить оригинальные файлы?

Например, это работает для контейнеров MySQL Percona:

version: '2'
services:
  percona-56:
    container_name: percona-56
    image: percona/percona-server:5.6
    volumes:
    - /srv/mysql/percona-56:/var/lib/mysql
    environment:
      MYSQL_ALLOW_EMPTY_PASSWORD: 'yes'

Исходные файлы из контейнера:

$ ll /srv/mysql/percona-56
total 176220
    auto.cnf
    error.log
    ibdata1
    ib_logfile0
    ib_logfile1
    init.ok
    mysql
    performance_schema

Я пытался проверить Percona Dockerfile, но не нашел что-то связанное с разделением томов.

$ docker --version
Docker version 1.12.3, build 6b644ec

person Kirby    schedule 08.11.2016    source источник


Ответы (1)


Когда вы добавляете VOLUME при запуске докера, вы говорите, что нужно использовать файловую систему основного хоста вместо файловой системы копирования при записи, которую Docker использует для изображений. Здесь есть два основных варианта:

  1. Вы привязываете-монтируете фактическое расположение файловой системы к образу. Это то, что вы здесь делаете.
  2. Вы позволяете Docker обрабатывать местоположение ... в этом случае Docker создает местоположение в основной файловой системе, а затем копирует содержимое образа в это место, чтобы начать работу.

Вы хотите получить и то, и другое - вам нужно фиксированное место в вашей файловой системе, но вы хотите, чтобы там были файлы из вашего образа. Теперь есть причина, по которой это не работает! Что произойдет, если auto.conf уже существует в этой папке и вы запустите свой контейнер? Что произойдет, если вы запустите два контейнера с разными версиями этого файла, указанными в одном месте? Вот почему, если вы выбираете реальное местоположение, он не пытается угадать, что делать с конфликтами между изображением и файловой системой, он просто связан с файловой системой.

Вы МОЖЕТЕ добиться того, чего хотите. На самом деле есть два варианта. Лучше, если ваше приложение будет читать из двух отдельных папок: одна находится внутри изображения, а вторая - в вашей файловой системе. Это полностью позволяет избежать этой проблемы;) Второй вариант - указать Docker, как обрабатывать отдельные файлы в вашем образе.

version: '2'
services:
  app:
    container_name: mono
    build: .
    volumes:
      # save .composer files on host to keep cache warmed up
      - '/srv/mono/mydir:/root/mydir'
      # Marking a volume this way will tell Docker to use THIS file 
      # from the image, even though the parent directory is a regular
      # volume.  If you have an auto.cnf file in your directory, it
      # will be ignored. 
      - /root/mydir/auto.cnf
    command: sleep infinity

......

person Paul Becotte    schedule 08.11.2016
comment
Это просто .... нигде не задокументировано? Я не вижу этого в документах v2 или v3, если я не слепой. Может, это просто стандартный синтаксис докеров? - person infogulch; 25.04.2018
comment
Я получаю Cannot create container for service SERVICE: cannot mount volume over existing file, file exists CONTAINER_FILE_PATH, этот метод еще работает или только для версии 2? У меня 3,5. - person Ixio; 29.01.2020
comment
docker-compose просто переводит yaml в команды докеров, ничего особенного. Если он работает в докере, он работает в compose. Что касается вашего вопроса, просто чтобы убедиться, что я очень быстро запустил docker run -it --rm -v pwd/conf/server.conf:/etc/nginx/nginx.conf nginx, и, как и ожидалось, он смонтировал этот файл поверх файла конфигурации nginx. Если не работает, вам следует открыть новый вопрос. - person Paul Becotte; 29.01.2020