Simply follow this guide to migrate your project from v1.1 to v1.2.

IMPORTANT There are v1.1 configurations that heavily use mount from build_dir and mount fromPath directives for such cases like caching of external dependencies (Gemfile, or package.json, or go.mod, etc.). While such mount directives still supported by the werf v1.2, it is not recommended for usage and is disabled by default by the giterminism mode (except mount from tmp_dir — this has not been forbidden) because it may lead to harmful, unreliable, host-dependent and nondeterministic builds. For such configurations there will be added a new feature to store such cache in the docker images, this feature is planned to be added into the werf v1.2, but it is not implemented yet. So if your configuration uses such mounts, then there are several options:

  1. Keep using v1.1 version until this feature is added into the werf v1.2.
  2. Completely remove mounts usage and wait until this feature is added into the werf v1.2.
  3. Describe and enable your mounts in werf v1.2 using the werf-giterminism.yaml (not recommended).

Key moments

1. Use content based tagging

Content based tagging strategy is the default strategy and only choice to be used internally by the werf deploy process.

  • Remove --tagging-strategy ... param of werf ci-env command.
  • Remove --tag-custom, --tag-git-tag, --tag-git-branch, --tag-by-stages-signature params.

In the case when you need a certain docker tag for a built image to exist in the container registry to be used outside the werf, then use --save-build-report (and optionally --build-report-path) option like follows:

  • werf build/converge --save-build-report --repo REPO;
  • docker pull $(cat .werf-build-report.json | jq -r .Images.IMAGE_NAME_FROM_WERF_YAML.DockerImageName);
  • docker tag $(cat .werf-build-report.json | jq -r .Images.IMAGE_NAME_FROM_WERF_YAML.DockerImageName) REPO:mytag;
  • docker push REPO:mytag.

2. Use converge command instead of build-and-publish command

Use werf converge command instead of werf deploy to build and publish images, and deploy into kubernetes. All params are the same as for werf deploy.

Commands changes (for reference):

  • werf build-and-publish command has been removed, there is only werf build command, usage of which is optional:
  • werf converge will build and publish needed images by itself, if not built already.
  • You may use werf build command in prebuild CI/CD pipeline stage instead of werf build-and-publish command.

3. Use the --repo parameter instead of the --stages-storage and --images-repo parameters

The werf converge command stores both the collected images and their stages in the container registry. To specify the storage to be used for storing images and stages, you now need to specify one parameter --repo instead of the two previously used in v1.1 --stages-storage and --images-repo. You can read more about this parameter in changelog.

Similarly with the environment variables used earlier: instead of WERF_STAGES_STORAGE and WERF_IMAGES_REPO, one variable WERF_REPO is now used.

4. Change Helm templates

Use .Values.werf.image.IMAGE_NAME instead of werf_container_image as follows:

        - name: main
          image: {{ .Values.werf.image.myimage }}

IMPORTANT! Notice usage of apiVersion: v2 to allow description of dependencies directly in the .helm/Chart.yaml instead of .helm/dependencies.yaml.

Helm templates changes (for reference):

  • Remove werf_container_env template usage completely.
  • Use .Values.werf.env instead of
  • Use .Values.werf.namespace instead of
  • If the image name contains a hyphen (-), then the entry should look like this: image: '{{ index .Values.werf.image "IMAGE-NAME" }}'.
  • Use "": "NUM" annotation instead of "": "true".

    IMPORTANT! Specify "NUM" as string instead of number NUM, annotation will be ignored otherwise.

    IMPORTANT! Remove spec.replicas field, more info in the changelog.

5. Use .helm/Chart.lock for subcharts

Due to giterminism werf does not allow uncommitted .helm/charts dir. To use subcharts specify dependencies in the .helm/Chart.yaml like that:

# .helm/Chart.yaml
apiVersion: v2
- name: redis
  version: "12.7.4"
  repository: ""

IMPORTANT! Notice usage of apiVersion: v2 to allow description of dependencies directly in the .helm/Chart.yaml instead of .helm/dependencies.yaml.

Next, follow these steps:

  1. Add .helm/charts into the .gitignore.
  2. Run werf helm dependency update command, which will create .helm/Chart.lock file and .helm/charts dir.
  3. Commit .helm/Chart.lock file into the project git repo.

