Image publishing procedure

Generally, the publishing process in the Docker ecosystem consists of the following steps:

docker tag REPO:TAG
docker push REPO:TAG
docker rmi REPO:TAG
  1. Getting a name or an id of the created local image.
  2. Creating a temporary alias-image for the above image that consists of two parts:
  3. Pushing an alias into the Docker registry.
  4. Deleting a temporary alias.

To publish an image from the config, werf implements another logic:

  1. Create a new image based on the built image with the specified name and save the internal service information about tagging schema to this image (using docker labels). This information is referred to as an image meta-information. werf uses this information in the deploying process and the cleaning process.
  2. Push the newly created image into the Docker registry.
  3. Delete the temporary image created in the first step.

This procedure will be referred to as the image publishing procedure.

The result of this procedure is an image named using the rules for naming images and pushed into the Docker registry. All these steps are performed with the werf publish command or the werf build-and-publish command.

Naming images

During the image publishing procedure, werf forms the image name using:

  • images repo param;
  • images repo mode param;
  • image name from the werf.yaml;
  • tag param.

The final name of the docker image has the form DOCKER_REPOSITORY:TAG.

The images repo and images repo mode params define where and how to store images. If the werf project contains only one nameless image, then the images repo is used as a docker repository as it is, and the resulting name of a docker image gets the following form: IMAGES_REPO:TAG.

Otherwise, werf constructs the resulting name of a docker image for every image depending on the images repo mode:

  • IMAGES_REPO:IMAGE_NAME-TAG pattern for a monorepo mode;
  • IMAGES_REPO/IMAGE_NAME:TAG pattern for a multirepo mode.

The images repo param should be specified by the --images-repo option or $WERF_IMAGES_REPO.

The images repo mode param should be specified by the --images-repo-mode option or $WERF_IMAGES_REPO_MODE.

The image naming behavior should be the same for publishing, deploying, and cleaning processes. Otherwise, the pipeline may fail, and you may end up losing images and stages during the cleanup.

The docker tag is taken from --tag-* params:

option description
--tag-git-tag TAG Use git-tag tagging strategy and tag by the specified git tag
--tag-git-branch BRANCH Use git-branch tagging strategy and tag by the specified git branch
--tag-git-commit COMMIT Use git-commit tagging strategy and tag by the specified git commit hash
--tag-custom TAG Use custom tagging strategy and tag by the specified arbitrary tag

All the specified tag params will be validated for the conformity with the tagging rules for docker images. User may apply the slug algorithm to the specified tag, learn more about the slug.

Also, user specifies both the tag value and the tagging strategy by using --tag-* options. The tagging strategy affects certain policies in the cleaning process.

Every --tag-git-* option requires a TAG, BRANCH, or COMMIT argument. These options are designed to be compatible with modern CI/CD systems, where a CI job is running in the detached git worktree for the specific commit, and the current git-tag, git-branch, or git-commit is passed to the job using environment variables (for example CI_COMMIT_TAG, CI_COMMIT_REF_NAME and CI_COMMIT_SHA for the GitLab CI).

Combining parameters

Any combination of tagging parameters can be used simultaneously in the werf publish command or werf build-and-publish command. As a result, werf will publish a separate image for each tagging parameter of every image in a project.

Examples

Linking images to a git tag

Let’s suppose werf.yaml defines two images: backend and frontend.

The following command:

werf publish --stages-storage :local --images-repo registry.hello.com/web/core/system --tag-git-tag v1.2.0

produces the following image names, respectively:

  • registry.hello.com/web/core/system/backend:v1.2.0;
  • registry.hello.com/web/core/system/frontend:v1.2.0.

Linking images to a git branch

Let’s suppose werf.yaml defines two images: backend and frontend.

The following command:

werf publish --stages-storage :local --images-repo registry.hello.com/web/core/system --tag-git-branch my-feature-x

produces the following image names, respectively:

  • registry.hello.com/web/core/system/backend:my-feature-x;
  • registry.hello.com/web/core/system/frontend:my-feature-x.

Linking images to a git branch with special characters in the name

Once again, we have a werf.yaml file with two defined images: backend and frontend.

The following command:

werf publish --stages-storage :local --images-repo registry.hello.com/web/core/system --tag-git-branch $(werf slugify --format docker-tag "Features/MyFeature#169")

produces the following image names, respectively:

  • registry.hello.com/web/core/system/backend:features-myfeature169-3167bc8c;
  • registry.hello.com/web/core/system/frontend:features-myfeature169-3167bc8c.

Note that the werf slugify command generates a valid docker tag. Learn more about the slug.

Linking images to a GitLab CI job

Let’s say we have a werf.yaml configuration file that defines two images, backend and frontend.

Running the following command in a GitLab CI job for a project named web/core/system with the git branch set as core/feature/ADD_SETTINGS and the Docker registry configured as registry.hello.com/web/core/system:

type werf && source <(werf ci-env gitlab --tagging-strategy tag-or-branch --verbose)
werf publish --stages-storage :local

yields the following image names:

  • registry.hello.com/web/core/system/backend:core-feature-add-settings-df80fdc3;
  • registry.hello.com/web/core/system/frontend:core-feature-add-settings-df80fdc3.

Note that werf automatically applies slug to the resulting tag of the docker image: core/feature/ADD_SETTINGS is converted to core-feature-add-settings-df80fdc3. This conversion occurs in the werf ci-env command, which determines the name of a git branch from the GitLab CI environment, automatically slugs it and sets WERF_TAG_GIT_BRANCH (which is alternative way to set the --tag-git-branch parameter). See more about the slug.

Unnamed image and a GitLab CI job

Let’s suppose we have a werf.yaml with a single unnamed image. Running the following command in the GitLab CI job for the project named web/core/queue with the git-tag named v2.3.1 and a Docker registry configured as registry.hello.com/web/core/queue:

type werf && source <(werf ci-env gitlab --tagging-strategy tag-or-branch --verbose)
werf publish --stages-storage :local

yields the following result: registry.hello.com/web/core/queue:v2.3.1.