Если я правильно понял проблему, то есть несколько подходов к этой проблеме, и я перечислю их от самого простого до более сложного:
Использование предыдущей версии для создания новой версии из
Это, безусловно, самый простой подход, который требует только изменения базового образа для вашей новой версии.
Рассмотрим следующее Dockerfile
для создания версии 2 приложения:
FROM version1
RUN ...
Затем создайте его with:
docker build -t version2 .
Этот подход, однако, имеет проблему - все старые куски будут накапливаться в новых изображениях. Это может или не может быть желательно, но что-то нужно учитывать.
Другая проблема заключается в том, что вы не можете легко обновить базовый образ.
Использовать многоступенчатые сборки
Многоступенчатый сборки позволяют запускать несколько этапов и включать результаты каждого этапа в окончательное изображение. На каждом этапе могут использоваться различные Docker изображения с различными инструментами, например, G CC для компиляции некоторой нативной библиотеки, но вам на самом деле не нужно G CC в конечном изображении.
Для того, чтобы сделать это работает с многоступенчатой сборкой, вам нужно будет иметь возможность создать самый первый образ. Давайте рассмотрим следующее Dockerfile
, которое делает именно это:
FROM alpine
RUN mkdir -p /app/latest && touch /app/latest/$(cat /proc/sys/kernel/random/uuid).chunk.js
Создает новое новое изображение Docker с новым чанком со случайным именем и помещает его в каталог с именем latest
- это важно с предложенным подходом!
Для создания последующих версий нам понадобится Dockerfile.next
, который выглядит следующим образом:
FROM version2 AS previous
RUN rm -rf /app/previous && mv /app/latest/ /app/previous
FROM alpine
COPY --from=previous /app /app
RUN mkdir -p /app/latest && touch /app/latest/$(cat /proc/sys/kernel/random/uuid).chunk.js
На первом этапе он поворачивает версию, удаляя previous
версия и перемещение latest
в previous
.
На втором этапе он копирует все версии, оставшиеся на первом этапе, создает новую версию и помещает ее в latest
.
Вот как это использовать:
docker build -t image:1 -f Dockerfile .
>> /app/latest/99cfc0e6-3773-40a0-82d4-8c8643cc243b.chunk.js
docker build -t image:2 --build-arg PREVIOUS_VERSION=1 -f Dockerfile.next .
>> /app/previous/99cfc0e6-3773-40a0-82d4-8c8643cc243b.chunk.js
>> /app/latest/2adf34c3-c50c-446b-9e85-29fb32011463.chunk.js
docker build -t image:3 --build-arg PREVIOUS_VERSION=2 -f Dockerfile.next
>> /app/previous/2adf34c3-c50c-446b-9e85-29fb32011463.chunk.js
>> /app/latest/2e1f8aea-36bb-4b9a-ba48-db88c175cd6b.chunk.js
docker build -t image:4 --build-arg PREVIOUS_VERSION=3 -f Dockerfile.next
>> /app/previous/2e1f8aea-36bb-4b9a-ba48-db88c175cd6b.chunk.js
>> /app/latest/851dbbf2-1126-4a44-a734-d5e20ce05d86.chunk.js
Обратите внимание, как чанки перемещаются с latest
на previous
.
Это решение требует, чтобы ваш сервер мог обнаруживать данные c файлов в разных каталогах, но это может усложнить локальную разработку, хотя эта логика c может быть условной в зависимости от среды.
В качестве альтернативы вы можете скопировать все файлы в один каталог при обращении Инер начинается. Это можно сделать с помощью сценария ENTRYPOINT
в самом Docker или в коде вашего сервера - это зависит только от вас, зависит от того, что удобнее.
Также в этом примере рассматривается только одна версия назад, но его можно масштабировать до нескольких версий с помощью более сложного сценария вращения. Например, чтобы сохранить 3 последние версии, вы можете сделать что-то вроде этого:
RUN rm -rf /app/version-0; \
[ -d /app/version-1 ] && mv /app/version-1 /app/version-0; \
[ -d /app/version-2 ] && mv /app/version-2 /app/version-1; \
mv /app/latest /app/version-2;
Или его можно параметризовать, используя Docker ARG
с количеством сохраняемых версий.
Вы Подробнее о многоэтапных сборках можно прочитать в официальной документации .