werf will automatically download subcharts into the cache and load subchart files in werf converge command (and other toplevel commands which require helm chart).

6. Cleanup by Git history

Remove --git-history-based-cleanup-v1.2 option for a cleanup. werf always uses git-history cleanup in the v1.2. More info in the changelog and in the cleanup article.

7. Define environment variables in werf-giterminism.yaml

NOTE! It is not recommended to use environment variables in the werf.yaml, more info in the article.

If you use environment variables in your werf.yaml, then use the following werf-giterminism.yaml snippet (for example to enable ENV_VAR1 and ENV_VAR2 variables):

# werf-giterminism.yaml
giterminismConfigVersion: 1
      - ENV_VAR1
      - ENV_VAR2

8. Adjust werf.yaml configuration

  1. Change relative include paths from {{ include “.werf/templates/1.tmpl” . }} to {{ include “templates/1.tmpl” . }}.
  2. Rename fromImageArtifact to fromArtifact.

    NOTICE! It is not required, but better to change artifact and fromArtifact to image and fromImage in such case. See deprecation note in the changelog.

9. Define custom .helm chart dir in the werf.yaml

--helm-chart-dir has been removed, use deploy.helmChartDir directive in werf.yaml like follows:

configVersion: 1
  helmChartDir: .helm2

Consider using different layout for your project: werf v1.2 supports multiple werf.yaml applications in the single Git repo.

  • Instead of defining a different deploy.helmChartDir in your werf.yaml, create multiple werf.yaml in subfolders of your project.
  • Each subfolder will contain own .helm directory.
  • Run werf from the subfolder in such case.
  • All relative paths specified in the werf.yaml should be adjusted to the subfolder where werf.yaml stored.
  • Absolute paths specified with git.add directive should use absolute paths from the root of the git repo (these paths settings are compatible with 1.1).

10. Migrate to helm 3

werf v1.2 performs migration of existing Helm 2 release to helm 3 automatically.

Helm 2 release should have the same name as newly used helm 3 release.

Before migrating werf will try to render and validate current .helm/templates and continue migration only when render succeeded.

IMPORTANT! Once project has been migrated to helm 3 there is no legal way back to the werf v1.1 and helm 2.


This article contains full descriptive list of changes since v1.1.


werf introduces the so-called giterminism mode. The word is constructed from git and determinism, which means “determined by the git”.

All werf configuration files, helm configuration and application files werf reads from the current commit of the git project directory. There is also so called dev mode to simplify local development of werf configuration and local development of an application with werf.

More info at the page.

Introduced new giterminism configuration file werf-giterminism.yaml.

Local development

Follow and dev

All toplevel commands: werf converge, werf run, werf bundle publish, werf render and werf build — has two main flags --follow and --dev aimed for local development.

By default, each of these commands reads all needed files from the current commit of the git repo. With the --dev flag command will read files from the project git worktree including untracked files. werf ignores changes in compliance with the rules described in .gitignore as well as rules that the user sets with the --dev-ignore=<glob> option (can be used multiple times).

Command with the --follow flag will work in a loop, where either:

  • a new commit to the project git work tree will cause command rerun — by default;
  • any changes in the git repository worktree including untracked files will cause command rerun — when --follow flag is combined with the --dev flag.

Internally werf will commit changes to dev branch werf-dev-<commit>. Dev-cache is linked only to those temporal commits and will not interfere with the main cache (when no --dev has been specified).

Composer support

werf supports main composer commands. When running these commands werf will set special environment variables with full docker images names of images described in the werf.yaml:


For example, given the following werf.yaml:

# werf.yaml
project: myproj
configVersion: 1
image: myimage
from: alpine

myimage full docker image name could be used in the docker-compose.yml like that:

version: '3'

werf provides following compose commands:

New bundles functionality

  • Bundles allow splitting the process of creation of a new release of the source code for an application and the process of deploying of this release into the kubernetes.
  • Bundles are stored in the container registry.
  • Working with bundles implies two steps: 1) publishing a bundle for your application version from the application git directory into the container registry; 2) deploy published bundle from the container registry into the kubernetes.

