Docker swarm неправильно копирует тома на другие рабочие узлы

Я пытаюсь создать приложение Laravel (стек LEMP) в Docker Swarm. Я использую HaProxy, как описано в сетевой документации Dockers для входных сетей, для баланс нагрузки от узлов менеджера общедоступный IPV4 между всеми рабочими узлами.

Моя текущая конфигурация выглядит так:

frontend http_front
   bind *:80
   stats uri /haproxy?stats
   default_backend http_back

frontend http_front_ssl
    bind *:443
    stats uri /haproxy?stats
    default_backend http_back_ssl

backend http_back
   balance roundrobin
   server vps1 xx.xx.xxx.xxx:8080 check
   server vps2 xx.xx.xxx.xxx:8080 check
   server vps3 xx.xx.xxx.xxx:8080 check

backend http_back_ssl
   balance roundrobin
   server vps1 xx.xx.xxx.xxx:4043 check
   server vps2 xx.xx.xxx.xxx:4043 check
   server vps3 xx.xx.xxx.xxx:4043 check

Затем у меня есть собственный образ, который предоставляет и предоставляет PHP-FPM на порту 9000:

docker service create \
--name php-fpm \
--replicas=3 \
--network app-net \
--secret source=proxy.conf,target=/etc/nginx/conf.d/site.conf \
--secret site.key \
--secret site.crt \
--mount type=volume,src=web,dst=/var/www \
jaquarh/php-fpm:alpha

Ключи предназначены для самоподписанного SSL (тестирование HTTPS). Dockerfile для сборки:

FROM php:7.4-fpm
COPY laravel/composer.lock laravel/composer.json /var/www/
WORKDIR /var/www

RUN apt-get update && apt-get install -y \
    build-essential \
    libpng-dev \
    libjpeg62-turbo-dev \
    libfreetype6-dev \
    locales \
    zip \
    jpegoptim optipng pngquant gifsicle \
    vim \
    unzip \
    git \
    curl

