By default, werf uses the Docker Registry API. For most container registry implementations, no other actions are required from the user.

However, the container registry may have limited support for the Docker Registry API and/or implement some functions in the native API. In this case, when using the container registry, the user may need to perform some additional actions and provide the supplementary data.

werf tries to automatically detect the type of container registry using the repository address provided (via the --repo option). The user can explicitly specify the container registry using the --repo-container-registry option or via the WERF_REPO_CONTAINER_REGISTRY environment variable.

  Build Bundles Cleanup
AWS ECR ok ok *ok
Azure CR ok ok *ok
Default ok ok ok
Docker Hub ok not supported *ok
GCR ok ok ok
GitHub Packages ( ok not supported *ok
GitHub Packages ( ok ok not supported
GitLab Registry ok ok *ok
Harbor ok ok ok
JFrog Artifactory ok ok ok
Nexus ok not tested ok
Quay ok not supported ok


When interacting with the container registry, werf commands use the information available in the Docker configuration. By default, they use the ~/.docker directory or an alternative path set by the WERF_DOCKER_CONFIG (or DOCKER_CONFIG) environment variable.

The Docker configuration is a directory where authorization data (and Docker settings) are stored (these data are used for accessing various container registries)

For authorization, you can use docker login / oras login commands as well as solutions provided by container registries.

For CI jobs, we recommend using the werf ci-env command. It creates a temporary Docker configuration based on a user configuration and performs authorization (if the container registry’s CI is used) using CI environment variables. See the relevant section of the documentation for more information about integrating werf with CI systems.

The usage of a shared Docker configuration when running parallel jobs in a CI system may lead to a job failure because of a race condition and conflicting temporary credentials (one job interferes with another by overriding temporary credentials in the shared Docker configuration). That is why we recommend creating a dedicated Docker configuration for each CI job (the werf ci-env command does this by default)


To use bundles, the container registry must support the OCI Image Format Specification.

Clean up

By default, werf uses the Docker Registry API for deleting tags. The user must be authenticated and have a sufficient set of permissions.

If the Docker Registry API isn’t supported and tags are deleted using the native API, then some additional container registry-specific actions are required on the user’s part.


werf deletes tags using the AWS SDK. Therefore, before performing a cleanup, the user must do one of the following:

Azure CR

werf deletes tags using the Azure CLI. Therefore, before performing a cleanup, the user must do the following:

  • Install the Azure CLI (az).
  • Perform authorization (az login).

The user must be assigned to one of the following roles: Owner, Contributor, or AcrDelete (learn more about Azure CR roles and permissions)

Docker Hub

werf uses the Docker Hub API to delete tags, so you need to set either the token or the username/password pair to clean up the container registry.

You can use the following script to get a token:

HUB_TOKEN=$(curl -s -H "Content-Type: application/json" -X POST -d '{"username": "'${HUB_USERNAME}'", "password": "'${HUB_PASSWORD}'"}' | jq -r .token)

You can’t use the personal access token as a token since the deletion of resources is only possible using the user’s primary credentials.

You can use the following options (or their respective environment variables) to set the said parameters:

  • -- repo-docker-hub-token or
  • --repo-docker-hub-username and --repo-docker-hub-password.

GitHub Packages (

werf uses the GitHub GraphQL API to delete tags, so you need to set the token with the appropriate scope (read:packages, write:packages, delete:packages) along with the repo scope to clean up the container registry.

GitHub does not support deleting versions of a package in public repositories

You can use the --repo-github-tack option or the corresponding environment variable to define the credentials.

GitLab Registry

werf uses the GitLab Container Registry API or Docker Registry API (depending on the GitLab version) to delete tags.

Privileges of the temporary CI job token ($CI_JOB_TOKEN) are not enough to delete tags. That is why the user have to create a dedicated token in the Access Token section (select the api in the Scope section) and perform authorization using it