Change main commands interface and behaviour

Interface rework

  • werf deploy is removed. Use werf converge — a single command to build and publish needed images into the container registry and deploy application into the kubernetes.
    • Use werf converge --require-built-images to emulate werf deploy behaviour: werf will exit with error in case needed images was not found in the container registry.
  • Commands werf stages *, werf images * and werf host project * are removed.
  • There is no more werf publish command, because werf build command with --repo param will publish images with all it’s stages into the container registry automatically.
  • There is no more --tag-by-stages-signature, --tag-git-branch, --tag-git-commit, --tag-git-tag, --tag-custom options, --tag-by-stages-signature behaviour is default.
    • Forcing of custom tags is not yet available in the v1.2
    • werf ci-env command only accepts hidden --tagging-strategy flag for legacy command call: werf ci-env --tagging-strategy without --as-file flag.
      • This flag usages should be completely removed from the werf ci-env invocations.
      • Specified param for this flag does not make a difference, --tag-by-stages-signature behaviour will be used anyway.

werf-build and werf-converge commands behaviour

  • By default werf build command does not require any arguments and will build cache in the local docker server images storage.
  • When running werf build with --repo param werf will lookup for already built images in the local docker server images storage and upload them if found any (without unnecessary rebuild).
  • werf converge command requires --repo to work, but as werf build command will automatically upload into the repo any locally existing images.

Cleaning commands behaviour

  • The werf cleanup/purge commands only for cleaning the project container registry.
  • The werf host purge --project=<project-name> for removing the project images in the local Docker (previously, it was possible to use the werf purge command).

Automatical images building in some toplevel commands

  • werf converge, werf run, werf bundle publish and werf render commands will automatically build needed images, which does not exist in the repo.
    • werf render will build images only when --repo param has been specified.

Storing of images in CI/CD systems

Use project’s container registry repository as --repo param for werf commands.

  • werf ci-env command for GitLab CI/CD for example will generate WERF_REPO=$CI_REGISTRY_IMAGE.
  • Specified --repo repository will be used as storage both for built images stages and final images.

Always store image stages in the container registry

  • werf converge command always stores images and all its stages in the container registry.
  • Single --repo param to specify storage of images with all its stages (there was separate --stages-storage and --images-repo params in the v1.1).
  • Due to the usage of content-based tagging final built image is the same as the last stage of this image.
    • And as image consists of multiple stages, all these stages are stored in the container registry anyway.
      • So storing of intermediate stages of the image does not create overhead for the container registry.
      • This makes werf build process host independent, because werf will reuse intermediate stages of an image from the container registry as a build cache.

Signature changes

  • Signature renamed to digest.
  • All signatures/digests of built images has been changed.
  • Dockerfile images and stapel images will be rebuilt.
    • In other words: build cache from the v1.1 is not valid anymore.

Stapel builder

  • Remove the ability to cache each instruction separately with asLayers directive.

Optional env param

  • For werf converge, werf render and werf bundle publish commands there is --env param.
  • --env param affects helm release name and kubernetes namespace as in v1.1.
    • When --env has been specified helm release name will be generated by the template [[ project ]]-[[ env ]] and kubernetes namespace will be generated by the same template [[ project ]]-[[ env ]] — this is the same as in v1.1.
    • When no --env param has been specified, then werf will use [[ project ]] template for the helm release and the same [[ project ]] template for the kubernetes namespace generation.

New werf-render command


