Задать вопрос
@Dima_Amigo

Как ускорить docker push?

Столкнулся с тем, что команда docker push работает ну очень медленно и в этом, наверное, нет никакого смысла.

В Dockerfile запускается команда загрузки всех зависимостей `RUN npm install`. Она качает около 600МБ файлов и всё это попадает в один слой докер образа, который в сжатом виде весит около 400МБ (не суть).
Далее этот слой грузится на приватный docker registry.

Вопрос: даже если изменится хотя бы один файл в зависимостях, докер опять создаст и попытается загрузить новый слой размером в 400МБ. Может быть есть готовые решения, чтобы docker push/pull не скачивали по 400МБ при малейшем изменении? Может быть есть другая утилита, которая заменяет собой docker push/pull и внутри хранит содержимое отдельных слоёв в гите?

UPD:

Представьте, что мы можем изменить реализацию команд docker push/pull.

Альтернативный docker push берёт нужный образ и помещает его через docker save в архив. Этот архив нужно разархивировать вместе со всеми слоями внутри и запушить в специальный git-репозиторий.

Альтернативный docker pull скачивает нужный образ из определённой ветки или тега в гите, собирает обратно из него архив и через docker load загружает образ в докер.

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

Минусы в таком подходе тоже есть: каждый git fetch вынужден грузить абсолютно все новые изменения (все версии).

Можно думать над велосипедами в эту сторону (может быть rsync вместо git), но вдруг уже есть готовое решение...
  • Вопрос задан
  • 393 просмотра
Подписаться 3 Средний 6 комментариев
Решения вопроса 1
Lynn
@Lynn
nginx, js, css
Можно использовать multi-stage build
Примерно так:
FROM node:lts-alpine as build
WORKDIR /app
# копируем исходный код
COPY ./ ./
# устанавливаем зависимости
RUN npm ci
# Компилируем приложение
RUN npm run build
# оставляем только production зависимости
RUN npm ci --prod
# опционально удаляем из исходников всякие тесты, ts-файлы и т.п.

FROM node:lts-alpine as app
WORKDIR /app
# копируем сначала node_modules
COPY --from=build /app/node_modules ./node_modules
# а потом всё остальное
COPY --from=build /app ./
# и запускаем
CMD [ "node", "/app/app.js" ]


В результате, если не меняется файл package-lock.json (т.е. не меняются зависимости прода), то слой созданный в команде COPY --from=build /app/node_modules ./node_modules будет взят из кэша. А это и есть все наши 400 мегабайт зависимостей.

живой пример

Это второй запуск после изменения приложения и версии в package.json, но без изменений зависимостей. Тут видно, что шаг 4 сборки честно выполнился, но при этом шаг 9 (копирование node_modules) взят из кэша, т.к. папка node_modules не поменялась.
$ docker build .
Sending build context to Docker daemon  6.656kB
Step 1/11 : FROM node:lts-alpine as build
 ---> 1c342643aa5c
Step 2/11 : WORKDIR /app
 ---> Using cache
 ---> 01d641ac9d8b
Step 3/11 : COPY ./ ./
 ---> 2a369bda0312
Step 4/11 : RUN npm ci
 ---> Running in 5becac2f9f07
added 2 packages in 1.914s
Removing intermediate container 5becac2f9f07
 ---> c010ba772a08
Step 5/11 : RUN npm run build
 ---> Running in de6fd7f872a5

> docker-node@1.2.3 build /app
> echo building app

building app
Removing intermediate container de6fd7f872a5
 ---> dc80bc125954
Step 6/11 : RUN npm ci --prod
 ---> Running in 825f86a54af5
npm WARN prepare removing existing node_modules/ before installation
added 1 packages in 0.079s
Removing intermediate container 825f86a54af5
 ---> a00a029b86dc
Step 7/11 : FROM node:lts-alpine as app
 ---> 1c342643aa5c
Step 8/11 : WORKDIR /app
 ---> Using cache
 ---> 01d641ac9d8b
Step 9/11 : COPY --from=build /app/node_modules ./node_modules
 ---> Using cache
 ---> 81d587ccf147
Step 10/11 : COPY --from=build /app ./
 ---> bb40061f06b6
Step 11/11 : CMD [ "node", "/app/app.js" ]
 ---> Running in e6b9e08d9d8f
Removing intermediate container e6b9e08d9d8f
 ---> eceb38619009
Successfully built eceb38619009

Ответ написан
Пригласить эксперта
Ответы на вопрос 2
@vitaly_il1
DevOps Consulting
Я человек практический, поэтому не верю что могу изобрести велосипед, который
1) будет работать принципиально лучше чем существующие
2) станет общепринятым

Поэтому я за multi-stage build, плюс можно выделить в отдельные слои "постоянные" и "переменнные" пакеты.
Обычно есть 80% пакетов 3rd party, они постоянные, и немного своих которые меняются.
Ответ написан
Комментировать
shurshur
@shurshur
Сисадмин, просто сисадмин...
Это невозможно. В принципе. Слой загружается на сервер только целиком, нельзя проверять, что в нём отличается только один файл. Тем более отличаться будет не только файл, но и, например, каталог, в который его положили - у него изменится mtime. Всё это отслеживается через контрольную сумму архива слоя, она от любого нового файла меняется.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы