Совместное использование папки между контейнерами Docker с предварительно скомпилированными файлами

#laravel #docker #npm #docker-compose #composer-php

#laravel #docker #npm #docker-создать #композитор-php

Вопрос:

Я использую Github Actions для создания контейнера Docker на php-fpm с Laravel, и предварительно скомпилированные файлы Docker составляют в нем файлы. Файлы CSS и JS создаются с помощью npm. Этот контейнер Docker затем помещается в мою учетную запись Docker.

Я хочу проверить этот контейнер и позволить ему запускаться с помощью Docker-Compose, а контейнер nginx запускается с этой конфигурацией:

 server {
    listen 80;
    index index.php index.html;
    error_log  /var/log/nginx/error.log;
    access_log /var/log/nginx/access.log;
    root /var/www/public;
    location ~ .php$ {
        try_files $uri =404;
        fastcgi_split_path_info ^(. .php)(/. )$;
        fastcgi_pass app:9000;
        fastcgi_index index.php;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_param PATH_INFO $fastcgi_path_info;
    }
    location / {
        try_files $uri $uri/ /index.php?$query_string;
        gzip_static on;
    }
}
  

Итак, часть PHP работает отлично, но часть CSS и JS не работает, потому что в контейнере приложения есть эти файлы. Как я могу скопировать, поделиться или что-то еще между этими двумя контейнерами?

Вы не можете поместить том с хоста, потому что том будет содержать только то, что находится на хосте, а не то, что находится в контейнере… это должно быть в другом направлении.

Комментарии:

1. Проблема в том, что я хочу нетронутую среду в хост-системе. Изображение из Docker создается в Github Actions, а затем передается в мою учетную запись Docker. Я не хочу иметь контекст сборки в моей операционной системе.

Ответ №1:

Вы должны использовать именованный том, который идеально соответствует вашим потребностям

 volumes:
  assets:

services:
  nginx:
    ...
    volumes:
      - assets:/var/www/public/:ro

  app:
    ...
    volumes:
      - assets:/your/npm/output/folder
  

Ваши файлы JS / CSS будут надлежащим образом распределены между вашими двумя контейнерами

Ответ №2:

Вы должны определить том docker во встроенной программе docker, затем установить свои предварительно скомпилированные файлы и после этого смонтировать этот именованный том в обеих системах.

Проблема в том, что вы пытаетесь смонтировать что-то, что уже находится в образе docker, а не в томе docker. Во время выполнения docker это невозможно сделать. Это не философия.

Таким образом, вы делаете (неправильно):

  1. Создайте docker build образ1 с предварительно скомпилированными файлами в /your_dir
  2. Как вы правильно сказали, вы не можете смонтировать со своего хоста каталог на docker-image1:/your_dir , потому что это переопределило бы его.
  3. Не существует элегантного способа доступа из docker-image2 в docker-image1.

Хорошая практика:

  1. Создайте том С ИМЕНЕМ docker, например, под названием myvolume.
  2. Создайте docker build образ1, который сохранит ваш предварительно скомпилированный файл в myvolume
  3. Создайте контейнер docker run -t image1... yourCssDocker, монтирующий myvolume
  4. Создайте контейнер docker run -t image2... yourNginxDocker, смонтировав myvolume

Вот как следует поступить. Обратите внимание, что вы должны обращаться к myvolume по его имени, а не по тому привязки (путь к хосту).

Вы можете выполнить все шаги (4 из хорошей практики), используя всего 1 файл docker-compose.yml (используя css-precomp в качестве имени тома docker)

 volumes:
  css-precomp:

services:
  my-service:
    build:
      - context: .
      - dockerfile: Dockerfile
    volumes:
      - css-precomp:/your_dir
    ...
  

Наконец, вы можете проверить, правильно ли сгенерированы ваши данные после сборки в Dockerfile, проверив /var/lib/docker/volumes/css-precomp/_data

Ответ №3:

Инструкция Dockerfile COPY позволяет копировать файлы из одного изображения в другое. Если вы уже создали образ своего PHP-приложения, вы можете создать образ nginx со статическими файлами из него, например:

 FROM nginx:latest
COPY --from=my/php-app /usr/src/app /usr/share/nginx/html
COPY nginx.conf /etc/nginx
  

Теперь у вас будет два автономных изображения. Если содержимое в изображении PHP изменится, вы можете перестроить изображение nginx, чтобы получить там обновленное содержимое. (Если вы используете именованные тома, как предполагают другие вопросы, вам придется вручную удалять тома, содержащие статические ресурсы, чтобы обновить их содержимое.) Эта настройка также будет хорошо работать в более продвинутых настройках, где у вас есть несколько копий каждого компонента, возможно, запущенных в разных системах (Docker Swarm, Amazon ECS, Kubernetes).

Если возможно обслуживать статические ресурсы непосредственно из серверной службы и использовать nginx только в качестве обратного прокси, это значительно упрощает последовательность развертывания. Однако это может быть невозможно при настройке PHP-FPM.

Комментарии:

1. Да, но это не очень хорошая практика, поскольку это дает вам возможность иметь разные предварительно скомпилированные версии в обоих docker, когда одна из них обновляется, а другая нет. Возможно сделать это так, как вы описали, но, по моему скромному мнению, это не рекомендуется.

2. Другими словами, то, что вы хотите, больше ориентировано на монолитную реализацию, чем на реализацию docker. Второй вариант более последователен, если вы дадите мне совет. Это далеко от философии docker

3. Я чувствую, что важной частью философии Docker является то, что изображения должны быть автономными, а совместное использование файлов между контейнерами на самом деле этого не достигает. Подход с использованием объема также не имеет стратегии обновления («объем будет автоматически заполнен при первом создании контейнера» не помогает вам при обновлении образа), и он плохо работает в кластеризованных средах, таких как Kubernetes.

4. Я согласен с этим, но я ответил только в соответствии с вопросом. Лучший способ — попытаться использовать все автономные изображения, но, к сожалению, это не было отправной точкой, если вы теряете согласованность. Лучший способ — достичь двух условий: 1-го, согласованности и 2-го самодостаточного. Если вы хотите и то, и другое, вам придется изменить архитектуру, дизайн и ответить на первый вопрос «не делайте этого». Наконец, если мне придется выбирать, пожертвовать одним из двух условий, я предпочитаю согласованную систему. Учтите, что философия совместного использования томов — это то, что k8s использует, например, для параметризации развертываний с помощью configmaps. Спасибо в любом случае