RUN apt-get clean && rm -rf /var/lib/apt/lists/*

RUN docker-php-ext-install pdo_mysql
RUN docker-php-ext-configure gd --with-freetype --with-jpeg
RUN docker-php-ext-install gd

RUN pecl install memcached; \
    docker-php-ext-install intl; \
    docker-php-ext-install exif; \
    echo "extension=memcached.so" >> /usr/local/etc/php/conf.d/memcached.ini; \
    docker-php-ext-enable exif;

RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer

RUN groupadd -g 1000 www
RUN useradd -u 1000 -ms /bin/bash -g www www

COPY . /var/www
COPY --chown=www:www . /var/www

USER www

EXPOSE 9000
CMD ["php-fpm"]

Затем я создаю службу nginx в качестве прокси для службы php-fpm.

docker service create \
--name nginx \
--secret site.key \
--secret site.crt \
--secret source=site.conf,target=/etc/nginx/conf.d/site.conf \
-p 8080:80 \
-p 4043:443 \
--replicas=3 \
--network app-net \
--mount type=volume,src=web,dst=/var/www \
nginx:latest \
sh -c "exec nginx -g 'daemon off;'"

Внутри моего тома web я храню все файлы laravel. На данный момент я только тестирую Http, поэтому моя конфигурация nginx выглядит так:

server {
    listen 80;
    listen [::]:80;
    server_name example.co.uk; # this is my actual domain for testing

    index index.php index.html;

    error_log /var/log/nginx/error.log;
    access_log /var/log/nginx/access.log;

    root /var/www/public;

    add_header X-Frame-Options "SAMEORIGIN";
    add_header X-XSS-Protection "1; mode=block";
    add_header X-Content-Type-Options "nosniff";

    charset utf-8;
    
    location / {
        try_files $uri $uri/ /index.php?$query_string;
        gzip_static on;
    }

   location = /favicon.ico {
        access_log off;
        log_not_found off;
    }

    location = /robots.txt {
       access_log off;
        log_not_found off;
   }

    error_page 404 /index.php;

   location ~ \.php$ {
        try_files $uri =404;
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        fastcgi_pass php-fpm:9000;
        fastcgi_index index.php;
       fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
        fastcgi_param PATH_INFO $fastcgi_path_info;
       include fastcgi_params;
    }

    # ready for when letsencrypt is introduced
    location ~ /.well-known/acme-challenge {
       allow all;
       root /var/www/html;
    }
}

Наконец, у меня есть предварительно созданный объем базы данных SQL и служба, готовая к использованию, которую использует laravel .env.

docker service create \
--name mysql \
--replicas=3 \
--network app-net \
--secret site.key \
--secret site.crt \
--mount type=volume,src=dbdata,target=/var/lib/mysql/ \
--env MYSQL_DATABASE=xxxxxx \
--env MYSQL_ROOT_PASSWORD=xxxxxx \
--env MYSQL_USER=xxxxx \
--env MYSQL_PASSWORD=xxxxx \
-p 3306:3306 \
mysql:latest

Проблема, с которой я столкнулся, заключается в том, что VPS1 (в данном случае менеджер) отлично получает эти файлы, потому что тома существуют в менеджере VPS. И VPS2, и VPS3 показывают, что эти тома смонтированы правильно, но данные не копируются.

Смонтировать

Другой

Как видно на изображениях, на моем компьютере для разработки (который также является рабочим для тестирования) я вижу, что монтирование было успешно создано, и моему докеру назначен контейнер nginx, однако, когда я проверяю каталоги в bash, только корпус каталога приложение laravel существует в узле менеджера.

Что я делаю не так? Как я могу скопировать этот том на свои рабочие узлы? Если я проверю объем в диспетчере, это будет выглядеть так:

ubuntu@vps-438f3f94:~$ docker volume inspect web
[
    {
        "CreatedAt": "2021-04-23T09:29:23Z",
        "Driver": "local",
        "Labels": {},
        "Mountpoint": "/var/lib/docker/volumes/web/_data",
        "Name": "web",
        "Options": {},
        "Scope": "local"
    }
]

Обновление: если я посмотрю на статистику HaProxy, то увижу, что мой компьютер для разработки DOWN, потому что у меня нет переадресации портов (так как я просто отлаживаю контейнеры), но я предполагаю, что это не имеет реальное влияние на объемы, но только для того, чтобы дать вам лучшее представление о моей среде.

http_back   
Queue   Session rate    Sessions    Bytes   Denied  Errors  Warnings    Server
Cur Max Limit   Cur Max Limit   Cur Max Limit   Total   LbTot   Last    In  Out Req Resp    Req Conn    Resp    Retr    Redis   Status  LastChk Wght    Act Bck Chk Dwn Dwntme  Thrtle
vps1    0   0   -   0   3       0
1   -   38
38  25m15s  14191   23441       0       0   0   0   0   25m30s UP   L4OK in 0ms 1   Y   -   28  10  0s  -
vps2    0   0   -   0   1       0
1   -   30
30  25m6s   10055   16896       0       0   0   0   0   25m28s UP   L4OK in 0ms 1   Y   -   30  10  0s  -
vps3    0   0   -   0   0       0
0   -   0
0   ?   0   0       0       0   0   0   0   13h5m DOWN  * L4TOUT in 2001ms  1   Y   -   1   1   13h5m   -
Backend 0   0       0   8       0   1   26212   121
68  25m6s   43399   52050
0   0       53  0   0   0   25m30s UP       2   2   0       9   2h20m   

person Jaquarh    schedule 23.04.2021    source источник
comment
docker тома являются локальными для узла, на котором они созданы, они не используются совместно и не синхронизируются между docker swarm узлами. Вы можете создать резервную копию docker volume (ов) с помощью сетевой файловой системы, которую можно смонтировать в RW на нескольких узлах.   -  person masseyb    schedule 23.04.2021
comment
Спасибо за эту полезную информацию и с предоставленной ссылкой, я могу изучить сеть тома. Будет ли это сделано с использованием общедоступного IPV4 на узле менеджера? Я также не использую docker-compose, так что здесь что-то меняется? Я вижу на моем vp2, что это действительно так, и тома не передаются @masseyb   -  person Jaquarh    schedule 23.04.2021
comment
Вам нужен где-то сервер NFS, не рекомендуется размещать его в глобальной сети. Для разработки вы можете запустить сервер NFS в докере, например. вы должны создать том и смонтировать его в контейнер сервера NFS, а затем создать docker volume(s), поддерживаемые службой NFS. В зависимости от того, где вы выполняете развертывание для производства, AWS предоставляет EFS, GCP предоставляет хранилище файлов и т. д.   -  person masseyb    schedule 23.04.2021
comment
Итак, моя инфраструктура неверна для данного вопроса, и мне нужно настроить подход NAS к томам. Из поиска в Google я вижу, что это означает, что обновления для разработки проще, потому что сервер NSF будет контролировать любые изменения, связанные с кодом, поэтому только тогда потребуется перезапустить контейнеры для обновлений @masseyb.   -  person Jaquarh    schedule 23.04.2021
comment
Правильно - да, звучит примерно правильно, если только laravel не перезагружается автоматически при изменениях, тогда вам, вероятно, нужно будет отбрасывать контейнеры, не уверен, если честно, я не использую Laravel, просто рой / kubernetes с томами, разделенными между контейнерами, работающими на разные узлы.   -  person masseyb    schedule 23.04.2021
comment
Я новичок в контейнерных приложениях, не говоря уже о кластерах, но мне нравится узнавать новое. Вы кажетесь исключительно хорошо осведомленным в этой области - возможно, мы могли бы сотрудничать? Расширьте обе стороны цикла DevOps. Я создал чат с SO, было бы здорово поговорить дальше. @masseyb   -  person Jaquarh    schedule 23.04.2021