import:
- from: <image name or external_image>
stage: <stage name>
before: <install setup>
after: <install setup>
add: <absolute path>
to: <absolute path>
owner: <owner>
group: <group>
includePaths:
- <relative path or glob>
excludePaths:
- <relative path or glob>
Из-за используемых инструментов сборки либо просто из-за исходных файлов размер целевого образа может увеличиваться в несколько раз. Зачастую эти файлы не нужны в конечном образе. Для решения таких проблем сообщество Docker предлагает выполнять установки инструментов, сборку и удаление ненужных файлов за один шаг.
Условный пример:
RUN “download-source && cmd && cmd2 && remove-source”
Аналогичный пример может быть реализован и в werf. Для этого достаточно описать инструкции в одной пользовательской стадии. Пример при использовании shell-сборщика для стадии install:
shell: install: - "download-source" - "cmd" - "cmd2" - "remove-source"
Однако при использовании такого метода кэширование работать не будет, и установка инструментов сборки будет выполняться каждый раз.
Другой способ — использование multi-stage сборки, которая поддерживается в Docker, начиная с версии 17.05.
FROM node:latest AS storefront
WORKDIR /app
COPY react-app .
RUN npm install
RUN npm run build
FROM maven:latest AS appserver
WORKDIR /app
COPY . .
RUN mvn package
FROM java:8-jdk-alpine
COPY --from=storefront /app/react-app/build/ /static
COPY --from=appserver /app/target/AtSea-0.0.1-SNAPSHOT.jar /app/AtSea.jar
Смысл такого подхода в следующем — описать несколько вспомогательных образов и выборочно копировать артефакты из одного образа в другой, оставляя все то, что не нужно в конечном образе.
werf предлагает подобный подход.
Почему werf не использует multi-stage сборку?
- Исторически возможность импорта появилась значительно раньше, чем в Docker появилась multi-stage сборка.
- werf дает больше гибкости при работе со вспомогательными образами.
Конфигурация импорта
Импорт ресурсов из образов должен быть описан в директиве import в конфигурации образа, куда импортируются файлы. import — массив записей, каждая из которых должна содержать следующие параметры:
from: <image name>: исходный образ, имя образа из которого вы хотите копировать файлы или каталоги. Поддерживается как импорт из образов текущего проекта, так и внешние образы в форматеimage_name:tagилиimage_name@digestadd: <absolute path>: исходный путь, абсолютный путь к файлу или каталогу в исходном образе для копирования.to: <absolute path>: путь назначения, абсолютный путь в образе назначения (куда импортируются файлы или каталоги). В случае отсутствия считается равным значению, указанному в параметреadd.before: <install || setup>orafter: <install || setup>: стадия образа назначения для импорта. В настоящий момент возможен импорт только до/после стадии install или setup.
Пример:
import:
- from: application-assets
add: /app/public/assets
to: /var/www/site/assets
after: install
- from: node:20-alpine
add: /usr/share/nginx/html
to: /var/www/site/prebuilt
after: setup
Так же, как и при конфигурации git mappings, поддерживаются маски включения и исключения файлов и каталогов.
Для указания маски включения файлов используется параметр includePaths: [], а для исключения excludePaths: []. Маски указываются относительно пути источника (параметр add).
Вы также можете указывать владельца и группу для импортируемых ресурсов с помощью параметров owner: <owner> и group: <group> соответственно.
Это поведение аналогично используемому при добавлении кода из Git-репозиториев, и вы можете подробнее почитать об этом в соответствующем разделе.
Обратите внимание, что путь импортируемых ресурсов и путь указанный в git mappings не должны пересекаться.
Правила пути назначения
Что окажется по пути назначения, зависит от того, каталог или файл указан в исходном пути.
Если add — это каталог, его содержимое сливается в to. Уже лежащие в to файлы сохраняются, а файлы с совпадающими именами перезаписываются. Именно поэтому несколько импортов могут вести в один и тот же каталог.
Если add — это файл, результат зависит от образа назначения:
- если пути
toне существует, файл создаётся ровно по этому пути:add: /app/config.yamlсto: /etc/app.yamlдаёт/etc/app.yaml; - если
toуже существует и это каталог, файл помещается внутрь него: тот же импорт сto: /etcдаёт/etc/config.yaml.
werf создаёт только родительский каталог для to, поэтому существует ли сам to, определяет образ назначения — когда разница важна, указывайте полный путь до файла.
Завершающий слеш в to (всё, кроме to: /) — ошибка конфигурации, сборка падает: пишите to: /usr/sbin, а не to: /usr/sbin/.