{"id":76769,"date":"2020-04-04T13:42:27","date_gmt":"2020-04-04T11:42:27","guid":{"rendered":"https:\/\/prohoster.info\/blog\/administrirovanie\/content-based-tagging-v-sborshhike-werf-zachem-i-kak-eto-rabotaet"},"modified":"2020-04-04T13:42:27","modified_gmt":"2020-04-04T11:42:27","slug":"content-based-tagging-v-sborshhike-werf-zachem-i-kak-eto-rabotaet","status":"publish","type":"post","link":"https:\/\/prohoster.info\/ro\/blog\/administrirovanie\/content-based-tagging-v-sborshhike-werf-zachem-i-kak-eto-rabotaet","title":{"rendered":"Tagging bazat pe con\u021binut \u00een compilatorul werf: de ce \u0219i cum func\u021bioneaz\u0103?","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p><img decoding=\"async\" alt=\"Tagging bazat pe con\u021binut \u00een compilatorul werf: de ce \u0219i cum func\u021bioneaz\u0103?\" src=\"\/wp-content\/uploads\/2020\/04\/494346bbee96cc2b6c838491ba1c67fb.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\n<noindex><a rel=\"nofollow\" href=\"https:\/\/werf.io\/\">werf<\/a><\/noindex> \u2014 utilitarul nostru CLI GitOps open-source pentru construirea \u0219i livrarea aplica\u021biilor \u00een Kubernetes. \u00cen <noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/flant\/blog\/493170\/\">versiunea v1.1<\/a><\/noindex> a fost introdus\u0103 o nou\u0103 func\u021bionalitate \u00een constructorul de imagini: etichetarea imaginilor bazat\u0103 pe con\u021binut sau <i>content-based tagging<\/i>. P\u00e2n\u0103 acum, schema tipic\u0103 de etichetare \u00een werf presupunea etichetarea imaginilor Docker \u00een func\u021bie de eticheta Git, ramura Git sau commit-ul Git. Dar toate aceste scheme au dezavantaje, care sunt complet rezolvate de noua strategie de etichetare. Detalii despre aceasta \u0219i de ce este at\u00e2t de bun\u0103 \u2014 mai jos.<noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/p>\n<h2>Deploiearea unui set de microservicii dintr-un singur Git-repozitoriu<\/h2>\n<p>\nSe \u00eent\u00e2lne\u0219te adesea situa\u021bia \u00een care aplica\u021bia este \u00eemp\u0103r\u021bit\u0103 \u00een mai multe servicii mai mult sau mai pu\u021bin independente. Rapoartele acestor servicii pot avea loc independent: un sau mai multe servicii pot fi livrate simultan, \u00een timp ce ceilal\u021bi trebuie s\u0103 continue s\u0103 func\u021bioneze f\u0103r\u0103 vreo modificare. Dar din perspectiva stoc\u0103rii codului \u0219i gestion\u0103rii proiectului, este mai convenabil s\u0103 p\u0103strezi aceste servicii ale aplica\u021biei \u00eentr-un singur repo.<\/p>\n<p>Exist\u0103 situa\u021bii \u00een care serviciile sunt cu adev\u0103rat independente \u0219i nu sunt legate de o singur\u0103 aplica\u021bie. \u00cen acest caz, acestea vor fi plasate \u00een proiecte separate \u0219i livrarea lor se va realiza prin procese CI\/CD separate \u00een fiecare dintre proiecte.<\/p>\n<p>Cu toate acestea, \u00een realitate, dezvoltatorii adesea \u00eempart o aplica\u021bie unic\u0103 \u00een mai multe microservicii, dar a crea un repo \u0219i un proiect separat pentru fiecare... \u2014 este un evident overkill. Despre aceast\u0103 situa\u021bie va fi vorba mai departe: mai multe astfel de microservicii se afl\u0103 \u00eentr-un singur repo de proiect \u0219i livr\u0103rile au loc printr-un singur proces \u00een CI\/CD.<\/p>\n<h3>Etichetarea pe baza ramurii Git \u0219i etichetei Git<\/h3>\n<p>\nPresupunem c\u0103 se folose\u0219te cea mai r\u0103sp\u00e2ndit\u0103 strategie de etichetare \u2014 <i>tag-or-branch<\/i>. Pentru ramurile Git, imaginile sunt etichetate cu numele ramurii; pentru o ramur\u0103, la un moment dat exist\u0103 o singur\u0103 imagine publicat\u0103 cu numele acestei ramuri. Pentru etichetele Git, imaginile sunt etichetate corespunz\u0103tor cu numele etichetei.<\/p>\n<p>Atunci c\u00e2nd se creeaz\u0103 o nou\u0103 etichet\u0103 Git \u2014 de exemplu, la lansarea unei noi versiuni \u2014 pentru toate imaginile proiectului din Docker Registry va fi creat\u0103 o nou\u0103 etichet\u0103 Docker:<\/p>\n<ul>\n<li> <code>myregistry.org\/myproject\/frontend:v1.1.10<\/code><\/li>\n<li> <code>myregistry.org\/myproject\/myservice1:v1.1.10<\/code><\/li>\n<li> <code>myregistry.org\/myproject\/myservice2:v1.1.10<\/code><\/li>\n<li> <code>myregistry.org\/myproject\/myservice3:v1.1.10<\/code><\/li>\n<li> <code>myregistry.org\/myproject\/myservice4:v1.1.10<\/code><\/li>\n<li> <code>myregistry.org\/myproject\/myservice5:v1.1.10<\/code><\/li>\n<li> <code>myregistry.org\/myproject\/database:v1.1.10<\/code><\/li>\n<\/ul>\n<p>\nAceste noi nume de imagini sunt incluse prin \u0219abloane Helm \u00een configura\u021bia Kubernetes. La lansarea unui deployment cu comanda <code>werf deploy<\/code> , are loc actualizarea c\u00e2mpului <code>imagine<\/code> \u00een manifestele resurselor Kubernetes \u0219i reap\u0103sa resursele corespunz\u0103toare datorit\u0103 schimb\u0103rii numelui imaginii.<\/p>\n<p><b>Problema<\/b>: \u00een cazul \u00een care con\u021binutul imaginii nu s-a schimbat de la anteriora versiune (tag-ul Git), ci doar tag-ul Docker, se produce <i>o reap\u0103sare<\/i> a acestei aplica\u021bii \u0219i, \u00een consecin\u021b\u0103, este posibil un anumit timp mort. De\u0219i nu au fost motive reale pentru a efectua aceast\u0103 reap\u0103sare.<\/p>\n<p>Ca urmare, cu schema actual\u0103 de versionare, trebuie s\u0103 gestion\u0103m mai multe repozitorii Git separate \u0219i apare problema organiz\u0103rii lans\u0103rii acestor multiple repozitorii. \u00cen general, aceast\u0103 schem\u0103 devine aglomerat\u0103 \u0219i complex\u0103. Ar fi mai bine s\u0103 grup\u0103m mai multe servicii \u00eentr-un singur repozitoriu \u0219i s\u0103 cre\u0103m astfel de tag-uri Docker pentru a evita reap\u0103sarile inutile.<\/p>\n<h3>Versionarea pe baza commit-ului Git<\/h3>\n<p>\n\u00cen werf exist\u0103, de asemenea, o strategie de versionare legat\u0103 de commit-urile Git.<\/p>\n<p>Commit-ul Git este un identificator al con\u021binutului repozitoriului Git \u0219i depinde de istoricul modific\u0103rilor fi\u0219ierelor din repozitoriu, deci pare logic s\u0103-l folosim pentru a versiona imaginile \u00een Docker Registry.<\/p>\n<p>Cu toate acestea, versionarea pe baza commit-ului Git are acelea\u0219i dezavantaje ca \u0219i pe baza ramurilor Git sau tag-urilor Git:<\/p>\n<ul>\n<li> Ar putea fi creat un commit gol care nu schimb\u0103 fi\u0219iere, iar tag-ul Docker al imaginii va fi schimbat.<\/li>\n<li> Ar putea fi creat un commit de tip merge care nu schimb\u0103 fi\u0219iere, iar tag-ul Docker al imaginii va fi schimbat.<\/li>\n<li> Ar putea fi creat un commit care schimb\u0103 fi\u0219ierele din Git, care nu sunt importate \u00een imagine, iar tag-ul Docker al imaginii va fi din nou schimbat.<\/li>\n<\/ul>\n<p><\/p>\n<h2>Versionarea pe baza numelui ramurii Git nu reflect\u0103 versiunea imaginii.<\/h2>\n<p>\nExist\u0103 \u0219i o alt\u0103 problem\u0103 legat\u0103 de strategia de versionare pe baza ramurilor Git.<\/p>\n<p>Versionarea pe baza numelui ramurii func\u021bioneaz\u0103 at\u00e2ta timp c\u00e2t commit-urile acestei ramuri sunt adunate secven\u021bial \u00een ordinea cronologic\u0103.<\/p>\n<p>Dac\u0103 \u00een schema actual\u0103 utilizatorul va ini\u021bia reconstruirea unui vechi commit asociat cu un anumit branch, atunci werf va suprascrie imaginea cu tag-ul Docker corespunz\u0103tor versiunii reconstruit\u0103 a imaginii pentru vechiul commit. Deployment-urile care folosesc acest tag risc\u0103, \u00een momentul repornirii pod-urilor, s\u0103 efectueze pull pentru o alt\u0103 versiune a imaginii, ceea ce va duce la pierderea leg\u0103turii cu sistemul CI, rezult\u00e2nd o desincronizare.<\/p>\n<p>\u00cen plus, \u00een cazul unor push-uri succesive \u00eentr-o ramur\u0103 cu intervale scurte \u00eentre ele, vechiul commit poate fi compilat mai t\u00e2rziu dec\u00e2t unul mai nou: versiunea veche a imaginii pierde tag-ul nou al ramurii Git. Aceste probleme pot fi rezolvate de sistemele CI\/CD (de exemplu, \u00een GitLab CI, un pipeline este lansat pentru seria de commits ultime). Totu\u0219i, nu toate sistemele sus\u021bin acest lucru \u0219i ar trebui s\u0103 existe o modalitate mai fiabil\u0103 de a preveni o problem\u0103 at\u00e2t de fundamental\u0103.<\/p>\n<h2>Ce este tagging-ul bazat pe con\u021binut?<\/h2>\n<p>\nDeci, ce este tagging-ul bazat pe con\u021binut \u2014 etichetarea imaginilor \u00een func\u021bie de con\u021binut.<\/p>\n<p>Pentru crearea tag-urilor Docker nu sunt folosite primitivele Git (branch Git, tag Git\u2026), ci un hash asociat cu:<\/p>\n<ul>\n<li> <i>con\u021binutul imaginii<\/i>. Identificatorul-tag al imaginii reflect\u0103 con\u021binutul acesteia. La compilarea unei noi versiuni, acest identificator nu se va schimba dac\u0103 fi\u0219ierele din imagine nu au fost modificate;<\/li>\n<li> <i>istoria cre\u0103rii acestei imagini \u00een Git<\/i>. Imaginele asociate cu diferite ramuri Git \u0219i diferite istorii de compilare prin werf vor avea identificatori de tag-uri diferi\u021bi.<\/li>\n<\/ul>\n<p>\nCa atare, un astfel de identificator de tag este denumit <b>semn\u0103tura stadiilor imaginii<\/b>.<\/p>\n<p>Fiecare imagine este compus\u0103 dintr-un set de etape: <code>from<\/code>, <code>before-install<\/code>, <code>git-archive<\/code>, <code>install<\/code>, <code>imports-after-install<\/code>, <code>before-setup<\/code>,\u2026 <code>git-latest-patch<\/code> \u0219.a.m.d. Fiecare etap\u0103 are un identificator care reflect\u0103 con\u021binutul s\u0103u \u2014 <b>semn\u0103tura etapei<\/b> <i>(stage signature)<\/i>.<\/p>\n<p>Imaginea final\u0103, format\u0103 din aceste etape, este etichetat\u0103 cu a\u0219a-numita semn\u0103tur\u0103 a setului acestor etape \u2014 <b>stages signature<\/b>, \u2014 care este generalizatoare pentru toate etapele imaginii.<\/p>\n<p>Fiecare imagine din configura\u021bie <code>werf.yaml<\/code> \u00een general va avea o astfel de semn\u0103tur\u0103 \u0219i, \u00een consecin\u021b\u0103, un tag Docker.<\/p>\n<p>Semn\u0103tura stadiilor rezolv\u0103 toate problemele men\u021bionate:<\/p>\n<ul>\n<li> Este rezistent\u0103 la commit-urile Git goale.<\/li>\n<li> Este rezistent\u0103 la commit-urile Git care modific\u0103 fi\u0219iere care nu sunt relevante pentru imagine.<\/li>\n<li> Nu duce la problema de suprascriere a versiunii actuale a imaginii \u00een timpul relans\u0103rii compil\u0103rilor pentru vechile commit-uri Git din ramur\u0103.<\/li>\n<\/ul>\n<p>\nAceasta este acum strategia de etichetare recomandat\u0103 \u0219i este utilizat\u0103 implicit \u00een werf pentru toate sistemele CI.<\/p>\n<h2>Cum s\u0103 activa\u021bi \u0219i s\u0103 utiliza\u021bi \u00een werf<\/h2>\n<p>\nOp\u021biunea corespunz\u0103toare a fost introdus\u0103 pentru comanda <code>werf publish<\/code>: <code>--tag-by-stages-signature=true|false<\/code><\/p>\n<p>\u00cen sistemul CI, strategia de etichetare este specificat\u0103 prin comanda <code>werf ci-env<\/code>. Anterior, pentru aceasta se definea parametrul <code>werf ci-env --tagging-strategy=tag-or-branch<\/code>. Acum, dac\u0103 specifica\u021bi <code>werf ci-env --tagging-strategy=stages-signature<\/code> sau nu specifica\u021bi aceast\u0103 op\u021biune, werf va folosi implicit strategia de etichetare <code>stages-signature<\/code>. Comanda <code>werf ci-env<\/code> va seta automat flag-urile necesare pentru comanda <code>werf build-and-publish<\/code> (sau <code>werf publish<\/code>), de aceea nu este nevoie s\u0103 specifica\u021bi op\u021biuni suplimentare pentru aceste comenzi.<\/p>\n<p>De exemplu, comanda:<\/p>\n<pre><code class=\"plaintext\">werf publish --stages-storage :local --images-repo registry.hello.com\/web\/core\/system --tag-by-stages-signature<\/code><\/pre>\n<p>\n\u2026 poate crea urm\u0103toarele imagini:<\/p>\n<ul>\n<li> <code>registry.hello.com\/web\/core\/system\/backend:4ef339f84ca22247f01fb335bb19f46c4434014d8daa3d5d6f0e386d<\/code><\/li>\n<li> <code>registry.hello.com\/web\/core\/system\/frontend:f44206457e0a4c8a54655543f749799d10a9fe945896dab1c16996c6<\/code><\/li>\n<\/ul>\n<p>\nAici <code>4ef339f84ca22247f01fb335bb19f46c4434014d8daa3d5d6f0e386d<\/code> \u2014 aceasta este semn\u0103tura stadiilor imaginii <code>backend<\/code>, iar <code>f44206457e0a4c8a54655543f749799d10a9fe945896dab1c16996c6<\/code> \u2014 semn\u0103tura stadiilor imaginii <code>frontend<\/code>.<\/p>\n<p>C\u00e2nd utiliza\u021bi func\u021bii speciale <code>werf_container_image<\/code> \u0219i <code>werf_container_env<\/code> \u00een \u0219abloanele Helm nu este nevoie s\u0103 schimba\u021bi nimic: aceste func\u021bii vor genera automat numele corecte pentru imagini.<\/p>\n<p>Exemplu de configurare \u00een sistemul CI:<\/p>\n<pre><code class=\"plaintext\">type multiwerf &amp;&amp; source &lt;(multiwerf use 1.1 beta)\ntype werf &amp;&amp; source &lt;(werf ci-env gitlab)\nwerf build-and-publish|deploy<\/code><\/pre>\n<p>\nMai multe informa\u021bii despre configurare sunt disponibile \u00een documenta\u021bie:<\/p>\n<ul>\n<li> <noindex><a rel=\"nofollow\" href=\"https:\/\/ru.werf.io\/v1.1\/documentation\/reference\/publish_process.html#%D1%82%D0%B5%D0%B3%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5-%D0%BE%D0%B1%D1%80%D0%B0%D0%B7%D0%BE%D0%B2-%D0%BF%D0%BE-%D1%81%D0%BE%D0%B4%D0%B5%D1%80%D0%B6%D0%B8%D0%BC%D0%BE%D0%BC%D1%83\">Ghid \u2192 Publicare (publish)<\/a><\/noindex>;<\/li>\n<li> <noindex><a rel=\"nofollow\" href=\"https:\/\/ru.werf.io\/v1.1\/documentation\/reference\/plugging_into_cicd\/overview.html#stages-signature\">Lucrul cu CI\/CD \u2192 Informa\u021bii generale \u2192 stages-signature<\/a><\/noindex>;<\/li>\n<li> <noindex><a rel=\"nofollow\" href=\"https:\/\/ru.werf.io\/v1.1\/documentation\/guides\/gitlab_ci_cd_integration.html#gitlab-ciyml\">Integrarea cu GitLab CI\/CD \u2192 .gitlab-ci.yml<\/a><\/noindex>.<\/li>\n<\/ul>\n<p><\/p>\n<h2>\u00cen concluzie<\/h2>\n<p><\/p>\n<ul>\n<li> O nou\u0103 op\u021biune <code>werf publish --tag-by-stages-signature=true|false<\/code>.<\/li>\n<li> Nou\u0103 valoare a op\u021biunii <code>werf ci-env --tagging-strategy=stages-signature|tag-or-branch<\/code> (dac\u0103 nu este specificat\u0103, va fi implicit <code>stages-signature<\/code>).<\/li>\n<li> Dac\u0103 anterior a fost utilizat\u0103 etichetarea pe baza comitelor Git (<code>WERF_TAG_GIT_COMMIT<\/code> sau op\u021biunea <code>werf publish --tag-git-commit COMMIT<\/code>), atunci este imperativ s\u0103 schimba\u021bi strategia de etichetare <i>stages-signature<\/i>.<\/li>\n<li> Proiectele noi ar trebui s\u0103 fie imediat setate pe noul sistem de etichetare.<\/li>\n<li> Proiectele vechi, c\u00e2nd sunt migrate la werf 1.1, ar trebui s\u0103 fie setate pe noul sistem de etichetare, dar vechiul <i>tag-or-branch<\/i> este \u00een continuare suportat.<\/li>\n<\/ul>\n<p>\nEtichetarea bazat\u0103 pe con\u021binut rezolv\u0103 toate problemele men\u021bionate \u00een articol:<\/p>\n<ul>\n<li> Stabilitatea numelui etichetei Docker fa\u021b\u0103 de comitele Git goale.<\/li>\n<li> Stabilitatea numelui etichetei Docker fa\u021b\u0103 de comitele Git care modific\u0103 fi\u0219iere nerelevante pentru imagine.<\/li>\n<li> Nu duce la o problem\u0103 de suprascriere a versiunii actuale a imaginii atunci c\u00e2nd se repornesc construc\u021biile pentru commituri vechi de Git pentru ramurile Git.<\/li>\n<\/ul>\n<p>\nFolosi\u021bi-l! \u0218i nu uita\u021bi s\u0103 ne vizita\u021bi pe <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/flant\/werf\">GitHub<\/a><\/noindex>, pentru a crea o problem\u0103 sau a g\u0103si una existent\u0103, a ad\u0103uga un vot, a crea un PR sau pur \u0219i simplu a observa dezvoltarea proiectului.<\/p>\n<h2>P.S.<\/h2>\n<p>\nCiti\u021bi \u0219i \u00een blogul nostru:<\/p>\n<ul>\n<li> \u00ab<noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/flant\/blog\/493170\/\">Lansarea werf 1.1: \u00eembun\u0103t\u0103\u021biri \u00een constructor ast\u0103zi \u0219i planuri de viitor<\/a><\/noindex>\u00bb<\/li>\n<li> \u00ab<noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/flant\/blog\/481306\/\">Prezent\u0103m werf 1.0 stabil: ce leg\u0103tur\u0103 are cu GitOps, statutul \u0219i planurile<\/a><\/noindex>\u00bb<\/li>\n<li> \u00ab<noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/flant\/blog\/460351\/\">werf \u2014 our tool for CI\/CD in Kubernetes (overview and presentation video)<\/a><\/noindex>\u00bb;<\/li>\n<li> Utilizarea werf pentru lansarea chart-urilor complexe Helm\n<ul>\n<li> \u00ab<noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/flant\/blog\/476646\/\">Mergerea 3-way \u00een werf: implementare \u00een Kubernetes cu Helm \u201epe steroizi\u201d<\/a><\/noindex>\u00bb;<\/li>\n<li> \u00ab<noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/flant\/blog\/468049\/\">Utilizarea werf pentru implementarea chart-urilor complex Helm<\/a><\/noindex>\u00bb;<\/li>\n<li> \u00ab<noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/flant\/blog\/465131\/\">Suport pentru monorepo \u0219i multirepo \u00een werf \u0219i ce leg\u0103tur\u0103 are cu Docker Registry<\/a><\/noindex>\u00bb;<\/li>\n<li> \u00ab<noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/flant\/blog\/463613\/\">Acum, pute\u021bi construi imagini Docker \u00een werf \u0219i folosind un Dockerfile obi\u0219nuit<\/a><\/noindex>\u00bb.<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<p>Sursa: <a content=\"nofollow\" rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/flant\/blog\/495112\/\">habr.com<\/a> <\/p>","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"excerpt":{"rendered":"<p>werf \u2014 \u043d\u0430\u0448\u0430 GitOps CLI-\u0443\u0442\u0438\u043b\u0438\u0442\u0430 \u0441 \u043e\u0442\u043a\u0440\u044b\u0442\u044b\u043c \u043a\u043e\u0434\u043e\u043c \u0434\u043b\u044f \u0441\u0431\u043e\u0440\u043a\u0438 \u0438 \u0434\u043e\u0441\u0442\u0430\u0432\u043a\u0438 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0439 \u0432 Kubernetes. \u0412 \u0440\u0435\u043b\u0438\u0437\u0435 v1.1 \u0431\u044b\u043b\u0430 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0430 \u043d\u043e\u0432\u0430\u044f \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u0432 \u0441\u0431\u043e\u0440\u0449\u0438\u043a\u0435 \u043e\u0431\u0440\u0430\u0437\u043e\u0432: \u0442\u0435\u0433\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u043e\u0431\u0440\u0430\u0437\u043e\u0432 \u043f\u043e \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u043c\u043e\u043c\u0443 \u0438\u043b\u0438 content-based tagging. \u0414\u043e \u0441\u0438\u0445 \u043f\u043e\u0440 \u0442\u0438\u043f\u0438\u0447\u043d\u0430\u044f \u0441\u0445\u0435\u043c\u0430 \u0442\u0435\u0433\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0432 werf \u043f\u0440\u0435\u0434\u043f\u043e\u043b\u0430\u0433\u0430\u043b\u0430 \u0442\u0435\u0433\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 Docker-\u043e\u0431\u0440\u0430\u0437\u043e\u0432 \u043f\u043e Git-\u0442\u0435\u0433\u0443, Git-\u0432\u0435\u0442\u043a\u0435 \u0438\u043b\u0438 Git-\u043a\u043e\u043c\u043c\u0438\u0442\u0443. \u041d\u043e \u0443 \u0432\u0441\u0435\u0445 \u044d\u0442\u0438\u0445 \u0441\u0445\u0435\u043c \u0435\u0441\u0442\u044c \u043d\u0435\u0434\u043e\u0441\u0442\u0430\u0442\u043a\u0438, [&hellip;]<\/p>\n","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"author":1,"featured_media":76770,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[688],"tags":[],"class_list":["post-76769","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.2.1 - aioseo.com -->\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\/ro\/blog\/administrirovanie\/content-based-tagging-v-sborshhike-werf-zachem-i-kak-eto-rabotaet\" \/>\n\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.2.1\" \/>\n\t\t<meta property=\"og:locale\" content=\"ro_RO\" \/>\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\udd47Content-based tagging \u0432 \u0441\u0431\u043e\u0440\u0449\u0438\u043a\u0435 werf: \u0437\u0430\u0447\u0435\u043c \u0438 \u043a\u0430\u043a \u044d\u0442\u043e \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442? | ProHoster\" \/>\n\t\t<meta property=\"og:url\" content=\"https:\/\/prohoster.info\/ro\/blog\/administrirovanie\/content-based-tagging-v-sborshhike-werf-zachem-i-kak-eto-rabotaet\" \/>\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=\"2020-04-04T11:42:27+00:00\" \/>\n\t\t<meta property=\"article:modified_time\" content=\"2020-04-04T11:42:27+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\udd47Etichetarea bazat\u0103 pe con\u021binut \u00een constructorul werf: de ce \u0219i cum func\u021bioneaz\u0103? | ProHoster","description":"","canonical_url":"https:\/\/prohoster.info\/ro\/blog\/administrirovanie\/content-based-tagging-v-sborshhike-werf-zachem-i-kak-eto-rabotaet","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"ro_RO","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\udd47Content-based tagging \u0432 \u0441\u0431\u043e\u0440\u0449\u0438\u043a\u0435 werf: \u0437\u0430\u0447\u0435\u043c \u0438 \u043a\u0430\u043a \u044d\u0442\u043e \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442? | ProHoster","og:url":"https:\/\/prohoster.info\/ro\/blog\/administrirovanie\/content-based-tagging-v-sborshhike-werf-zachem-i-kak-eto-rabotaet","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":"2020-04-04T11:42:27+00:00","article:modified_time":"2020-04-04T11:42:27+00:00","article:publisher":"https:\/\/www.facebook.com\/prohoster","article:author":"https:\/\/www.facebook.com\/prohoster"},"aioseo_meta_data":{"post_id":"76769","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":null,"breadcrumb_settings":null,"limit_modified_date":false,"reviewed_by":null,"ai":null,"created":"2021-02-28 17:30:22","updated":"2022-09-28 05:59:33","focus_keyword":null,"additional_keywords":null,"truseo_locale":null},"gt_translate_keys":[{"key":"link","format":"url"}],"_links":{"self":[{"href":"https:\/\/prohoster.info\/ro\/wp-json\/wp\/v2\/posts\/76769","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/ro\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/ro\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/ro\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/ro\/wp-json\/wp\/v2\/comments?post=76769"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/ro\/wp-json\/wp\/v2\/posts\/76769\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/prohoster.info\/ro\/wp-json\/wp\/v2\/media\/76770"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/ro\/wp-json\/wp\/v2\/media?parent=76769"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/ro\/wp-json\/wp\/v2\/categories?post=76769"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/ro\/wp-json\/wp\/v2\/tags?post=76769"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}