#docker #docker-compose #volumes
#docker #docker-compose #тома
Вопрос:
Я хочу разделить объем между 2 файлами docker-compose. Есть 2 взаимосвязанных приложения, и мне нужно создать символическую ссылку между ними. Я попытался использовать именованные тома и внешнюю функцию.
В первом контейнере я вижу содержимое папки /var/www / s1, но папка /var/www / s2 пуста, в то время как во втором контейнере я вижу содержимое папки /var/www / s2, но /var/www/s1папка кажется пустой. Поскольку я не могу видеть содержимое папки, созданной другим приложением в /var/www, я не могу создать символическую ссылку.
Я создал несколько фиктивных файлов docker-compose, чтобы попытаться проще раскрыть проблему.
В /var/www/s1 должен быть «magazine.txt » файл, в то время как в /var/www/s2 должен быть «paper.txt «досье.
Первый файл docker-compose выглядит следующим образом:
services:
nginx:
image: nginx
container_name: nginx
volumes:
- ../:/var/www/s1
- shared-s:/var/www
volumes:
shared-s:
name: shared-s
Второй файл docker-compose выглядит следующим образом:
version: '3.8'
services:
php:
image: php
container_name: php
command: tail -F /var/www/s2/paper.txt
volumes:
- ../:/var/www/s2
- shared-s:/var/www
volumes:
shared-s:
external:
name: shared-s
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
80b83a60a0e5 php "docker-php-entrypoi…" 2 seconds ago Up 1 second php
05addf1fc24e nginx "/docker-entrypoint.…" 9 seconds ago Up 8 seconds 80/tcp nginx
8c596d21cf7b portainer/portainer "/portainer" 2 hours ago Up About a minute 9000/tcp, 0.0.0.0:9001->9001/tcp portainer
$ docker exec -it 05addf1fc24e sh
# cd /var/www
# ls
s1 s2
# cd s1
# ls
docker magazine.txt
# cd ..
# cd s2
# ls
# exit
$ docker exec -it 80b83a60a0e5 sh
# cd /var/www
# ls
s1 s2
# cd s1
# ls
# cd ..
# cd s2
# ls
docker paper.txt
# exit
Ответ №1:
На механическом уровне тома и привязки монтируются не так, как вы предлагаете. Именованный том shared-s
будет содержать только пустые каталоги s1
и s2
, но не содержимое ни из одного из каталогов хоста.
Что происходит, это что-то вроде этого:
- Docker сначала запускает (скажем)
nginx
контейнер. Он сортируетvolumes:
монтируемые файлы в этом контейнере от кратчайшего к самому длинному. - Поскольку
shared-s
том пуст, содержимое изnginx
базового образа/var/www
копируется на том; затем том монтируется/var/www
в контейнер. - Docker создает точку монтирования
/var/www/s1
(в томе), затем привязывает к ней каталог хоста (вообще не изменяя том). - Docker запускает
php
контейнер и сортирует егоvolumes:
. - Поскольку
shared-s
том не является пустым, Docker просто монтирует его в контейнер, скрывая все содержимое, которое могло быть/var/www
в изображении. - Docker создает точку монтирования
/var/www/s2
(в томе), затем привязывает к ней каталог хоста (вообще не изменяя том).
Вы заметите пару проблем с этой последовательностью. Содержимое других подключенных томов никогда не копируется в «общий» том, что нарушает общий доступ к файлам, который вы пытаетесь использовать здесь. Какой бы контейнер ни запускался первым, содержимое из его образа копирует в общий том, и все, что содержится в этом изображении в другом контейнере, теряется. Если на то пошло, если в базовом образе есть обновление, Docker проигнорирует это в пользу (старого) содержимого, находящегося в общем томе.
Я бы посоветовал полностью избегать томов здесь. Создайте отдельный образ для каждого контейнера, COPY
вставив в него код вашего приложения. Если вы можете использовать статический файловый сервер во внутреннем приложении, это будет намного проще, чем пытаться копировать файлы из одного контейнера в другой. Если этого невозможно избежать, вы можете использовать COPY --from=image
синтаксис, который обычно используется при многоэтапных сборках, чтобы также копировать содержимое из одного созданного образа в другой.