{"id":37667,"date":"2019-10-31T22:18:58","date_gmt":"2019-10-31T19:18:58","guid":{"rendered":"https:\/\/prohoster.info\/blog\/podderzhka-monorepo-i-multirepo-v-werf-i-pri-chyom-zdes-docker-registry\/"},"modified":"2019-10-31T22:18:58","modified_gmt":"2019-10-31T19:18:58","slug":"podderzhka-monorepo-i-multirepo-v-werf-i-pri-chyom-zdes-docker-registry","status":"publish","type":"post","link":"https:\/\/prohoster.info\/en\/blog\/administrirovanie\/podderzhka-monorepo-i-multirepo-v-werf-i-pri-chyom-zdes-docker-registry","title":{"rendered":"Support for monorepo and multirepo in werf and its connection to Docker Registry","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p><img decoding=\"async\" alt=\"Support for monorepo and multirepo in werf and its connection to Docker Registry\" src=\"\/wp-content\/uploads\/2019\/09\/7bd2036d8e53b04965212698a209d4c7.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nThe topic of monorepositories has been discussed numerous times and typically sparks quite active debates. When creating <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/flant\/werf\">werf<\/a><\/noindex> as an Open Source tool aimed at improving the process of building application code from Git into Docker images (and their subsequent delivery to Kubernetes), we rarely ponder which choice is better. Our primary goal is to provide everything necessary for supporters of different opinions (as long as it doesn't contradict common sense, of course).<\/p>\n<p>The recently introduced support for mono-repo in werf is a good example of this. But first, let's clarify how this support is related to using werf and what Docker Registry has to do with it\u2026<noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/p>\n<h2>Issues<\/h2>\n<p>\nImagine this situation. In a company, there are numerous development teams working on independent projects. Most applications operate in Kubernetes, meaning they are containerized. For storing containers and images, a registry is required. The company uses Docker Hub with a single account <code>COMPANY<\/code>. Similar to most source code management systems, <b>Docker Hub does not allow the creation of a nested hierarchy of repositories<\/b>, such as <code>COMPANY\/PROJECT\/IMAGE<\/code>. In this case\u2026 how do you store non-monolithic applications in the registry without creating a separate account for each project? <\/p>\n<p><img decoding=\"async\" alt=\"Support for monorepo and multirepo in werf and its connection to Docker Registry\" src=\"\/wp-content\/uploads\/2019\/09\/b7905fab48723a123bee536e1fe56c5a.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nPerhaps the situation described is familiar to some, but let's consider the question of organizing application storage in general, i.e., without tying it to the example and Docker Hub mentioned above.<\/p>\n<h3>Solutions<\/h3>\n<p>\nIf the application <b>is monolithic<\/b>, there are no issues, and we simply store the images in the project's container registry.<\/p>\n<p>When the application is represented by several components, <b>microservices<\/b>, a specific approach is required. Taking the example of a typical web application consisting of two images: <code>frontend<\/code> and <code>backend<\/code> \u2014 possible options are:<\/p>\n<ol>\n<li> Store images in separate nested repositories:\n<p><img decoding=\"async\" alt=\"Support for monorepo and multirepo in werf and its connection to Docker Registry\" src=\"\/wp-content\/uploads\/2019\/09\/a05bfdaec10ea7b4542200c6a2bb4939.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/li>\n<li> Store everything in one repository, considering the image name in the tag, for example, as follows:\n<p><img decoding=\"async\" alt=\"Support for monorepo and multirepo in werf and its connection to Docker Registry\" src=\"\/wp-content\/uploads\/2019\/09\/83498b5bcdf7a57dfe933295e78fc785.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/li>\n<\/ol>\n<p>\n<i><b>NB<\/b>: Actually, there is another option for saving in different repositories, <code>PROJECT-frontend<\/code> and <code>PROJECT-backend<\/code>, but we will not consider it due to the complexity of support, organization, and distribution of rights among users.<\/i><\/p>\n<h2>Support in werf<\/h2>\n<p>\nInitially, werf was limited to nested repositories \u2014 fortunately, most registries support this feature. Starting from version <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/flant\/werf\/releases\/tag\/v1.0.4-alpha.3\">v1.0.4-alpha.3<\/a><\/noindex>, support for registries that <b>do not support nesting<\/b>, including Docker Hub, has been added. From this moment on, users have a choice of how to store application images.<\/p>\n<p>The implementation is available under the option <code>--images-repo-mode=multirepo|monorepo<\/code> (by default, <code>multirepo<\/code>, i.e., storage in nested repositories). It defines the patterns by which images are stored in the registry. Simply choose the desired mode when using the main commands, and everything else will remain unchanged.<\/p>\n<p>Since most werf options can be set <b>via environment variables<\/b>, in CI\/CD systems, the storage mode can usually be easily specified globally for the entire project. For example, <b>in the case of GitLab<\/b> , it is sufficient to add an environment variable in the project settings: <i>Settings -&gt; CI \/ CD -&gt; Variables: <code>WERF_IMAGES_REPO_MODE: multirepo|monorepo<\/code><\/i>.<\/p>\n<p>When it comes to publishing images and deploying applications (you can read in detail about these processes in the relevant sections of the documentation: <noindex><a rel=\"nofollow\" href=\"https:\/\/werf.io\/documentation\/reference\/publish_process.html\">Publish process<\/a><\/noindex> and <noindex><a rel=\"nofollow\" href=\"https:\/\/werf.io\/documentation\/reference\/deploy_process\/deploy_into_kubernetes.html\">Deploy process<\/a><\/noindex>), the mode merely defines the template for working with the image.<\/p>\n<h3>The devil is in the details.<\/h3>\n<p>\nThe distinction and primary difficulty in adding a new storage method lies in the process of cleaning the registry <i>(for cleaning capabilities supported in werf, see <noindex><a rel=\"nofollow\" href=\"https:\/\/werf.io\/documentation\/reference\/cleaning_process.html\">Cleaning process<\/a><\/noindex>)<\/i>.<\/p>\n<p>). When cleaning, werf takes into account the images used in Kubernetes clusters, as well as the policies configured by the user. The policies are based on the categorization of tags into strategies. The currently supported strategies are:<\/p>\n<ol>\n<li> 3 strategies related to Git primitives such as tag, branch, and commit;<\/li>\n<li> 1 strategy for arbitrary user-defined tags.<\/li>\n<\/ol>\n<p>\nWe save information about the tag strategy when publishing the image in the labels of the final image. The value itself \u2014 the so-called <b>meta tag<\/b> \u2014 is necessary for applying part of the policies. For example, when deleting a branch or tag from a Git repository, it makes sense to also delete any associated <i>unused<\/i> images from the registry, which is covered by part of our policies.<\/p>\n<p>When stored in a single repository (<code>monorepo<\/code>), within the image tag, besides the meta tag, the image name can also be stored: <code>PROJECT:<b>frontend<\/b>-META-TAG<\/code>. To separate them, we did not introduce any specific delimiter, but simply added the necessary value to the label of the final image at publication.<\/p>\n<p><i><b>NB<\/b>: If you are interested in seeing everything described in the source code of werf, you can start at <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/flant\/werf\/pull\/1684\/files\">PR 1684<\/a><\/noindex>.<\/i><\/p>\n<p>In this article, we will not focus further on the issues and justification of our approach: regarding tagging strategies, data storage in labels, and the publishing process as a whole\u2014everything about this is detailed in Dmitry Stolyarov's recent report: \"<noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/flant\/blog\/460351\/\">werf is our tool for CI\/CD in Kubernetes<\/a><\/noindex>\u00bb.<\/p>\n<h2>In summary<\/h2>\n<p>\nThe lack of support for registry without nesting was not a blocking factor for us or the known users of werf\u2014since it is always possible to set up a separate image registry (or switch to the hypothetical Container Registry in Google Cloud)\u2026 However, removing such a limitation seemed logical in order for the tool to be more convenient for a broader DevOps community. In implementing this, we faced the main challenge of reworking the container registry cleanup mechanism. Now that everything is ready, it\u2019s nice to realize that it has become easier for someone, and we (as the main developers of the project) do not foresee significant difficulties in further supporting this feature.<\/p>\n<p>Stay with us, and soon we will tell you about other innovations in <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/flant\/werf\">werf<\/a><\/noindex>!<\/p>\n<h2>P.S.<\/h2>\n<p>\nAlso read in our blog:<\/p>\n<ul>\n<li> \u00ab<noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/flant\/blog\/463613\/\">You can now build Docker images in werf using a regular Dockerfile<\/a><\/noindex>\u00bb;<\/li>\n<li> \u00ab<noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/flant\/blog\/460351\/\">werf is our tool for CI\/CD in Kubernetes (overview and video report)<\/a><\/noindex>\u00bb.<\/li>\n<\/ul>\n<p>Source: <a content=\"nofollow\" rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/flant\/blog\/465131\/\">habr.com<\/a><\/p>","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"excerpt":{"rendered":"<p>\u0422\u0435\u043c\u0430 \u043c\u043e\u043d\u043e\u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u044f \u043e\u0431\u0441\u0443\u0436\u0434\u0430\u043b\u0430\u0441\u044c \u0443\u0436\u0435 \u043d\u0435 \u0440\u0430\u0437 \u0438, \u043a\u0430\u043a \u043f\u0440\u0430\u0432\u0438\u043b\u043e, \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u0442 \u0432\u0435\u0441\u044c\u043c\u0430 \u0430\u043a\u0442\u0438\u0432\u043d\u044b\u0435 \u0441\u043f\u043e\u0440\u044b. \u0421\u043e\u0437\u0434\u0430\u0432\u0430\u044f werf \u043a\u0430\u043a Open Source-\u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442, \u043f\u0440\u0438\u0437\u0432\u0430\u043d\u043d\u044b\u0439 \u0443\u043b\u0443\u0447\u0448\u0438\u0442\u044c \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u044b \u0441\u0431\u043e\u0440\u043a\u0438 \u043a\u043e\u0434\u0430 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0439 \u0438\u0437 Git \u0432 Docker-\u043e\u0431\u0440\u0430\u0437\u044b (\u0438 \u0438\u0445 \u043f\u043e\u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0439 \u0434\u043e\u0441\u0442\u0430\u0432\u043a\u0438 \u0432 Kubernetes), \u043c\u044b \u043c\u0430\u043b\u043e \u0440\u0430\u0437\u043c\u044b\u0448\u043b\u044f\u0435\u043c \u043d\u0430 \u0442\u0435\u043c\u0443 \u0442\u043e\u0433\u043e, \u043a\u0430\u043a\u043e\u0439 \u0432\u044b\u0431\u043e\u0440 \u043b\u0443\u0447\u0448\u0435. \u0414\u043b\u044f \u043d\u0430\u0441 \u043f\u0435\u0440\u0432\u0438\u0447\u043d\u043e \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0438\u0442\u044c \u0432\u0441\u0451 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0435 \u0434\u043b\u044f \u0441\u0442\u043e\u0440\u043e\u043d\u043d\u0438\u043a\u043e\u0432 \u0440\u0430\u0437\u043d\u044b\u0445 \u043c\u043d\u0435\u043d\u0438\u0439 (\u0435\u0441\u043b\u0438 \u044d\u0442\u043e [&hellip;]<\/p>\n","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"author":1,"featured_media":28270,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[688],"tags":[],"class_list":["post-37667","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-administrirovanie"],"aioseo_notices":[],"aioseo_head":"\n\t\t<!-- All in One SEO 5.0.1.1 - aioseo.com -->\n\t<meta name=\"description\" content=\"\u0422\u0435\u043c\u0430 \u043c\u043e\u043d\u043e\u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u044f.\" \/>\n\t<meta name=\"robots\" content=\"max-image-preview:large\" \/>\n\t<meta name=\"author\" content=\"Yuri Gagarin\"\/>\n\t<link rel=\"canonical\" href=\"https:\/\/prohoster.info\/en\/blog\/administrirovanie\/podderzhka-monorepo-i-multirepo-v-werf-i-pri-chyom-zdes-docker-registry\" \/>\n\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.1.1\" \/>\n\t\t<meta property=\"og:locale\" content=\"en_US\" \/>\n\t\t<meta property=\"og:site_name\" content=\"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b\" \/>\n\t\t<meta property=\"og:type\" content=\"article\" \/>\n\t\t<meta property=\"og:title\" content=\"\ud83e\udd47\u041f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0430 monorepo \u0438 multirepo \u0432 werf \u0438 \u043f\u0440\u0438 \u0447\u0451\u043c \u0437\u0434\u0435\u0441\u044c Docker Registry | ProHoster\" \/>\n\t\t<meta property=\"og:description\" content=\"\u0422\u0435\u043c\u0430 \u043c\u043e\u043d\u043e\u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u044f.\" \/>\n\t\t<meta property=\"og:url\" content=\"https:\/\/prohoster.info\/en\/blog\/administrirovanie\/podderzhka-monorepo-i-multirepo-v-werf-i-pri-chyom-zdes-docker-registry\" \/>\n\t\t<meta property=\"og:image\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:secure_url\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:width\" content=\"350\" \/>\n\t\t<meta property=\"og:image:height\" content=\"350\" \/>\n\t\t<meta property=\"article:published_time\" content=\"2019-10-31T19:18:58+00:00\" \/>\n\t\t<meta property=\"article:modified_time\" content=\"2019-10-31T19:18:58+00:00\" \/>\n\t\t<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<meta property=\"article:author\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<!-- All in One SEO -->\n\n","aioseo_head_json":{"title":"\ud83e\udd47Support for monorepo and multirepo in werf and what it has to do with Docker Registry | ProHoster","description":"The topic of the monorepo.","canonical_url":"https:\/\/prohoster.info\/en\/blog\/administrirovanie\/podderzhka-monorepo-i-multirepo-v-werf-i-pri-chyom-zdes-docker-registry","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"en_US","og:site_name":"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b","og:type":"article","og:title":"\ud83e\udd47\u041f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0430 monorepo \u0438 multirepo \u0432 werf \u0438 \u043f\u0440\u0438 \u0447\u0451\u043c \u0437\u0434\u0435\u0441\u044c Docker Registry | ProHoster","og:description":"\u0422\u0435\u043c\u0430 \u043c\u043e\u043d\u043e\u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u044f.","og:url":"https:\/\/prohoster.info\/en\/blog\/administrirovanie\/podderzhka-monorepo-i-multirepo-v-werf-i-pri-chyom-zdes-docker-registry","og:image":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:secure_url":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:width":350,"og:image:height":350,"article:published_time":"2019-10-31T19:18:58+00:00","article:modified_time":"2019-10-31T19:18:58+00:00","article:publisher":"https:\/\/www.facebook.com\/prohoster","article:author":"https:\/\/www.facebook.com\/prohoster"},"aioseo_meta_data":{"post_id":"37667","title":null,"description":null,"keywords":null,"keyphrases":null,"primary_term":null,"canonical_url":null,"og_title":null,"og_description":null,"og_object_type":"default","og_image_type":"default","og_image_url":null,"og_image_width":null,"og_image_height":null,"og_image_custom_url":null,"og_image_custom_fields":null,"og_video":null,"og_custom_url":null,"og_article_section":null,"og_article_tags":null,"twitter_use_og":false,"twitter_card":"default","twitter_image_type":"default","twitter_image_url":null,"twitter_image_custom_url":null,"twitter_image_custom_fields":null,"twitter_title":null,"twitter_description":null,"schema":{"blockGraphs":[],"customGraphs":[],"default":{"data":{"Article":[],"Course":[],"Dataset":[],"FAQPage":[],"Movie":[],"Person":[],"Product":[],"ProductReview":[],"Car":[],"Recipe":[],"Service":[],"SoftwareApplication":[],"WebPage":[]},"graphName":"","isEnabled":true},"graphs":[]},"schema_type":null,"schema_type_options":null,"pillar_content":false,"robots_default":true,"robots_noindex":false,"robots_noarchive":false,"robots_nosnippet":false,"robots_nofollow":false,"robots_noimageindex":false,"robots_noodp":false,"robots_notranslate":false,"robots_max_snippet":null,"robots_max_videopreview":null,"robots_max_imagepreview":"large","priority":null,"frequency":null,"local_seo":null,"seo_analyzer_scan_date":"2026-01-23 18:48:19","breadcrumb_settings":null,"limit_modified_date":false,"reviewed_by":null,"ai":null,"created":"2021-03-01 01:22:29","updated":"2026-01-23 18:48:19","focus_keyword":null,"additional_keywords":null,"truseo_locale":null},"gt_translate_keys":[{"key":"link","format":"url"}],"_links":{"self":[{"href":"https:\/\/prohoster.info\/en\/wp-json\/wp\/v2\/posts\/37667","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/en\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/en\/wp-json\/wp\/v2\/comments?post=37667"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/en\/wp-json\/wp\/v2\/posts\/37667\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/prohoster.info\/en\/wp-json\/wp\/v2\/media\/28270"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/en\/wp-json\/wp\/v2\/media?parent=37667"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/en\/wp-json\/wp\/v2\/categories?post=37667"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/en\/wp-json\/wp\/v2\/tags?post=37667"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}