Helm 3

  • Helm 3 is default and the only choice when deploying with werf v1.2.
  • An already existing helm 2 release will be migrated to helm 3 automatically in the werf converge command given that helm 2 release has the same name as newly deployed helm 3 release.
    • CAUTION There is no legal way back once helm 2 release has been migrated to helm 3.
    • werf-converge command will check that project helm charts are correctly rendered before running the process of migration.


  • .Values.werf.image.IMAGE_NAME instead of werf_image template.
  • Removed werf_container_env helm template function.
  • Giterministic loading of all chart files (including subcharts).
    • This is only true for top-level commands like werf converge or werf render.
    • Low-level helm commands werf helm * still load chart files from the local filesystem.
  • Environment passed with --env param is available at the .Values.werf.env.
  • Target namespace is available at the .Values.werf.namespace.
  • Fix usage of the .helm/Chart.yaml. This makes .helm/Chart.yaml optional, but werf will use it when it exists.
    • Take .helm/Chart.yaml from the repository if exists.
    • Override field with werf project name from the werf.yaml.
    • Set metadata.version = 1.0.0 if not set.
  • Added .Values.werf.version service value with werf cli util version.
  • Support setting initial number of replicas when HPA is active for Deployment and other resources kinds. Set "": NUM annotation, do not set spec.replicas field in templates in such case explicitly.
    • spec.replicas will override
    • This annotation is especially useful when HPA is active, here is the reason.

Working with subcharts

  • Lock file with dependencies should be committed .helm/Chart.lock.
  • werf will automatically download dependencies charts using this lock file.
  • Typically .helm/charts directory should be added to .gitignore file.
  • werf allows storing chart dependencies directly in the .helm/charts though.
    • These charts will override charts automatically downloaded by the .helm/Chart.lock file

Deleted werf-helm-deploy-chart command

Use werf helm install/upgrade native helm commands instead of werf helm deploy-chart.

Better integration with werf-helm-* commands

  • werf helm template command could be used to render chart templates even if custom werf templates function are used (like werf_secret_file).
  • Secret files are fully supported by werf helm * commands.
  • Custom annotations and labels are fully supported by werf helm * commands (--add-annotation and --add-label options).

Changed service values format

Removed section, use .Values.werf.image instead.

