docker-compose не фиксирует изменения файловой системы в общем томе - PullRequest
0 голосов
/ 12 декабря 2018

Добрый день всем.

Моя задача здесь - использовать некоторый объем, который будет разделен между несколькими службами.Этот том будет заполнен командой ADD или COPY в определенном сервисном Dockerfile.Проблема, с которой я столкнулся, заключается в том, что том не обновляется при запуске служб через docker-compose up.

. Рассмотрим следующую настройку:

# docker-compose.yml
version: "3"

services:
  service-a:
    build:
      context: service-a
      dockerfile: Dockerfile
    volumes:
      - shared:/test/dir

  service-b:
    build:
      context: service-b
      dockerfile: Dockerfile
    volumes:
      - shared:/another-test/dir

volumes:
  shared:

# ./service-a/Dockerfile
FROM alpine:3.8
COPY test-dir /test/dir
CMD [ "tail", "-f", "/dev/null" ]

# ./service-b/Dockerfile
FROM alpine:3.8
CMD [ "tail", "-f", "/dev/null" ]

И мы создадим папку ./service-a/test-dir.Теперь давайте создадим его:

> docker-compose build
Building service-a
Step 1/3 : FROM alpine:3.8
 ---> 196d12cf6ab1
Step 2/3 : COPY test-dir /test/dir
 ---> ac66ed92b442
Step 3/3 : CMD [ "tail", "-f", "/dev/null" ]
 ---> Running in 932eb32b6184
Removing intermediate container 932eb32b6184
 ---> 7e0385d17f96
Successfully built 7e0385d17f96
Successfully tagged docker-compose-test_service-a:latest
Building service-b
Step 1/2 : FROM alpine:3.8
 ---> 196d12cf6ab1
Step 2/2 : CMD [ "tail", "-f", "/dev/null" ]
 ---> Running in 59a8b91c6b2d
Removing intermediate container 59a8b91c6b2d
 ---> 4e2c16ea5a80
Successfully built 4e2c16ea5a80
Successfully tagged docker-compose-test_service-b:latest

И запустим службы:

> docker-compose up --no-build -d
Creating network "docker-compose-test_default" with the default driver
Creating volume "docker-compose-test_shared" with default driver
Creating docker-compose-test_service-a_1 ... done
Creating docker-compose-test_service-b_1 ... done

Давайте проверим сопоставленные каталоги:

> docker-compose exec service-a ls -lah /test/dir
total 8
drwxr-xr-x    2 root     root        4.0K Dec 12 06:14 .
drwxr-xr-x    3 root     root        4.0K Dec 12 06:14 ..
> docker-compose exec service-b ls -lah /another-test/dir
total 8
drwxr-xr-x    2 root     root        4.0K Dec 12 06:14 .
drwxr-xr-x    3 root     root        4.0K Dec 12 06:14 ..

Теперь давайте поместим несколько текстовых файлов в ./service-a/test-dir на хост-машине и выполните сборку:

> docker-compose build
Building service-a
Step 1/3 : FROM alpine:3.8
 ---> 196d12cf6ab1
Step 2/3 : COPY test-dir /test/dir
 ---> bd168b0fc8cc
Step 3/3 : CMD [ "tail", "-f", "/dev/null" ]
 ---> Running in 6e81b32243e1
Removing intermediate container 6e81b32243e1
 ---> cc28fc6de9ac
Successfully built cc28fc6de9ac
Successfully tagged docker-compose-test_service-a:latest
Building service-b
Step 1/2 : FROM alpine:3.8
 ---> 196d12cf6ab1
Step 2/2 : CMD [ "tail", "-f", "/dev/null" ]
 ---> Using cache
 ---> 4e2c16ea5a80
Successfully built 4e2c16ea5a80
Successfully tagged docker-compose-test_service-b:latest

Как вы можете видеть, кеш не используется на шаге COPY в service-a, что означает, что изменения запекаются в образе.Теперь давайте запустим службы:

> docker-compose up --no-build -d
Recreating docker-compose-test_service-a_1 ...
Recreating docker-compose-test_service-a_1 ... done

Еще раз service-b остается без изменений, только service-a воссоздается.Давайте проверим фактические сервисы ( здесь возникает проблема ):

> docker-compose exec service-a ls -lah /test/dir
total 8
drwxr-xr-x    2 root     root        4.0K Dec 12 06:17 .
drwxr-xr-x    3 root     root        4.0K Dec 12 06:20 ..
> docker-compose exec service-b ls -lah /another-test/dir
total 8
drwxr-xr-x    2 root     root        4.0K Dec 12 06:17 .
drwxr-xr-x    3 root     root        4.0K Dec 12 06:14 ..

Таким образом, файлы не отображаются ... Однако, если мы запустим временный контейнер на основе service-a изображения, оно покажетправильный список:

> docker run --rm docker-compose-test_service-a ls -lah /test/dir
total 8
drwxr-xr-x    2 root     root        4.0K Dec 12 06:20 .
drwxr-xr-x    3 root     root        4.0K Dec 12 06:20 ..
-rwxr-xr-x    1 root     root           0 Dec 12 06:20 rrrrrr.txt
-rwxr-xr-x    1 root     root           0 Dec 12 06:16 test.txt

Есть идеи для обхода этого?Пока кажется, что помогает только полное отключение через docker-compose down с уничтожением тома.Не самое лучшее решение, хотя, как и в реальном проекте, это приведет к серьезным простоям.

Я надеюсь, что конфигурация читаема, но я могу поместить ее в маленькое git-репо, возможно, при необходимости.

Заранее спасибо.

1 Ответ

0 голосов
/ 12 декабря 2018

Докер будет только автоматически заполнять том, когда он первый создан .В описываемом вами рабочем процессе, когда вы удаляете и воссоздаете «первый» контейнер с его новым изображением, вам также необходимо удалить и воссоздать том, что, вероятно, означает удаление и воссоздание всего стека.

СуществуетСуществует несколько способов решения этой проблемы:

  1. Перестройте архитектуру приложения, чтобы не нужно было обмениваться файлами.(Очевидно, это большая часть работы.) Если есть какое-то полустатическое содержимое, вам может понадобиться «вставить их» в поглощающее изображение или настроить две части вашей системы для связи через HTTP.(Подобный обмен данными между контейнерами не является чем-то отличным для Docker, и он становится хуже, когда вы начинаете смотреть на решения с несколькими хостами, такие как Swarm или Kubernetes.)

  2. Если естьучаствуют только две части, создайте одно изображение, которое запускает два процесса.Я видел другие вопросы SO, которые делают это для компонента PHP-FPM, который обслуживает динамический контент, плюс сервер nginx, который обслуживает статический контент и направляет некоторые запросы в PHP-FPM, но где весь статический и динамический контент является «частьюприложение "и точка входа HTTP-via-nginx - это" единственная точка входа в контейнер ". supervisord - это де-факто процесс управления по умолчанию, когда это необходимо.

  3. Внутри «производящего» контейнера напишите некоторый код времени запускакоторый копирует данные из чего-либо на изображении в общую папку данных

    #!/bin/sh
    # Run me as the image's ENTRYPOINT.
    if [ -d /data ]; then
      cp -r /app/static /data
    done
    exec "$@"
    

    Это будет заполнять том данных при при каждом запуске.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...