У нас есть CI-сервер Jenkins, который извлекает наш код из Git, собирает его, создает образ Docker, а затем отправляет его на некоторые производственные серверы.
Наш проект в основном написан на Python, поэтому "сборка" включает в себя запуск
pip install -r requirements.txt
Это работает нормально, только медленно. Он должен получать пакеты по сети, плюс он должен создавать библиотеки C для некоторых из них (а lxml не маленький!).
В разработке я успешно использовал pip-accel
чтобы ускорить этот процесс. Он имеет тот же интерфейс, что и pip
но он кэширует как загрузки Python, так и встроенный код C, поэтому
pip-accel install -r requirements.txt
быстро.
Я хочу сделать это для наших производственных сборок, но сталкиваюсь с некоторыми препятствиями.
Очевидно, pip-accel
нужен каталог для хранения кеша. Поскольку наш CI-сервер - это то, что запускает сборки, это логичное место для его размещения. Но pip install
команда выполняется внутри нового контейнера Docker, поэтому она не может просто получить доступ к общему каталогу на этом сервере.
Кажется, что «тома» Docker предназначены для совместного использования каталогов с контейнерами, но наша сборка происходит (неожиданный сюрприз) внутри docker build
, и только docker run
позволяет прикреплять тома. Вы не можете прикреплять тома с docker build
.
Что-то мне не хватает? Как я могу запустить docker build
и поделиться папкой кеша с моим хостом вне контейнера, в котором я нахожусь?
У меня мало репутации, чтобы комментировать ваш вопрос, поэтому в моем ответе тоже есть несколько вопросов.
Я попытался создать ту же настройку, что и ваш, но минифицирован (на основе вашего объяснения выше), и, похоже, есть улучшения с собственными механизмами кеширования докера
Мой пример Dockerfile выглядит так:
FROM ubuntu:14.04
RUN apt-get update \
&& apt-get install -y python-pip python-dev build-essential \
&& pip install pip-accel
COPY requirements.txt /requirements.txt
RUN pip-accel install -r /requirements.txt
CMD tail -f /dev/null
А файл requirements.txt выглядел так:
Flask==0.8
Jinja2==2.6
Werkzeug==0.8.3
Создав это в первый раз (посмотрите дольше), я добавил новую библиотеку chardet == 1.0.1, и теперь мой файл requirements.txt выглядел так:
Flask==0.8
Jinja2==2.6
Werkzeug==0.8.3
chardet==1.0.1
После запуска сборки докера он использовал весь собственный кеш докера, в котором также были старые библиотеки pip
anovil@anovil-Latitude-E6440:~/tmp/serverfault/docker$ time docker build --rm .
Sending build context to Docker daemon 3.072 kB
Step 1 : FROM ubuntu:14.04
---> 89d5d8e8bafb
...
...
Removing intermediate container 337c23340e7a
Step 5 : CMD tail -f /dev/null
---> Running in 5cb25bc75bbe
---> d3dfe184934b
Removing intermediate container 5cb25bc75bbe
Successfully built d3dfe184934b
real 0m6.325s
user 0m0.024s
sys 0m0.012s
Потому что сборка докеров по умолчанию имеет '--force-rm = false', '--no-cache = false'.
Другое дело, если ваш Jenkins CI запускает эту сборку от имени разных пользователей или на разных хостах. В противном случае нужно упорядочить команды в Dockerfile.
Если у вас все еще есть вопросы, можете ли вы поделиться своим образцом Dockerfile, а также сообщить здесь, насколько / часто ваш файл requirements.txt изменяет каждую сборку jenkins.