Как повторно разделить тома между контейнерами Docker-в-Docker?

#docker #docker-compose #docker-in-docker

Вопрос:

Я подключил том shared к своему сервису main . Теперь я пытаюсь подключить тот же том к другому контейнеру client , который запускается docker-compose up client изнутри main контейнера (Докер в докере).:

 version: "3.8"

# set COMPOSE_PROJECT_NAME=default before running `docker-compose up main`

services:
  main:
    image: rbird/docker-compose:python-3.9-slim-buster
    privileged: true
    entrypoint: docker-compose up client # start client
    volumes:
      - //var/run/docker.sock:/var/run/docker.sock
      - ./docker-compose.yml:/docker-compose.yml
      - ./shared:/shared

  client:
    image: alpine
    entrypoint: sh -c "ls shared*"
    profiles:
      - do-not-run-directly
    volumes:
      - /shared:/shared1
      - ./shared:/shared2
 

Результат, который я получаю, таков:

 [ ] Running 2/2
 - Network test_default   Created                                                                                                                                                                                       0.0s
 - Container test_main_1  Started                                                                                                                                                                                       0.9s
Attaching to main_1
Recreating default_client_1 ... done
Attaching to default_client_1
main_1  | client_1  | shared1:
main_1  | client_1  |
main_1  | client_1  | shared2:
main_1  | default_client_1 exited with code 0
main_1 exited with code 0
 

Поэтому папки /shared2 и /shared2 пусты, хотя они содержат файлы как в каталоге хоста, так и в main контейнере.

Как повторно разделить объемы между контейнерами?

Или есть способ разделить каталог хоста между всеми контейнерами, даже теми, которые запущены одним из контейнеров?

Ответ №1:

Самый чистый ответ здесь-удалить main: контейнер и profiles: блок для client: контейнера и запустить docker-compose непосредственно на хосте.


В приведенной здесь настройке используется сокет Docker хоста. (Это не «Докер в докере»; эта настройка, как правило, является еще более запутанным случаем запуска второго демона Докера в контейнере.) Это означает, что экземпляр Docker Compose внутри контейнера отправляет инструкции демону Docker хоста, указывая ему, какие контейнеры запускать. Вы монтируете docker-compose.yml файл в корневом каталоге контейнера, поэтому ./shared путь / также интерпретируется относительно.

Это означает, что демон Docker хоста получает запрос на создание контейнера с /shared подключением /shared1 внутри нового контейнера, а также с /shared подключением ( ./shared относительно пути / ) /shared2 . Демон Docker хоста создает этот контейнер, используя пути хоста. Если вы посмотрите на свою хост-систему, вы, вероятно, увидите пустой /shared каталог в корневой папке файловой системы хоста, и если вы создадите там файлы, они появятся в новых контейнерах /shared1 и /shared2 каталогах.

В общем случае нет способа подключить файловую систему одного контейнера к другой. Если вы пытаетесь запустить docker (или docker-compose ) из контейнера, вам необходимо иметь внешние знания о том, какие из ваших собственных файловых систем монтируются и что именно было смонтировано.


Если вы можете, избегайте как подходов к контейнерам, запускающим другие контейнеры, так и совместного использования объемов между контейнерами. Если можно запустить другой контейнер, и этот другой контейнер может монтировать произвольные части файловой системы хоста, то вы можете довольно просто запустить весь хост. В дополнение к проблемам безопасности, сложности пути, которые вы здесь отмечаете, трудно обойти. Общий доступ к томам плохо работает в средах, отличных от докеров (например, в Kubernetes трудно получить том для чтения и записи, и контейнеры, как правило, не будут находиться на одном хосте друг с другом), и существуют сложности с разрешениями и наличием нескольких читателей и авторов для одних и тех же файлов.

Вместо этого запускайте docker и docker-compose выполняйте команды только на хосте (как привилегированный пользователь в системе, не являющейся разработчиком). Если одному контейнеру требуется односторонняя публикация содержимого, доступного только для чтения, в другой контейнер, например в статические ресурсы, создайте пользовательское изображение COPY --from= , одно изображение в другое. В противном случае рассмотрите возможность использования специального сетевого хранилища (например, базы данных), которое специально не зависит от файловой системы и знает, как обрабатывать параллельный доступ.