Import stages
import:
- image: <image name>
  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>

The size of the final image can grow dramatically due to the assembly tools and source files eating up space. These files are generally not needed in the final image. To avoid this, the Docker community suggests installing tools, building, and removing irrelevant files in one step:

RUN “download-source && cmd && cmd2 && remove-source”

You can do the same in werf — just specify the relevant instructions for some user stage. Below is an example of specifying the shell assembly instructions for the install stage (you can do so for the ansible builder as well):

shell:
  install:
  - "download-source"
  - "cmd"
  - "cmd2"
  - "remove-source"

However, this method does not support caching. Thus, a build toolkit will be installed all over again.

Another way is to use a multi-stage build, a feature supported in Docker since version 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

The point of this approach is to describe several auxiliary images and selectively copy artifacts from one image to another, leaving all the unnecessary data outside the final image.

werf offers the same approach.

Why doesn’t werf use multi-stage assembly?

  • Historically, imports came much earlier than the Docker multi-stage mechanism, and
  • werf allows for greater flexibility when working with auxiliary images.

Import configuration

Importing resources from the images must be described in the import directive in the destination image in the image config section. import is an array of records, where each record must contain the following:

  • image: <image name>: source image; the name of the image copy files from.
  • stage: <stage name>: source image stage; the stage of the source_image to copy files from.
  • add: <absolute path>: source path; the absolute path to the file or directory in the source image to copy from.
  • to: <absolute path>: destination path; the absolute path in the destination image. If absent, the destination path defaults to the source path (as specified by the add directive).
  • before: <install || setup> or after: <install || setup>: destination image stage; the stage to import files. Currently, only install and setup stages are supported.

An example of the import directive:

import:
- image: application-assets
  add: /app/public/assets
  to: /var/www/site/assets
  after: install
- image: frontend
  add: /app/assets
  after: setup

As with the git mappings configuration, include and exclude file and directory masks are supported (includePaths: [] and excludePaths: [], respectively). Masks must be specified relative to the source path (as in the add parameter). You can also specify an owner and a group for the imported resources, owner: <owner> and group: <group>. This behavior is similar to the one used when adding code from Git repositories, and you can read more about it in the git directive section.

Note that the path of imported resources and the path specified in git mappings must not overlap.