Deploy process

  • Wait until all release resources terminated before exiting in werf dismiss and werf helm uninstall commands.


  • Rename fromImageArtifact to fromArtifact
    • CAUTION fromImageArtifact/fromArtifact has also been deprecated and will be removed in the v1.3, it is recommended to use image and fromImage in such case.
  • Remove the herebyIAdmitThatFromLatestMightBreakReproducibility and herebyIAdmitThatBranchMightBreakReproducibility directives. Now when using the directives fromLatest and git.branch you must loosen the giterminism rules with the corresponding directives in werf-giterminism.yaml.
  • Remove --helm-chart-dir option, define helm chart dir in the werf.yaml:

     configVersion: 1
       helmChartDir: .helm
  • Move --allow-git-shallow-clone, --git-unshallow and --git-history-synchronization options into the werf.yaml, added new gitWorktree meta section](../reference/werf_yaml.html#meta-section-gitWorktree). Disabled generation of old options in the werf ci-env command. Always unshallow git clone by default.
  • Use sprig v3 instead of v2:
  • New documentation page describing werf.yaml template engine.
  • Fix naming for the user template. The template name is the path relative to the templates directory. {{ include “.werf/templates/1.tmpl” . }} => {{ include “templates/1.tmpl” . }}.
  • Nameless image declaration image: ~ is deprecated, it is better to always name your images. Will be removed in v1.3.
  • env "ENVIRONMENT_VARIABLE_NAME" function requires ENVIRONMENT_VARIABLE_NAME variable to exists (it may contain empty value, but should be explicitly defined).
  • The new required function gives developers the ability to declare a value entry as required for config rendering. If the value is empty, the config will not render and will return an error message supplied by the developer.

     {{ required "A valid <anything> value required!" <anything> }}

Tagging strategy

  • Only content-based.
  • Export of built images into arbitrary container registry coming soon.
  • Forcing custom built tags coming soon.


  • Git history based by default.
    • Previously this mode was enabled with --git-history-based-cleanup-v1.2 option.
      • Option has been removed.
  • Removed tag strategy based algorithms completely.
  • --keep-stages-built-within-last-n-hours option to keep images that were built within period (2 hours by default).
  • Git-history based cleanup improvement:
    • The keep policy imagesPerReference.last counts several stages that were built on the same commit as one.
    • Thus, the policy may cover more tags than expected, and this behavior is correct.

Caching of stapel artifact/image imports by files checksum

  • Suppose we have an artifact which builds some files.
  • This artifact has a stage-dependency in the werf.yaml to rebuild these files when some source files has been changed.
  • When source files has been changed werf rebuilds this artifact.
    • Because stage-dependency has changed, last artifact stage will also have a different digest.
    • But after artifact rebuild factual checksum of built files not changed — the same files.
      • In the v1.1 werf would still perform import of these files into the target image.
        • As a consequence target image will be unnecessarily rebuilt and redeployed.
      • In the v1.2 werf would check checksum of imported files and perform reimport only when checksum changed.

Primary and secondary images storage support

  • Automatically upload locally built images into the specified --repo.
  • Use stages from read-only secondary images storage specified by --secondary-repo options (can be specified multiple times).
    • Suitable stages from the --secondary-repo will be copied into the primary --repo.

Built images report format changes

werf converge, werf build, werf run, werf bundle publish and werf render commands has --save-build-report and --build-report-path options. --save-build-report option enables generation of built images report in the following format:

$ werf build --save-build-report

  "Images": {
    "result": {
      "WerfImageName": "result",
      "DockerRepo": "quickstart-application",
      "DockerTag": "32e88a6a19a425c9254374ee2899b365876de31ac7d6857b523696a1-1613371915843",
      "DockerImageID": "sha256:fa6445196bc8ed44e4d2842eeb068aab4e627112d504334f2e56d235993ba4f0",
      "DockerImageName": "quickstart-application:32e88a6a19a425c9254374ee2899b365876de31ac7d6857b523696a1-1613371915843"
    "vote": {
      "WerfImageName": "vote",
      "DockerRepo": "quickstart-application",
      "DockerTag": "45f03bdd90c844eb2e61e7e01dae491588d2bdadbd195881b25be9b0-1613371915351",
      "DockerImageID": "sha256:a6845bbc7912e45c601b0291170f9f503722efceb9e3cc98a5701ea4d26b017e",
      "DockerImageName": "quickstart-application:45f03bdd90c844eb2e61e7e01dae491588d2bdadbd195881b25be9b0-1613371915351"
    "worker": {
      "WerfImageName": "worker",
      "DockerRepo": "quickstart-application",
      "DockerTag": "1b16118e7d5c67aa3c61fc0f8d49b3eccf8f72810f01c33a40290418-1613371916044",
      "DockerImageID": "sha256:546af94bd73dc20a7ab1f49562f42c547ee388fb75cf480eae9fde02b48ad6ad",
      "DockerImageName": "quickstart-application:1b16118e7d5c67aa3c61fc0f8d49b3eccf8f72810f01c33a40290418-1613371916044"


$ werf build --save-build-report --build-report-path=.werf-build-report.env


Support multiple werf.yaml in the single git repo

User may put werf.yaml (and .helm) into any subdirectory of the project git repo.

  • All relative paths specified in the werf.yaml will be calculated relatively to the werf process cwd or --dir param.
  • Typically, user will run werf from the subdirectory where werf.yaml reside.
  • There is also --config option to pass custom werf.yaml config, all relative paths will also be calculated relatively to the werf process cwd or --dir param.
  • Added --git-work-tree param (or WERF_GIT_WORK_TREE variable) to specify a directory that contains .git in the case when autodetect failed, or we want to use specific work tree.
    • For example when running werf from the submodule of the project we may want to use root repo worktree instead of submodule’s work tree.
      • Built stages will be linked to the commits of the root repo in such case.

Other and internals

  • Added git-archives and git-patches cache in the ~/.werf/local_cache/ along with git-worktrees. Do not create patches and archives in /tmp (or --tmp-dir).
  • Remove stages_and_images read-only lock during build process
  • stages_and_images read only lock is preventive measure against running cleanup and build commands at the same time;
  • This lock creates unnecessary load on the synchronization server, because this lock working all the time the build process is active for each build process.
  • It is mostly safe to just omit this lock completely.
  • Also removed unused image lock from the lock manager (legacy from v1.1).
  • Also renamed kubernetes-related stage and stage-cache locks to include project name (just for more correctness, incompatible with v1.1 change).

Documentation rework

  • Split all documentation into sections by the level of the understanding:
    • landing page;
    • introduction;
    • quickstart;
    • guides;
    • reference;
    • advanced;
    • internals.
  • New guides section.