Как кэшировать загрузки диспетчера пакетов для сборок докеров?

Если я запускаю composer install со своего хоста, я попадаю в свой локальный кеш композитора:

  - Installing deft/iso3166-utility (1.0.0)
    Loading from cache

Тем не менее, при создании контейнера, имеющего в своем Dockerfile:

RUN composer install -n -o --no-dev

Я загружаю все, например:

  - Installing deft/iso3166-utility (1.0.0)
    Downloading: 100%         

Это ожидаемо, но я предпочитаю избегать этого. Так как даже на ребилде тоже все заново скачивал.

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

Я изучил это и нашел подход к определить том в Dockerfile :

ENV COMPOSER_HOME=/var/composer
VOLUME /var/composer

Я добавил это в свой Dockerfile и рассчитывал загрузить файлы только один раз, а затем попасть в кеш.

Тем не менее, когда я изменяю свой composer, например. удалите флаг -o и перезапустите docker build ., я ожидал попадания в кеш при сборке, но все же снова загружаю поставщиков.

Как должны работать тома, чтобы иметь кеш данных внутри контейнера докеров?


person k0pernikus    schedule 18.08.2016    source источник
comment
Том будет сохраняться для экземпляра контейнера, но не при сборке. Вы можете создать именованный том, который будет храниться в статическом расположении, но тогда вы связываете решение со средой. Вам нужно подумать о том, что вы хотите сделать в сборке, а что после. Вы можете настроить какой-то локальный репозиторий, который будет действовать как кеш/прокси.   -  person ldg    schedule 18.08.2016
comment
Я тоже с этим борюсь. Вы придумали выход из этого положения? Я подумал, что, возможно, сработает использование прокси-сервера HTTP и указание использования Docker. Потенциально исключая hub.docker.com из прокси, чтобы не хранить две копии загруженных образов.   -  person elifiner    schedule 25.11.2016
comment
@gooli Опубликовал ответ о том, как я справляюсь с проблемой. Спасибо за напоминание.   -  person k0pernikus    schedule 25.11.2016


Ответы (3)


Используйте экспериментальную функцию: Docker buildkit (поддерживается, начиная с версии docker 18.09, docker-compose 1.25.4).

В вашем докерфайле

# syntax=docker/dockerfile:experimental
FROM ....
# ......  
RUN --mount=type=cache,target=/var/composer composer install -n -o --no-dev

Теперь перед сборкой убедитесь, что env var экспортируется:

export DOCKER_BUILDKIT=1
docker build ....

Если вы используете docker-compose, не забудьте также экспортировать COMPOSE_DOCKER_CLI_BUILD :

export COMPOSE_DOCKER_CLI_BUILD=1 DOCKER_BUILDKIT=1
docker-compose build ...

Если это не работает с docker-compose, убедитесь, что ваша версия docker-compose выше 1.25.4.

docker-compose version
person Abdennour TOUMI    schedule 14.09.2019
comment
Какова минимальная версия движка докера для использования этой экспериментальной функции? - person k0pernikus; 14.09.2019
comment
18.09 .. добавлю в ответ - person Abdennour TOUMI; 14.09.2019
comment
И вместо того, чтобы экспортировать var, можно также включить его в саму команду: DOCKER_BUILDKIT=1 docker build . - person k0pernikus; 16.09.2019
comment
@k0pernikus ???? Я линукс супермен .. Или можно сделать псевдоним . .или .. и или .. но идея в том, что мы отвечаем на вопросы всего мира. Учитывая происхождение каждого .. вот почему. - person Abdennour TOUMI; 02.05.2020
comment
Кэш Composer находится в /tmp/cache начиная с composer 1.10. - person helvete; 22.09.2020

Я нашел два способа решения этой проблемы, но ни один из них больше не работает с томами композитора.

  1. Ускорьте процесс загрузки композитора: используйте hirak/prestissimo.

    composer global require "hirak/prestissimo:^0.3"
    
  2. Заставить докер использовать кешированную установку композитора.
    Docker использует кеш на RUN, если добавленные файлы не изменились. Если вы сделаете только COPY . /your-php-app, docker build обновит все кэши и повторно запустит установку композитора, даже если изменился только один несвязанный файл в дереве исходного кода.
    Чтобы сборка docker запускала установку composer install только при изменении пакета, необходимо добавить файлы composer.json и composer.lock перед добавлением исходных файлов. Поскольку в любом случае также нужны исходные файлы, необходимо использовать разные папки для установки композитора и rsync содержимого обратно в добавленную папку; кроме того, после установки необходимо вручную запускать сценарии после установки.
    Это должно выглядеть примерно так (не проверено):

    WORKDIR /tmp/
    COPY composer.json composer.lock ./
    RUN composer install -n -o --no-dev --no-scripts
    
    WORKDIR /your-php-app/ 
    COPY . /your-php-app/
    RUN rsync -ah /tmp/* /your/php-app/
    RUN composer run-script post-install-cmd
    

или совместить =)

person k0pernikus    schedule 25.11.2016
comment
Этот ответ довольно странный... кажется, он не позволяет привязать монтирование из вашего локальный кеш композитора в кеш компоновщика изображений. Что происходит сейчас (насколько я могу догадаться), так это то, что ваш каталог vendor/ полностью скопирован, и поэтому композитору не нужно ничего повторно загружать (или устанавливать). Однако это может иметь кроссплатформенные последствия. - person Christian; 14.07.2018
comment
@Christian О каких межплатформенных проблемах вы думаете? Я использую этот Dockerfile как для разработки, так и для производства. - person k0pernikus; 16.07.2018
comment
Если вы используете какой-либо пакет композитора, который использует исполняемый файл для конкретной платформы, по опыту, композитор недостаточно умен, чтобы понять, что пакет следует переустановить. - person Christian; 16.07.2018
comment
В любом случае, чтобы ответить на ваш (подразумеваемый) вопрос выше, кажется, что docker compose (и, может быть, docker?) каким-то образом не монтирует привязки томов во время сборки. Я знаю, что работающий вариант — это использовать что-то вроде GitLab CI вместо простой сборки с помощью docker-compose. - person Christian; 16.07.2018
comment
Вместо использования временного каталога и использования rsync для выравнивания образа я бы предпочел использовать многоэтапная сборка при возможности использования docker 17.05 или более поздней версии. - person k0pernikus; 18.10.2018
comment
Хотя этот ответ не решает точно поставленный вопрос, я должен сказать, что prestissimo потрясающий! - person Milan Simek; 13.04.2019

Я бы подумал об использовании каталога $HOME/.composer/cache/files. Здесь composer читает/записывает при использовании composer install.

Если вы можете смонтировать его со своего хоста в свой контейнер, это сработает. Также вы можете просто загружать его после каждого запуска composer install, а затем вставлять его перед запуском composer install в следующий раз.

Примерно так Travis CI рекомендует делать это.

Кроме того, рассмотрите возможность использования флага --prefer-dist с вашей командой composer install.

Информацию об этом можно найти здесь: https://getcomposer.org/doc/03-cli.md#install

--prefer-dist: обратная сторона --prefer-source, composer будет устанавливаться из dist, если это возможно. Это может существенно ускорить установку на серверах сборки и в других случаях, когда вы обычно не запускаете обновления поставщиков. Это также способ обойти проблемы с git, если у вас нет правильной настройки.

Некоторые ссылки на использование кеша композитора для вас:

person domdambrogia    schedule 15.01.2019