Почему docker в контейнерах docker (dind) монтирует тома с путем к хосту?

У меня есть настройки с Docker в Docker и попробуйте смонтировать папки.

Допустим, у меня есть те папки, которыми я хочу поделиться со своим родителем. На хосте я создал файл в /tmp/dind с именем foo, Хост запускает контейнер 1, который запускает контейнер 2. Это результат, который я хочу получить.

Host      | Container 1 | Container 2

/tmp/dind |  /tmp/dind2 | /tmp/dind3
      <------->     <------->

Вместо этого я получаю

Host      | Container 1 | Container 2

/tmp/dind |  /tmp/dind2 | /tmp/dind3
      <------->
      <----------------------->

Код здесь:

docker run --rm -it \
  -v /tmp/dind:/tmp/dind2 \
  -v /var/run/docker.sock:/var/run/docker.sock docker sh -c \
    "docker run --rm -it \
      -v /tmp/dind2:/tmp/dind3 \
      -v /var/run/docker.sock:/var/run/docker.sock \
      docker ls /tmp/dind3"

Это ничего не выводит, а следующая команда выдает foo как результат. Я изменил установленный объем:

docker run --rm -it \
  -v /tmp/dind:/tmp/dind2 \
  -v /var/run/docker.sock:/var/run/docker.sock docker sh -c \
    "docker run --rm -it \
      -v /tmp/dind:/tmp/dind3 \
      -v /var/run/docker.sock:/var/run/docker.sock \
      docker ls /tmp/dind3"

Вопрос в том, что мне нужно сделать, чтобы использовать путь к контейнеру 1, а не хост? Или я что-то не так понимаю в докере?

2 ответа

Несмотря на то, что вы говорите "Docker-in-Docker" и "dind", эта настройка на самом деле не Docker-in-Docker: ваш container1 дает инструкции демону Docker хоста, который влияет на container2.

Host      Container1
    /-----
 (Docker)
    |     Container2
    \---->

(Примечание: обычно это рекомендуемый путь для установок типа CI. "Docker-in-Docker" обычно означает, что container1 запускает свой собственный отдельный демон Docker, который обычно не рекомендуется.)

Так как container1 дает инструкции Docker хоста, а Docker хоста запускает container2, любой docker run -v пути всегда являются путями хоста. Если вы не знаете, что какой-то конкретный каталог уже смонтирован в вашем контейнере, сложно обмениваться файлами с "субконтейнерами".

Один из способов обойти это - утверждать, что существует какой-то общий путь:

docker run \
  -v $PWD/exchange:/exchange \
  -v /var/run/docker.sock:/var/run/docker.sock \
  -e EXCHANGE_PATH=$PWD/exchange \
  --name container1
  ...

# from within container1
mkdir $EXCHANGE_PATH/container2
echo hello world > $EXCHANGE_PATH/container2/file.txt
docker run \
  -v $EXCHANGE_PATH/container2:/data
  --name container2
  ...

Когда я делал это в прошлом (для тестовой установки, которая хотела запускать вспомогательные контейнеры), я использовал кропотливую работу docker create, docker cp, docker start, docker cp, Docker rm последовательность. Это очень удобно, но имеет то преимущество, что "местная" сторона docker cp всегда является текущим контекстом файловой системы, даже если вы разговариваете с демоном Docker хоста из контейнера.

Не имеет значения, связывает ли контейнер 2 путь хоста, потому что изменения в файлах в контейнере 1 напрямую влияют на все пути хоста. Таким образом, они все работают над одними и теми же файлами.

Таким образом, ваши настройки верны и будут функционировать так же, как если бы они ссылались так, как вы описали.

Обновить
Если вы хотите убедиться, что процесс не изменяет файлы хоста, вы можете сделать следующее:

Создание пользовательских образов Docker, которые копируют все данные из папки a в папку bгде вы выполняете скрипт на папке b, А затем смонтировать файлы с ./:/a, Таким образом вы сохраняете гибкость в отношении файлов, которые вы привязываете к контейнеру, не позволяя контейнеру изменять файлы хоста.

Надеюсь, это ответит на ваш вопрос:)

Другие вопросы по тегам