{"id":22972,"date":"2026-04-24T01:15:39","date_gmt":"2026-04-24T01:15:39","guid":{"rendered":"https:\/\/umang.pk\/2026\/04\/24\/%db%81%d9%85-%d9%86%db%92-%d8%ac%db%8c%d9%86%da%a9%d9%86%d8%b2%d8%8c-%da%88%d9%88%da%a9%d8%b1-%da%a9%d9%85%d9%be%d9%88%d8%b2%d8%8c-%d8%a7%d9%88%d8%b1-%d9%b9%d8%b1%db%8c%d9%81%db%8c%da%a9-%da%a9%d8%a7\/"},"modified":"2026-04-24T01:15:39","modified_gmt":"2026-04-24T01:15:39","slug":"%db%81%d9%85-%d9%86%db%92-%d8%ac%db%8c%d9%86%da%a9%d9%86%d8%b2%d8%8c-%da%88%d9%88%da%a9%d8%b1-%da%a9%d9%85%d9%be%d9%88%d8%b2%d8%8c-%d8%a7%d9%88%d8%b1-%d9%b9%d8%b1%db%8c%d9%81%db%8c%da%a9-%da%a9%d8%a7","status":"publish","type":"post","link":"https:\/\/umang.pk\/ur\/2026\/04\/24\/%db%81%d9%85-%d9%86%db%92-%d8%ac%db%8c%d9%86%da%a9%d9%86%d8%b2%d8%8c-%da%88%d9%88%da%a9%d8%b1-%da%a9%d9%85%d9%be%d9%88%d8%b2%d8%8c-%d8%a7%d9%88%d8%b1-%d9%b9%d8%b1%db%8c%d9%81%db%8c%da%a9-%da%a9%d8%a7\/","title":{"rendered":"\u06c1\u0645 \u0646\u06d2 \u062c\u06cc\u0646\u06a9\u0646\u0632\u060c \u0688\u0648\u06a9\u0631 \u06a9\u0645\u067e\u0648\u0632\u060c \u0627\u0648\u0631 \u0679\u0631\u06cc\u0641\u06cc\u06a9 \u06a9\u0627 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u062a\u06d2 \u06c1\u0648\u0626\u06d2 \u0645\u0648\u0646\u0648\u0631\u06cc\u067e\u0648 \u067e\u0631 \u0645\u0628\u0646\u06cc \u0645\u0627\u0626\u06cc\u06a9\u0631\u0648 \u0633\u0631\u0648\u0633\u0632 \u0633\u0633\u0679\u0645 \u06a9\u06d2 \u0644\u06cc\u06d2 \u067e\u0631\u0648\u0688\u06a9\u0634\u0646 \u06a9\u06d2 \u0644\u06cc\u06d2 \u062a\u06cc\u0627\u0631 CI\/CD \u067e\u0627\u0626\u067e \u0644\u0627\u0626\u0646 \u06a9\u06cc\u0633\u06d2 \u0628\u0646\u0627\u0626\u06cc"},"content":{"rendered":"\n<div id=\"\">\n<p>\u06cc\u06c1 \u0679\u06cc\u0648\u0679\u0648\u0631\u06cc\u0644 \u0627\u06cc\u06a9 \u0648\u0627\u062d\u062f \u0644\u06cc\u0646\u06a9\u0633 \u0633\u0631\u0648\u0631 \u067e\u0631 \u062c\u06cc\u0646\u06a9\u0646\u0632\u060c \u0688\u0648\u06a9\u0631 \u06a9\u0645\u067e\u0648\u0632\u060c \u0627\u0648\u0631 \u0679\u0631\u06cc\u0641\u06a9 \u06a9\u0627 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u062a\u06d2 \u06c1\u0648\u0626\u06d2 \u067e\u06cc\u062f\u0627\u0648\u0627\u0631 \u06a9\u06d2 \u0644\u06cc\u06d2 \u062a\u06cc\u0627\u0631 CI\/CD \u067e\u0627\u0626\u067e \u0644\u0627\u0626\u0646 \u0628\u0646\u0627\u0646\u06d2 \u06a9\u06d2 \u0644\u06cc\u06d2 \u0627\u06cc\u06a9 \u0645\u06a9\u0645\u0644\u060c \u0639\u0645\u0644\u06cc \u0631\u06c1\u0646\u0645\u0627 \u06c1\u06d2\u06d4<\/p>\n<p>\u062e\u0648\u062f\u06a9\u0627\u0631 \u062a\u062c\u062f\u06cc\u062f \u06a9\u0631\u0646\u06d2 \u0648\u0627\u0644\u06d2 HTTPS \u06a9\u0627 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u062a\u06d2 \u06c1\u0648\u0626\u06d2 \u0627\u067e\u0646\u06cc \u0645\u0631\u0636\u06cc \u06a9\u06d2 \u0688\u0648\u0645\u06cc\u0646 \u0645\u06cc\u06ba \u062e\u062f\u0645\u0627\u062a \u06a9\u0648 \u06a9\u0633 \u0637\u0631\u062d \u0638\u0627\u06c1\u0631 \u06a9\u0631\u0646\u0627 \u06c1\u06d2 \u0627\u0648\u0631 \u0627\u06cc\u06a9 \u0633\u0645\u0627\u0631\u0679 \u062a\u0639\u06cc\u0646\u0627\u062a\u06cc \u062d\u06a9\u0645\u062a \u0639\u0645\u0644\u06cc \u06a9\u0648 \u0646\u0627\u0641\u0630 \u06a9\u0631\u0646\u06d2 \u06a9\u0627 \u0637\u0631\u06cc\u0642\u06c1 \u0633\u06cc\u06a9\u06be\u06cc\u06ba \u062c\u0648 \u062a\u0628\u062f\u06cc\u0644\u06cc\u0648\u06ba \u06a9\u0627 \u067e\u062a\u06c1 \u0644\u06af\u0627\u062a\u06cc \u06c1\u06d2 \u0627\u0648\u0631 \u0635\u0631\u0641 \u0645\u062a\u0627\u062b\u0631\u06c1 \u0645\u0627\u0626\u06cc\u06a9\u0631\u0648 \u0633\u0631\u0648\u0633\u0632 \u06a9\u0648 \u062f\u0648\u0628\u0627\u0631\u06c1 \u062a\u0639\u06cc\u0646\u0627\u062a \u06a9\u0631\u062a\u06cc \u06c1\u06d2\u06d4 \u06cc\u06c1 \u063a\u06cc\u0631 \u0636\u0631\u0648\u0631\u06cc \u0645\u06a9\u0645\u0644 \u0627\u0633\u0679\u06cc\u06a9 \u06a9\u06cc \u062f\u0648\u0628\u0627\u0631\u06c1 \u062a\u0642\u0633\u06cc\u0645 \u06a9\u0648 \u0631\u0648\u06a9\u0646\u06d2 \u0645\u06cc\u06ba \u0645\u062f\u062f \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4 \u06c1\u0645 \u062d\u0642\u06cc\u0642\u06cc \u062f\u0646\u06cc\u0627 \u06a9\u06d2 \u067e\u06cc\u062f\u0627\u0648\u0627\u0631\u06cc \u0645\u0633\u0627\u0626\u0644 \u0627\u0648\u0631 \u06c1\u0631 \u0645\u0633\u0626\u0644\u06d2 \u06a9\u06d2 \u0644\u06cc\u06d2 \u062f\u0631\u0633\u062a \u0627\u0635\u0644\u0627\u062d\u0627\u062a \u06a9\u0627 \u0628\u06be\u06cc \u0627\u062d\u0627\u0637\u06c1 \u06a9\u0631\u06cc\u06ba \u06af\u06d2\u06d4<\/p>\n<h2 id=\"heading-table-of-contents\"><strong>\u0627\u0646\u0688\u06cc\u06a9\u0633<\/strong><\/h2>\n<h2 id=\"heading-1-what-youll-build\">1. \u06a9\u06cc\u0627 \u0628\u0646\u0627\u0646\u0627 \u06c1\u06d2\u06d4<\/h2>\n<p>\u0627\u0633 \u0679\u06cc\u0648\u0679\u0648\u0631\u06cc\u0644 \u0645\u06cc\u06ba\u060c \u0622\u067e \u0627\u06cc\u06a9 \u062c\u06cc\u0646\u06a9\u0646\u0632 \u0645\u062b\u0627\u0644 \u0628\u0646\u0627\u062a\u06d2 \u06c1\u06cc\u06ba \u062c\u0648 \u0622\u067e \u06a9\u06d2 \u0627\u06cc\u067e\u0644\u06cc\u06a9\u06cc\u0634\u0646 \u0627\u0633\u0679\u06cc\u06a9 \u06a9\u06d2 \u0637\u0648\u0631 \u067e\u0631 \u0627\u0633\u06cc \u0644\u06cc\u0646\u06a9\u0633 \u0633\u0631\u0648\u0631 \u067e\u0631 \u0688\u0648\u06a9\u0631 \u06a9\u06d2 \u0627\u0646\u062f\u0631 \u0686\u0644 \u0631\u06c1\u0627 \u06c1\u06d2\u06d4<\/p>\n<p>\u0679\u0631\u06cc\u0641\u06a9 \u062c\u06cc\u0646\u06a9\u0646\u0632 \u06a9\u06d2 \u0633\u0627\u0645\u0646\u06d2 \u0627\u06cc\u06a9 \u0631\u06cc\u0648\u0631\u0633 \u067e\u0631\u0627\u06a9\u0633\u06cc \u06a9\u06d2 \u0637\u0648\u0631 \u067e\u0631 \u06a9\u0627\u0645 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u060c \u0635\u0627\u0641 \u06cc\u0648 \u0622\u0631 \u0627\u06cc\u0644 \u0641\u0631\u0627\u06c1\u0645 \u06a9\u0631\u062a\u0627 \u06c1\u06d2 (<code>https:\/\/jenkins.example.com<\/code>) \u06a9\u06d2 \u0633\u0627\u062a\u06be <strong>\u062e\u0648\u062f \u06a9\u0627\u0631 \u0637\u0631\u06cc\u0642\u06d2 \u0633\u06d2 \u0642\u0627\u0628\u0644 \u062a\u062c\u062f\u06cc\u062f \u0622\u0626\u06cc\u06d2 \u0627\u0646\u06a9\u0631\u067e\u0679 \u0633\u0631\u0679\u06cc\u0641\u06a9\u06cc\u0679<\/strong>.<\/p>\n<p>\u06c1\u0645 \u0627\u06cc\u067e\u0644\u06cc\u06a9\u06cc\u0634\u0646 \u0631\u06cc\u067e\u0648\u0632\u0679\u0631\u06cc \u0645\u06cc\u06ba \u062f\u0631\u062c \u0630\u06cc\u0644 \u062c\u06cc\u0646\u06a9\u0646\u0632 \u0641\u0627\u0626\u0644 \u0628\u06be\u06cc \u0628\u0646\u0627\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4<\/p>\n<ul>\n<li>\n<p>\u062c\u0628 \u0628\u06be\u06cc \u0622\u067e \u062f\u06be\u06a9\u0627 \u062f\u06cc\u062a\u06d2 \u06c1\u06cc\u06ba \u062a\u0648 \u062e\u0648\u062f \u0628\u062e\u0648\u062f \u0645\u062a\u062d\u0631\u06a9 \u06c1\u0648\u062c\u0627\u062a\u0627 \u06c1\u06d2\u06d4 <code>staging<\/code> \u062f\u0631\u062e\u062a \u06a9\u06cc \u0634\u0627\u062e\u060c<\/p>\n<\/li>\n<li>\n<p>\u0645\u0639\u0644\u0648\u0645 \u06a9\u0631\u06cc\u06ba \u06a9\u06c1 \u06c1\u0631 \u06a9\u0645\u0679 \u0645\u06cc\u06ba \u06a9\u0648\u0646 \u0633\u06cc \u0645\u0627\u0626\u06cc\u06a9\u0631\u0648 \u0633\u0631\u0648\u0633\u0632 \u062a\u0628\u062f\u06cc\u0644 \u06c1\u0648\u0626\u06cc \u06c1\u06cc\u06ba\u06d4<\/p>\n<\/li>\n<li>\n<p>\u0627\u067e\u0646\u06d2 \u0645\u06cc\u0632\u0628\u0627\u0646 \u0633\u0633\u0679\u0645 \u0633\u06d2 \u062a\u0627\u0632\u06c1 \u062a\u0631\u06cc\u0646 \u06a9\u0648\u0688 \u062d\u0627\u0635\u0644 \u06a9\u0631\u06cc\u06ba\u06d4<\/p>\n<\/li>\n<li>\n<p>\u062f\u0648\u0628\u0627\u0631\u06c1 \u062a\u0639\u0645\u06cc\u0631 \u06a9\u0631\u06cc\u06ba \u0627\u0648\u0631 \u062f\u0648\u0628\u0627\u0631\u06c1 \u0634\u0631\u0648\u0639 \u06a9\u0631\u06cc\u06ba\u06d4 <strong>\u0635\u0631\u0641 \u0645\u062a\u0627\u062b\u0631\u06c1 \u062e\u062f\u0645\u0627\u062a<\/strong>.<\/p>\n<\/li>\n<\/ul>\n<p>\u06c1\u0631 \u062f\u06be\u06a9\u0627 \u0635\u0631\u0641 \u0645\u062a\u0639\u0644\u0642\u06c1 \u062e\u062f\u0645\u0627\u062a \u06a9\u0648 \u062f\u0648\u0628\u0627\u0631\u06c1 \u062a\u0642\u0633\u06cc\u0645 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<h3 id=\"heading-prerequisites\">\u0634\u0631\u0637\u06cc\u06ba<\/h3>\n<p>\u0634\u0631\u0648\u0639 \u06a9\u0631\u0646\u06d2 \u0633\u06d2 \u067e\u06c1\u0644\u06d2\u060c \u06cc\u06c1 \u06af\u0627\u0626\u06cc\u0688 \u0641\u0631\u0636 \u06a9\u0631\u062a\u0627 \u06c1\u06d2 \u06a9\u06c1 \u0622\u067e \u06a9\u0686\u06be \u0628\u0646\u06cc\u0627\u062f\u06cc \u062a\u0635\u0648\u0631\u0627\u062a \u0627\u0648\u0631 \u0679\u0648\u0644\u0632 \u0633\u06d2 \u067e\u06c1\u0644\u06d2 \u06c1\u06cc \u0648\u0627\u0642\u0641 \u06c1\u06cc\u06ba\u06d4<\/p>\n<p>\u06cc\u06c1 \u0627\u0628\u062a\u062f\u0627\u0626\u06cc \u0633\u0637\u062d \u06a9\u0627 \u0633\u0628\u0642 \u0646\u06c1\u06cc\u06ba \u06c1\u06d2\u06d4 \u0622\u067e \u0627\u0646\u0641\u0631\u0627\u0633\u0679\u0631\u06a9\u0686\u0631\u060c \u06a9\u0646\u0679\u06cc\u0646\u0631\u0632\u060c \u0627\u0648\u0631 CI\/CD \u067e\u0627\u0626\u067e \u0644\u0627\u0626\u0646\u0648\u06ba \u06a9\u06d2 \u0633\u0627\u062a\u06be \u0628\u0631\u0627\u06c1 \u0631\u0627\u0633\u062a \u06a9\u0627\u0645 \u06a9\u0631\u06cc\u06ba \u06af\u06d2\u06d4<\/p>\n<p>\u0622\u067e \u06a9\u0648 \u062f\u0631\u062c \u0630\u06cc\u0644 \u0686\u06cc\u0632\u0648\u06ba \u0633\u06d2 \u0622\u06af\u0627\u06c1 \u06c1\u0648\u0646\u0627 \u0686\u0627\u06c1\u06cc\u06d2:<\/p>\n<ul>\n<li>\n<p>\u0628\u0646\u06cc\u0627\u062f\u06cc \u0644\u06cc\u0646\u06a9\u0633 \u06a9\u0645\u0627\u0646\u0688\u0632 (SSH\u060c \u0641\u0627\u0626\u0644 \u0633\u0633\u0679\u0645 \u0646\u06cc\u0648\u06cc\u06af\u06cc\u0634\u0646\u060c \u0627\u062c\u0627\u0632\u062a)<\/p>\n<\/li>\n<li>\n<p>\u0688\u0627\u06a9\u0631 \u06a9\u06cc \u0628\u0646\u06cc\u0627\u062f\u06cc \u0628\u0627\u062a\u06cc\u06ba (\u062a\u0635\u0627\u0648\u06cc\u0631\u060c \u06a9\u0646\u0679\u06cc\u0646\u0631\u0632\u060c \u062d\u062c\u0645\u060c \u0646\u06cc\u0679 \u0648\u0631\u06a9)<\/p>\n<\/li>\n<li>\n<p>\u06af\u0679 \u0648\u0631\u06a9 \u0641\u0644\u0648 (\u06a9\u0644\u0648\u0646\u060c \u067e\u0644\u060c \u0628\u0631\u0627\u0646\u0686)<\/p>\n<\/li>\n<li>\n<p>CI\/CD \u067e\u0627\u0626\u067e \u0644\u0627\u0626\u0646 \u06a9\u0627 \u0639\u0645\u0648\u0645\u06cc \u062e\u06cc\u0627\u0644<\/p>\n<\/li>\n<\/ul>\n<p>\u0645\u0637\u0644\u0648\u0628\u06c1 \u0627\u0648\u0632\u0627\u0631 \u0627\u0648\u0631 \u0645\u0627\u062d\u0648\u0644:<\/p>\n<ul>\n<li>\n<p>\u0644\u06cc\u0646\u06a9\u0633 \u0633\u0631\u0648\u0631 (\u0627\u0648\u0628\u0646\u0679\u0648 \u062a\u062c\u0648\u06cc\u0632 \u06a9\u0631\u062f\u06c1)<\/p>\n<\/li>\n<li>\n<p>\u0688\u0648\u06a9\u0631 \u0627\u0646\u062c\u0646 + \u0688\u0648\u06a9\u0631 \u06a9\u0645\u067e\u0648\u0632 (v2)<\/p>\n<\/li>\n<li>\n<p>\u0688\u0648\u0645\u06cc\u0646 \u06a9\u0627 \u0646\u0627\u0645 (Trefik + HTTPS \u06a9\u06d2 \u0644\u06cc\u06d2)<\/p>\n<\/li>\n<li>\n<p>GitHub \u0630\u062e\u06cc\u0631\u06c1 (\u0628\u06cc\u06a9 \u0627\u06cc\u0646\u0688 \u067e\u0631\u0648\u062c\u06cc\u06a9\u0679\u0633 \u06a9\u06d2 \u0644\u06cc\u06d2)<\/p>\n<\/li>\n<li>\n<p>\u0645\u0627\u0626\u06cc\u06a9\u0631\u0648 \u0633\u0631\u0648\u0633 \u0641\u0646 \u062a\u0639\u0645\u06cc\u0631 \u06a9\u06cc \u0628\u0646\u06cc\u0627\u062f\u06cc \u062a\u0641\u06c1\u06cc\u0645<\/p>\n<\/li>\n<\/ul>\n<p>\u0627\u06af\u0631 \u0622\u067e \u0645\u0646\u062f\u0631\u062c\u06c1 \u0628\u0627\u0644\u0627 \u0633\u06d2 \u0648\u0627\u0642\u0641 \u06c1\u06cc\u06ba\u060c \u062a\u0648 \u0622\u067e \u0627\u0633 \u06a9\u06cc \u067e\u06cc\u0631\u0648\u06cc \u06a9\u0631\u0646\u06d2 \u06a9\u06d2 \u0644\u06cc\u06d2 \u062a\u06cc\u0627\u0631 \u06c1\u06cc\u06ba\u06d4<\/p>\n<h2 id=\"heading-2-architecture\">2. \u0641\u0646 \u062a\u0639\u0645\u06cc\u0631<\/h2>\n<p>\u0641\u0646 \u062a\u0639\u0645\u06cc\u0631 \u06a9\u0627 \u062c\u0627\u0626\u0632\u06c1 \u062d\u0633\u0628 \u0630\u06cc\u0644 \u06c1\u06d2:<\/p>\n<pre><code class=\"language-plaintext\">\u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 Linux server (Ubuntu) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n\u2502                                                                               \u2502\n\u2502   \/home\/developer\/projects\/                                                  \u2502\n\u2502       \u2514\u2500\u2500 project-prod-configs\/             \u2190 infra repo (compose, Traefik) \u2502\n\u2502              \u251c\u2500\u2500 docker-compose.staging.yml                                   \u2502\n\u2502              \u251c\u2500\u2500 traefik.staging.yml                                          \u2502\n\u2502              \u2514\u2500\u2500 project-backend\/          \u2190 app repo (services, gateways) \u2502\n\u2502                     \u251c\u2500\u2500 Jenkinsfile                                           \u2502\n\u2502                     \u251c\u2500\u2500 docker-compose.staging.yml                            \u2502\n\u2502                     \u2514\u2500\u2500 apps\/                                                 \u2502\n\u2502                            \u251c\u2500\u2500 services\/<name>\/                               \u2502\n\u2502                            \u251c\u2500\u2500 gateways\/<name>\/                               \u2502\n\u2502                            \u2514\u2500\u2500 core\/<name>\/                                   \u2502\n\u2502                                                                               \u2502\n\u2502   \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 Docker network: proxy \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510      \u2502\n\u2502   \u2502  traefik (80, 443)                                                 \u2502      \u2502\n\u2502   \u2502     \u2502                                                              \u2502      \u2502\n\u2502   \u2502     \u251c\u2500\u2500\u25ba jenkins  (projects-jenkins-staging)                     \u2502      \u2502\n\u2502   \u2502     \u2502      \u21b3 \/projects  \u2190 bind-mount of the host project tree     \u2502      \u2502\n\u2502   \u2502     \u2502      \u21b3 \/var\/run\/docker.sock \u2190 controls host Docker           \u2502      \u2502\n\u2502   \u2502     \u2502                                                              \u2502      \u2502\n\u2502   \u2502     \u2514\u2500\u2500\u25ba your services & gateways (built by the pipeline)          \u2502      \u2502\n\u2502   \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518      \u2502\n\u2502                                                                               \u2502\n\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n            \u25b2\n            \u2502  webhook on push\n            \u2502\n   GitHub: <org>\/project-backend (branch: staging)\n<\/org><\/name><\/name><\/name><\/code><\/pre>\n<p>\u06cc\u06c1\u0627\u06ba \u062f\u0648 \u0627\u06c1\u0645 \u062e\u06cc\u0627\u0644\u0627\u062a \u06c1\u06cc\u06ba\u06d4<\/p>\n<ol>\n<li>\n<p><strong>\u062c\u06cc\u0646\u06a9\u0646\u0632 \u06a9\u0646\u0679\u06cc\u0646\u0631\u0632 \u0645\u06cc\u06ba \u0686\u0644\u062a\u0627 \u06c1\u06d2\u06d4<\/strong>\u0644\u06cc\u06a9\u0646 \u06cc\u06c1 <strong>\u0645\u06cc\u0632\u0628\u0627\u0646 \u06a9\u06cc<\/strong> \u0688\u0648\u06a9\u0631 \u0633\u06d2 \u0644\u06cc\u0633 <code>\/var\/run\/docker.sock<\/code>. \u0645\u06cc\u06ba \u067e\u0631\u0648\u062c\u06cc\u06a9\u0679 \u0641\u0648\u0644\u0688\u0631 \u06a9\u0648 \u0627\u0633 \u0637\u0631\u062d \u0645\u0627\u0624\u0646\u0679 \u06a9\u0631\u062a\u0627 \u06c1\u0648\u06ba: <code>\/projects\/...<\/code>\u062a\u0648 \u06cc\u06c1 \u06c1\u0648 \u0633\u06a9\u062a\u0627 \u06c1\u06d2 <code>cd<\/code> \u0627\u0633\u06d2 \u0627\u067e\u0646\u06d2 \u0645\u06cc\u0632\u0628\u0627\u0646 \u06a9\u06d2 \u0627\u0635\u0644 \u06a9\u0648\u0688 \u0645\u06cc\u06ba \u0688\u0627\u0644\u06cc\u06ba \u0627\u0648\u0631 \u0627\u0633\u06d2 \u0686\u0644\u0627\u0626\u06cc\u06ba\u06d4 <code>docker compose<\/code> \u0648\u06c1\u0627\u06ba<\/p>\n<\/li>\n<li>\n<p>\u06a9\u06c1 <strong>\u062c\u06cc\u0646\u06a9\u0646\u0632 \u0641\u0627\u0626\u0644 \u0627\u06cc\u067e \u06a9\u06d2 \u0630\u062e\u06cc\u0631\u06d2 \u0645\u06cc\u06ba \u0648\u0627\u0642\u0639 \u06c1\u06d2\u06d4<\/strong>\u0644\u06c1\u0630\u0627\u060c \u067e\u0627\u0626\u067e \u0644\u0627\u0626\u0646 \u06a9\u06cc \u062a\u0639\u0631\u06cc\u0641 \u06a9\u0648\u0688 \u06a9\u06d2 \u0637\u0648\u0631 \u067e\u0631 \u0648\u0631\u0698\u0646 \u06c1\u06d2. \u062c\u06cc\u0646\u06a9\u0646\u0632 \u0622\u0633\u0627\u0646\u06cc \u0633\u06d2 \u0627\u0633 \u06a9\u06cc \u0646\u0634\u0627\u0646\u062f\u06c1\u06cc \u06a9\u0631\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4<\/p>\n<\/li>\n<\/ol>\n<h3 id=\"heading-3-server-prerequisites\">3. \u0633\u0631\u0648\u0631 \u06a9\u06cc \u0634\u0631\u0627\u0626\u0637<\/h3>\n<p>\u0627\u0633 \u0633\u06d2 \u067e\u06c1\u0644\u06d2 \u06a9\u06c1 \u0622\u067e \u062c\u06cc\u0646\u06a9\u0646\u0632 \u06cc\u0627 \u0679\u0631\u06cc\u0641\u06a9 \u06a9\u0648 \u062a\u0631\u062a\u06cc\u0628 \u062f\u06cc\u0646\u0627 \u0634\u0631\u0648\u0639 \u06a9\u0631\u06cc\u06ba\u060c \u0622\u067e \u06a9\u0648 \u0627\u067e\u0646\u06d2 \u0633\u0631\u0648\u0631 \u06a9\u0648 \u0645\u0646\u0627\u0633\u0628 \u0637\u0631\u06cc\u0642\u06d2 \u0633\u06d2 \u062a\u06cc\u0627\u0631 \u06a9\u0631\u0646\u0627 \u0686\u0627\u06c1\u06cc\u06d2\u06d4<\/p>\n<p>\u0627\u0633 \u0645\u0631\u062d\u0644\u06d2 \u0645\u06cc\u06ba:<\/p>\n<ul>\n<li>\n<p>\u067e\u0631\u0627\u062c\u06cc\u06a9\u0679 \u0645\u06cc\u0646\u062c\u0645\u0646\u0679 \u06a9\u06d2 \u0644\u06cc\u06d2 \u0627\u06cc\u06a9 \u0648\u0642\u0641 \u0634\u062f\u06c1 \u0644\u06cc\u0646\u06a9\u0633 \u0635\u0627\u0631\u0641 \u0628\u0646\u0627\u0626\u06cc\u06ba<\/p>\n<\/li>\n<li>\n<p>\u0688\u0648\u06a9\u0631 \u0627\u0648\u0631 \u0688\u0648\u06a9\u0631 \u06a9\u0645\u067e\u0648\u0632 \u0627\u0646\u0633\u0679\u0627\u0644 \u06a9\u0631\u06cc\u06ba\u06d4<\/p>\n<\/li>\n<li>\n<p>\u0627\u067e\u0646\u06d2 \u0630\u062e\u06cc\u0631\u06c1 \u06a9\u06d2 \u0644\u06cc\u06d2 \u0641\u0648\u0644\u0688\u0631 \u06a9\u0627 \u0688\u06be\u0627\u0646\u0686\u06c1 \u062a\u0631\u062a\u06cc\u0628 \u062f\u06cc\u06ba\u06d4<\/p>\n<\/li>\n<\/ul>\n<p>\u06cc\u06c1 \u0627\u0633 \u0628\u0627\u062a \u06a9\u0648 \u06cc\u0642\u06cc\u0646\u06cc \u0628\u0646\u0627\u062a\u0627 \u06c1\u06d2 \u06a9\u06c1 \u0622\u067e \u06a9\u06cc CI\/CD \u067e\u0627\u0626\u067e \u0644\u0627\u0626\u0646 \u0635\u0627\u0641 \u0627\u0648\u0631 \u067e\u06cc\u0634 \u06af\u0648\u0626\u06cc \u06a9\u06d2 \u0642\u0627\u0628\u0644 \u0645\u0627\u062d\u0648\u0644 \u0645\u06cc\u06ba \u0686\u0644\u062a\u06cc \u06c1\u06d2\u06d4<\/p>\n<pre><code class=\"language-bash\"># Linux user that owns the project tree\nsudo adduser developer\n\n# Docker engine + Compose plugin\ncurl -fsSL https:\/\/get.docker.com | sh\nsudo usermod -aG docker developer\n\n# Sanity check Compose v2\ndocker compose version\n# -> Docker Compose version v2.x.y\n\n# Find where the Compose plugin binary lives \u2014 write it down, you'll need it\nls \/usr\/libexec\/docker\/cli-plugins\/docker-compose\n# (some distros use \/usr\/lib\/docker\/cli-plugins\/docker-compose)\n\n# Project layout\nsudo mkdir -p \/home\/developer\/project\nsudo chown -R developer:developer \/home\/developer\/project\n\n# Clone both repos in the right place\ncd \/home\/developer\/projects\ngit clone https:\/\/github.com\/<org>\/projects-prod-configs.git\ncd projects-prod-configs\ngit clone -b staging https:\/\/github.com\/<org>\/projects-backend.git\n<\/org><\/org><\/code><\/pre>\n<p>\u0627\u0628 \u0622\u067e \u06a9\u06d2 \u067e\u0627\u0633 \u06c1\u0648\u0646\u0627 \u0686\u0627\u06c1\u0626\u06d2:<\/p>\n<pre><code class=\"language-plaintext\">\/home\/developer\/projects\/projects-prod-configs\/projects-backend\n<\/code><\/pre>\n<p>\u0627\u0633 \u0631\u0627\u0633\u062a\u06d2 \u06a9\u0648 \u06cc\u0627\u062f \u0631\u06a9\u06be\u06cc\u06ba\u06d4 \u062c\u06cc\u0646\u06a9\u0646\u0632 \u0641\u0627\u0626\u0644 \u0627\u0633 \u06a9\u0627 \u062d\u0648\u0627\u0644\u06c1 \u062f\u06cc\u062a\u06cc \u06c1\u06d2\u06d4<\/p>\n<h3 id=\"heading-dns\">\u0688\u06cc \u0627\u06cc\u0646 \u0627\u06cc\u0633<\/h3>\n<p>\u0627\u067e\u0646\u06d2 \u062c\u06cc\u0646\u06a9\u0646\u0632 \u0630\u06cc\u0644\u06cc \u0688\u0648\u0645\u06cc\u0646 \u06a9\u06d2 \u0631\u06cc\u06a9\u0627\u0631\u0688 \u06a9\u0648 \u0633\u0631\u0648\u0631 \u06a9\u06d2 \u0639\u0648\u0627\u0645\u06cc IP \u06a9\u06cc \u0637\u0631\u0641 \u0627\u0634\u0627\u0631\u06c1 \u06a9\u0631\u06cc\u06ba\u06d4 <strong>\u067e\u06c1\u0644\u06d2<\/strong> HTTP \u0686\u06cc\u0644\u0646\u062c \u06a9\u06d2 \u0630\u0631\u06cc\u0639\u06d2 \u062a\u0648\u062b\u06cc\u0642 \u06a9\u0631\u0646\u06d2 \u06a9\u06d2 \u0644\u06cc\u06d2 Let&#8217;s Encrypt \u06a9\u0648 \u0641\u0639\u0627\u0644 \u06a9\u0631\u0646\u06d2 \u06a9\u06d2 \u0644\u06cc\u06d2 \u0627\u0646 \u0627\u0642\u062f\u0627\u0645\u0627\u062a \u067e\u0631 \u0639\u0645\u0644 \u06a9\u0631\u06cc\u06ba\u06d4<\/p>\n<pre><code class=\"language-plaintext\">jenkins.example.com   A   <server-public-ip>\n<\/server-public-ip><\/code><\/pre>\n<h2 id=\"heading-4-traefik-the-reverse-proxy\">4. Traefik &#8211; \u0631\u06cc\u0648\u0631\u0633 \u067e\u0631\u0627\u06a9\u0633\u06cc<\/h2>\n<p>Traefik \u067e\u0648\u0631\u06d2 \u0646\u0638\u0627\u0645 \u0645\u06cc\u06ba \u062f\u0627\u062e\u0644\u06d2 \u06a9\u06d2 \u0646\u0642\u0637\u06c1 \u06a9\u06d2 \u0637\u0648\u0631 \u067e\u0631 \u06a9\u0627\u0645 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4 \u06c1\u0631 \u0633\u0631\u0648\u0633 \u06a9\u0648 \u062f\u0633\u062a\u06cc \u0637\u0648\u0631 \u067e\u0631 \u0627\u06cc\u06a9 \u0628\u0646\u062f\u0631\u06af\u0627\u06c1 \u06a9\u06d2 \u0637\u0648\u0631 \u067e\u0631 \u0638\u0627\u06c1\u0631 \u06a9\u0631\u0646\u06d2 \u06a9\u06d2 \u0628\u062c\u0627\u0626\u06d2\u060c Traefik \u062e\u0648\u062f \u0628\u062e\u0648\u062f:<\/p>\n<ul>\n<li>\n<p>\u0688\u0648\u0645\u06cc\u0646 \u0646\u0627\u0645 \u06a9\u06cc \u0628\u0646\u06cc\u0627\u062f \u067e\u0631 \u0679\u0631\u06cc\u0641\u06a9 \u06a9\u06cc \u0631\u0648\u0679\u0646\u06af<\/p>\n<\/li>\n<li>\n<p>Let&#8217;s Encrypt \u06a9\u0627 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u062a\u06d2 \u06c1\u0648\u0626\u06d2 HTTPS \u0633\u0631\u0679\u06cc\u0641\u06a9\u06cc\u0679 \u0628\u0646\u0627\u0626\u06cc\u06ba \u0627\u0648\u0631 \u0627\u0646 \u06a9\u06cc \u062a\u062c\u062f\u06cc\u062f \u06a9\u0631\u06cc\u06ba\u06d4<\/p>\n<\/li>\n<li>\n<p>\u0688\u0648\u06a9\u0631 \u0633\u06d2 \u062c\u0691\u06cc\u06ba \u0627\u0648\u0631 \u0645\u062a\u062d\u0631\u06a9 \u0637\u0648\u0631 \u067e\u0631 \u062e\u062f\u0645\u0627\u062a \u06a9\u0627 \u067e\u062a\u06c1 \u0644\u06af\u0627\u0626\u06cc\u06ba\u06d4<\/p>\n<\/li>\n<\/ul>\n<p>\u0645\u062e\u062a\u0635\u0631\u0627\u064b\u060c Traefik \u0622\u067e \u06a9\u0648 \u062f\u0631\u062c \u0630\u06cc\u0644 \u062e\u062f\u0645\u0627\u062a \u062a\u06a9 \u0631\u0633\u0627\u0626\u06cc \u0641\u0631\u0627\u06c1\u0645 \u06a9\u0631\u062a\u0627 \u06c1\u06d2:<\/p>\n<p>https:\/\/jenkins.example.com<br \/>https:\/\/api.example.com<\/p>\n<p>\u2026 \u06cc\u06c1 NGINX \u06a9\u0648 \u062f\u0633\u062a\u06cc \u0637\u0648\u0631 \u067e\u0631 \u06a9\u0646\u0641\u06cc\u06af\u0631 \u06a9\u06cc\u06d2 \u0628\u063a\u06cc\u0631 \u06cc\u0627 SSL \u0633\u0631\u0679\u06cc\u0641\u06a9\u06cc\u0679\u0633 \u06a9\u0627 \u0627\u0646\u062a\u0638\u0627\u0645 \u06a9\u06cc\u06d2 \u0628\u063a\u06cc\u0631 \u0645\u0645\u06a9\u0646 \u06c1\u06d2\u06d4<\/p>\n<p>\u0627\u0633 \u0633\u06cc\u0679 \u0627\u067e \u0645\u06cc\u06ba\u060c Traefik Docker \u06a9\u0646\u0679\u06cc\u0646\u0631\u0632 \u06a9\u0648 \u062f\u06cc\u06a9\u06be\u062a\u0627 \u06c1\u06d2 \u0627\u0648\u0631 \u0644\u06cc\u0628\u0644\u0632 \u06a9\u0627 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u062a\u06d2 \u06c1\u0648\u0626\u06d2 \u0679\u0631\u06cc\u0641\u06a9 \u06a9\u0648 \u0631\u0648\u0679 \u06a9\u0631\u062a\u0627 \u06c1\u06d2 \u062c\u0633 \u06a9\u06cc \u0622\u067e \u0628\u0639\u062f \u0645\u06cc\u06ba \u0648\u0636\u0627\u062d\u062a \u06a9\u0631\u06cc\u06ba \u06af\u06d2\u06d4<\/p>\n<p>Traefik \u06c1\u0631 \u06a9\u0646\u0679\u06cc\u0646\u0631 \u06a9\u06d2 \u0644\u06cc\u06d2 \u0627\u06cc\u06a9 \u062d\u0642\u06cc\u0642\u06cc \u0688\u0648\u0645\u06cc\u0646 \u0627\u0648\u0631 \u0627\u06cc\u06a9 \u062d\u0642\u06cc\u0642\u06cc \u0633\u0631\u0679\u06cc\u0641\u06a9\u06cc\u0679 \u0641\u0631\u0627\u06c1\u0645 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4 <strong>\u06a9\u0648\u0626\u06cc \u0633\u0631\u0648\u0633 \u0645\u062e\u0635\u0648\u0635 \u06a9\u0646\u0641\u06cc\u06af\u0631\u06cc\u0634\u0646 \u0646\u06c1\u06cc\u06ba \u06c1\u06d2\u06d4<\/strong> &#8211; \u0628\u0633 \u0686\u0646\u062f \u0644\u06cc\u0628\u0644\u0632 \u0634\u0627\u0645\u0644 \u06a9\u0631\u06cc\u06ba\u06d4<\/p>\n<h3 id=\"heading-traefikstagingyml-static-config\"><code>traefik.staging.yml<\/code>    (\u062c\u0627\u0645\u062f \u062a\u0631\u062a\u06cc\u0628)<\/h3>\n<p>\u0627\u067e\u0646\u06d2 \u0628\u0646\u06cc\u0627\u062f\u06cc \u0688\u06be\u0627\u0646\u0686\u06d2 \u06a9\u06d2 \u0630\u062e\u06cc\u0631\u06d2 \u06a9\u06cc \u062c\u0691 \u0645\u06cc\u06ba \u062f\u0631\u062c \u0630\u06cc\u0644 \u062f\u0631\u062c \u06a9\u0631\u06cc\u06ba:<\/p>\n<pre><code class=\"language-yaml\">api:\n  dashboard: true\n\nentryPoints:\n  web:\n    address: \":80\"\n  websecure:\n    address: \":443\"\n\ncertificatesResolvers:\n  letsencrypt:\n    acme:\n      httpChallenge:\n        entryPoint: web\n      email: admin@example.com           # \u2190 change me\n      storage: \/etc\/traefik\/acme.json\n\nproviders:\n  docker:\n    endpoint: \"unix:\/\/\/var\/run\/docker.sock\"\n    exposedByDefault: false              # only containers with traefik.enable=true\n    network: proxy\n  file:\n    directory: \/etc\/traefik\/dynamic\n    watch: true\n\nlog:\n  level: INFO\n\naccessLog: {}\n<\/code><\/pre>\n<h3 id=\"heading-the-traefik-service-in-docker-composestagingyml\">\u0679\u0631\u06cc\u0641\u06a9 \u0633\u0631\u0648\u0633 <code>docker-compose.staging.yml<\/code><\/h3>\n<pre><code class=\"language-yaml\">networks:\n  proxy:\n    name: proxy\n    driver: bridge\n  internal:\n    name: internal\n    driver: bridge\n\nvolumes:\n  acme-data:\n  traefik-logs:\n  jenkins-data:\n\nservices:\n  traefik:\n    image: traefik:v2.11\n    container_name: projects-traefik-staging\n    restart: unless-stopped\n    ports:\n      - \"80:80\"        # HTTP (auto-redirects to HTTPS)\n      - \"443:443\"      # HTTPS\n      - \"8080:8080\"    # Traefik dashboard (internal only \u2014 protect via firewall)\n    volumes:\n      - \/var\/run\/docker.sock:\/var\/run\/docker.sock:ro\n      - .\/traefik.staging.yml:\/etc\/traefik\/traefik.yml:ro\n      - .\/dynamic:\/etc\/traefik\/dynamic:ro\n      - acme-data:\/etc\/traefik           # persists Let's Encrypt certs\n      - traefik-logs:\/var\/log\/traefik\n    networks:\n      - proxy\n    command:\n      - '--api.insecure=false'\n      - '--api.dashboard=true'\n      - '--providers.docker=true'\n      - '--providers.docker.exposedbydefault=false'\n      - '--providers.docker.network=proxy'\n      - '--entrypoints.web.address=:80'\n      - '--entrypoints.websecure.address=:443'\n      - '--entrypoints.web.http.redirections.entryPoint.to=websecure'\n      - '--entrypoints.web.http.redirections.entryPoint.scheme=https'\n      - '--certificatesresolvers.letsencrypt.acme.httpchallenge=true'\n      - '--certificatesresolvers.letsencrypt.acme.httpchallenge.entrypoint=web'\n      - '--certificatesresolvers.letsencrypt.acme.email=${ACME_EMAIL:-admin@example.com}'\n      - '--certificatesresolvers.letsencrypt.acme.storage=\/etc\/traefik\/acme.json'\n      - '--log.level=INFO'\n      - '--accesslog=true'\n    labels:\n      - \"traefik.enable=true\"\n      - \"traefik.docker.network=proxy\"\n      # Traefik's own dashboard\n      - \"traefik.http.routers.traefik-dash.rule=Host(`traefik.example.com`)\"\n      - \"traefik.http.routers.traefik-dash.entrypoints=websecure\"\n      - \"traefik.http.routers.traefik-dash.tls.certresolver=letsencrypt\"\n      - \"traefik.http.routers.traefik-dash.service=api@internal\"\n<\/code><\/pre>\n<p>\u0628\u0631\u0627\u06c1 \u06a9\u0631\u0645 \u0644\u0627\u0626\u06cc\u06ba:<\/p>\n<pre><code class=\"language-bash\">cd \/home\/developer\/projects\/projects-prod-configs\ndocker compose -f docker-compose.staging.yml up -d traefik\n<\/code><\/pre>\n<p>\u067e\u06c1\u0644\u06cc \u0628\u0627\u0631 \u0644\u0627\u06af\u0632 \u0686\u06cc\u06a9 \u06a9\u0631\u06cc\u06ba\u06d4 DNS \u062d\u0644 \u06c1\u0648\u062a\u06d2 \u06c1\u06cc Traefik \u0622\u067e \u06a9\u06d2 \u0688\u06cc\u0634 \u0628\u0648\u0631\u0688 \u0645\u06cc\u0632\u0628\u0627\u0646 \u06a9\u06d2 \u0644\u06cc\u06d2 \u0627\u06cc\u06a9 \u0633\u0631\u0679\u06cc\u0641\u06a9\u06cc\u0679 \u06a9\u06cc \u062f\u0631\u062e\u0648\u0627\u0633\u062a \u06a9\u0631\u06d2 \u06af\u0627\u06d4<\/p>\n<pre><code class=\"language-bash\">docker logs -f projects-traefik-staging\n<\/code><\/pre>\n<p><strong>\u0679\u067e<\/strong> \u062c\u0627\u0646\u0686 \u06a9\u06d2 \u062f\u0648\u0631\u0627\u0646\u060c ACME \u06a9\u0648 \u0633\u0679\u06cc\u062c\u0646\u06af \u0627\u06cc\u0646\u0688 \u067e\u0648\u0627\u0626\u0646\u0679 \u06a9\u06d2 \u0637\u0648\u0631 \u067e\u0631 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u06cc\u06ba (<code>acme.caServer=https:\/\/acme-staging-v02.api.letsencrypt.org\/directory<\/code>) \u0627\u06af\u0631 \u0622\u067e \u0627\u067e\u0646\u06d2 DNS \u06a9\u0648 \u063a\u0644\u0637 \u0637\u0631\u06cc\u0642\u06d2 \u0633\u06d2 \u062a\u0631\u062a\u06cc\u0628 \u062f\u06cc\u062a\u06d2 \u06c1\u06cc\u06ba \u062a\u0648 Let&#8217;s Encrypt \u06a9\u06cc \u0634\u0631\u062d \u06a9\u06cc \u062d\u062f \u0633\u06d2 \u062a\u062c\u0627\u0648\u0632 \u06a9\u0631\u0646\u06d2 \u0633\u06d2 \u0628\u0686\u0646\u06d2 \u06a9\u06d2 \u0644\u06cc\u06d2\u06d4 \u0628\u0631\u0627\u06c1 \u06a9\u0631\u0645 \u0644\u0627\u0626\u06cc\u0648 \u062c\u0627\u0646\u06d2 \u0633\u06d2 \u067e\u06c1\u0644\u06d2 \u0627\u0633 \u062c\u06be\u0646\u0688\u06d2 \u06a9\u0648 \u06c1\u0679\u0627 \u062f\u06cc\u06ba\u06d4<\/p>\n<h2 id=\"heading-5-run-jenkins-in-docker\">5. \u0688\u0648\u06a9\u0631 \u067e\u0631 \u062c\u06cc\u0646\u06a9\u0646\u0632 \u0686\u0644\u0627\u0646\u0627<\/h2>\n<p>\u0627\u0633 \u062c\u06cc\u0646\u06a9\u0646\u0632 \u0633\u0631\u0648\u0633 \u06a9\u0648 \u0627\u0633\u06cc \u0633\u0631\u0648\u0633 \u0645\u06cc\u06ba \u0634\u0627\u0645\u0644 \u06a9\u0631\u06cc\u06ba\u06d4 <code>docker-compose.staging.yml<\/code>. \u06c1\u0631 \u0633\u0637\u0631 \u0627\u06c1\u0645 \u06c1\u06d2 (\u0627\u0648\u0631 \u062a\u0628\u0635\u0631\u06d2 \u0627\u0633 \u06a9\u06cc \u0648\u062c\u06c1 \u0628\u062a\u0627\u062a\u06d2 \u06c1\u06cc\u06ba)\u06d4<\/p>\n<pre><code class=\"language-yaml\">  jenkins:\n    image: jenkins\/jenkins:lts\n    container_name: projects-jenkins-staging\n    restart: unless-stopped\n    user: root                           # to use host docker.sock without UID juggling\n    environment:\n      - JAVA_OPTS=-Xmx1g -Xms512m -Duser.timezone=Asia\/Dhaka\n      - TZ=Asia\/Dhaka                    # OS-level timezone inside container\n      - JENKINS_OPTS=--prefix=\/\n    ports:\n      - \"3095:8080\"                      # web UI (also reachable directly if needed)\n      - \"50000:50000\"                    # inbound agent port\n    volumes:\n      - jenkins-data:\/var\/jenkins_home   # Jenkins config\/jobs\/secrets persistence\n      - \/var\/run\/docker.sock:\/var\/run\/docker.sock                          # control host Docker\n      - \/usr\/bin\/docker:\/usr\/bin\/docker                                     # docker CLI from host\n      - \/usr\/libexec\/docker\/cli-plugins:\/usr\/libexec\/docker\/cli-plugins:ro  # docker compose plugin\n      - \/home\/developer\/projects:\/projects                                # project tree\n      - \/etc\/localtime:\/etc\/localtime:ro                                    # match host clock\n      - \/etc\/timezone:\/etc\/timezone:ro\n    networks:\n      - proxy\n      - internal\n    healthcheck:\n      test: ['CMD', 'curl', '-f', 'http:\/\/localhost:8080\/login']\n      interval: 30s\n      timeout: 10s\n      retries: 5\n      start_period: 120s\n    deploy:\n      resources:\n        limits:\n          memory: 1024M\n<\/code><\/pre>\n<p><strong>\u06a9\u06cc\u0648\u06ba<\/strong> <code>user: root<\/code><strong>?<\/strong> \u0634\u06cc\u0626\u0631 \u06a9\u0631\u0646\u06d2 \u06a9\u0627 \u0622\u0633\u0627\u0646 \u062a\u0631\u06cc\u0646 \u0637\u0631\u06cc\u0642\u06c1 <code>docker.sock<\/code> UID\/GID \u062c\u0645\u0646\u0627\u0633\u0679\u06a9\u0633 \u06a9\u06d2 \u0628\u063a\u06cc\u0631 \u067e\u0631\u0648\u062c\u06cc\u06a9\u0679 \u0628\u0627\u0626\u0646\u0688 \u0645\u0627\u0624\u0646\u0679\u06d4 \u0627\u06af\u0631 \u0622\u067e \u063a\u06cc\u0631 \u0645\u0631\u0627\u0639\u0627\u062a \u06cc\u0627\u0641\u062a\u06c1 \u0635\u0627\u0631\u0641\u06cc\u0646 \u06a9\u0648 \u062a\u0631\u062c\u06cc\u062d \u062f\u06cc\u062a\u06d2 \u06c1\u06cc\u06ba\u060c \u062a\u0648 \u0622\u067e \u06a9\u0648 \u062a\u0631\u062a\u06cc\u0628 \u062f\u06cc\u0646\u06d2 \u06a9\u06cc \u0636\u0631\u0648\u0631\u062a \u06c1\u06d2: <code>group: docker<\/code> UID\/perms \u06a9\u0648 \u0645\u06cc\u0632\u0628\u0627\u0646 \u0641\u0648\u0644\u0688\u0631 \u0645\u06cc\u06ba \u062a\u0631\u062a\u06cc\u0628 \u062f\u06cc\u06ba\u06d4 \u06cc\u06c1 \u0645\u0645\u06a9\u0646 \u06c1\u06d2\u060c \u0644\u06cc\u06a9\u0646 \u06cc\u06c1\u0627\u06ba \u06af\u0646\u062c\u0627\u0626\u0634 \u0633\u06d2 \u0628\u0627\u06c1\u0631 \u06c1\u06d2\u06d4<\/p>\n<h2 id=\"heading-6-expose-jenkins-on-a-domain-via-traefik\">6. Traefik \u06a9\u06d2 \u0630\u0631\u06cc\u0639\u06d2 \u062c\u06cc\u0646\u06a9\u0646\u0632 \u06a9\u0648 \u0627\u067e\u0646\u06d2 \u0688\u0648\u0645\u06cc\u0646 \u067e\u0631 \u0638\u0627\u06c1\u0631 \u06a9\u0631\u06cc\u06ba\u06d4<\/h2>\n<p>\u06cc\u06c1 \u0627\u06cc\u06a9 \u0627\u06cc\u0633\u0627 \u062d\u0635\u06c1 \u06c1\u06d2 \u062c\u0633\u06d2 \u0628\u06c1\u062a \u0633\u06d2 \u0631\u06c1\u0646\u0645\u0627 \u0686\u06be\u0648\u0691 \u062f\u06cc\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4 \u06c1\u0645 \u0634\u0627\u0645\u0644 \u06a9\u0631\u06cc\u06ba \u06af\u06d2 <strong>\u0644\u06cc\u0628\u0644<\/strong> \u0627\u067e\u0646\u06cc \u062c\u06cc\u0646\u06a9\u0646\u0632 \u0633\u0631\u0648\u0633 \u0633\u06d2 \u062c\u0691\u06cc\u06ba \u0627\u0648\u0631 Traefik \u06a9\u0648 \u0627\u0633\u06d2 \u0627\u067e\u0646\u06d2 \u0644\u06cc\u06d2 \u0644\u06cc\u0646\u06d2 \u062f\u06cc\u06ba\u06d4 Traefik \u06a9\u0646\u0641\u06cc\u06af\u0631\u06cc\u0634\u0646 \u0645\u06cc\u06ba \u062a\u0631\u0645\u06cc\u0645 \u06a9\u0631\u0646\u06d2 \u06a9\u06cc \u0636\u0631\u0648\u0631\u062a \u0646\u06c1\u06cc\u06ba \u06c1\u06d2\u06d4<\/p>\n<pre><code class=\"language-yaml\">  jenkins:\n    # ... everything above ...\n    labels:\n      - \"traefik.enable=true\"\n      - \"traefik.docker.network=proxy\"\n\n      # 1) Router \u2014 match incoming Host\n      - \"traefik.http.routers.jenkins.rule=Host(`jenkins.example.com`)\"\n      - \"traefik.http.routers.jenkins.entrypoints=websecure\"\n      - \"traefik.http.routers.jenkins.tls.certresolver=letsencrypt\"\n      - \"traefik.http.routers.jenkins.service=jenkins\"\n\n      # 2) Service \u2014 tell Traefik which container port is the app\n      - \"traefik.http.services.jenkins.loadbalancer.server.port=8080\"\n\n      # 3) Middleware \u2014 Jenkins needs X-Forwarded-Proto so it knows it's behind HTTPS\n      - \"traefik.http.middlewares.jenkins-headers.headers.customrequestheaders.X-Forwarded-Proto=https\"\n      - \"traefik.http.routers.jenkins.middlewares=jenkins-headers\"\n<\/code><\/pre>\n<p>\u06c1\u0631 \u0633\u0637\u0631 \u06a9\u0627 \u06a9\u0631\u062f\u0627\u0631 \u062d\u0633\u0628 \u0630\u06cc\u0644 \u06c1\u06d2:<\/p>\n<table>\n<thead>\n<tr>\n<th>\u0628\u0631\u0627\u0646\u0688<\/th>\n<th>\u0645\u0642\u0635\u062f<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td><code>traefik.enable=true<\/code><\/td>\n<td>\u0627\u0633 \u06a9\u0646\u0679\u06cc\u0646\u0631 \u06a9\u0648 \u0645\u0646\u062a\u062e\u0628 \u06a9\u0631\u06cc\u06ba (\u06c1\u0645 <code>exposedByDefault=false<\/code>)\u06d4<\/td>\n<\/tr>\n<tr>\n<td><code>traefik.docker.network=proxy<\/code><\/td>\n<td>Traefik \u06a9\u0648 \u0628\u062a\u0627\u0626\u06cc\u06ba \u06a9\u06c1 \u062c\u06cc\u0646\u06a9\u0646\u0632 \u06a9\u06d2 \u0633\u0627\u062a\u06be \u06a9\u0648\u0646 \u0633\u0627 \u0646\u06cc\u0679 \u0648\u0631\u06a9 \u0631\u0627\u0628\u0637\u06c1 \u06a9\u0631\u06d2 (\u062c\u06cc\u0646\u06a9\u0646\u0632 \u062f\u0648\u0646\u0648\u06ba \u0646\u06cc\u0679 \u0648\u0631\u06a9\u0633 \u067e\u0631 \u06c1\u06d2)\u06d4 <code>proxy<\/code> \u0627\u0648\u0631 <code>internal<\/code>)\u06d4<\/td>\n<\/tr>\n<tr>\n<td><code>routers.jenkins.rule=Host(...)<\/code><\/td>\n<td>\u06c1\u0645 \u06cc\u06c1 \u0645\u06cc\u0632\u0628\u0627\u0646 \u0646\u0627\u0645 \u0635\u0631\u0641 \u062c\u06cc\u0646\u06a9\u0646\u0632 \u06a9\u0648 \u062f\u06cc\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4<\/td>\n<\/tr>\n<tr>\n<td><code>routers.jenkins.entrypoints=websecure<\/code><\/td>\n<td>\u0635\u0631\u0641 443 \u067e\u0631 \u0633\u0646\u062a\u0627 \u06c1\u06d2\u06d4 (HTTP \u0631\u06cc \u0688\u0627\u0626\u0631\u06cc\u06a9\u0634\u0646 \u0633\u06cc\u06a9\u0634\u0646 4 \u0645\u06cc\u06ba \u062a\u0631\u062a\u06cc\u0628 \u062f\u06cc\u0627 \u06af\u06cc\u0627 \u062a\u06be\u0627\u06d4)<\/td>\n<\/tr>\n<tr>\n<td><code>routers.jenkins.tls.certresolver=letsencrypt<\/code><\/td>\n<td>\u062e\u0648\u062f\u06a9\u0627\u0631 \u0627\u062c\u0631\u0627\u0621 + \u0633\u0631\u0679\u06cc\u0641\u06a9\u06cc\u0679 \u06a9\u06cc \u062a\u062c\u062f\u06cc\u062f<\/td>\n<\/tr>\n<tr>\n<td><code>services.jenkins.loadbalancer.server.port=8080<\/code><\/td>\n<td>\u062c\u06cc\u0646\u06a9\u0646\u0632 \u06a9\u0646\u0679\u06cc\u0646\u0631 \u06a9\u06d2 \u0627\u0646\u062f\u0631 8080 \u0633\u0646\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4<\/td>\n<\/tr>\n<tr>\n<td><code>customrequestheaders.X-Forwarded-Proto=https<\/code><\/td>\n<td>\u0627\u06af\u0631 \u06cc\u06c1 \u0645\u0648\u062c\u0648\u062f \u0646\u06c1\u06cc\u06ba \u06c1\u06d2 \u062a\u0648\u060c \u062c\u06cc\u0646\u06a9\u0646\u0632 \u0627\u06cc\u06a9 \u0628\u0646\u0627\u0626\u06cc\u06ba \u06af\u06d2\u06d4 <code>http:\/\/<\/code> \u0648\u06cc\u0628 \u06c1\u06a9\/\u0644\u0646\u06a9 \u0627\u0648\u0631 \u0648\u0642\u0641\u06d2 \u06a9\u0627 URL\u06d4<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>\u062c\u06cc\u0646\u06a9\u0646\u0632 \u06a9\u0648 \u0627\u0679\u06be\u0627\u0624\u06d4<\/p>\n<pre><code class=\"language-bash\">cd \/home\/developer\/projects\/projects-prod-configs\ndocker compose -f docker-compose.staging.yml up -d jenkins\n\n# Watch Traefik issue the certificate\ndocker logs -f projects-traefik-staging | grep -i acme\n<\/code><\/pre>\n<p>\u0622\u067e \u06a9\u0648 \u0627\u0633\u06d2 10 \u0633\u06d2 60 \u0633\u06cc\u06a9\u0646\u0688 \u06a9\u06d2 \u0628\u0639\u062f \u06a9\u06be\u0648\u0644\u0646\u06d2 \u06a9\u06d2 \u0642\u0627\u0628\u0644 \u06c1\u0648\u0646\u0627 \u0686\u0627\u06c1\u0626\u06d2\u06d4 <code>https:\/\/jenkins.example.com<\/code> \u0627\u06cc\u06a9 \u062f\u0631\u0633\u062a \u0644\u0627\u06a9 \u0622\u0626\u06cc\u06a9\u0646 \u06a9\u06d2 \u0633\u0627\u062a\u06be \u062c\u06cc\u0646\u06a9\u0646\u0632 \u06a9\u0627 \u0633\u06cc\u0679 \u0627\u067e \u0648\u0632\u0631\u0688 \u062f\u06cc\u06a9\u06be\u06cc\u06ba\u06d4<\/p>\n<p>\u062c\u06cc\u0646\u06a9\u0646\u0632 \u06a9\u06d2 \u0627\u0646\u062f\u0631 (\u067e\u06c1\u0644\u06d2 \u0644\u0627\u06af \u0627\u0646 \u06a9\u06d2 \u0628\u0639\u062f):<\/p>\n<p>\u062c\u06cc\u0646\u06a9\u0646\u0632 \u0645\u06cc\u0646\u062c\u0645\u0646\u0679 \u2192 \u0633\u0633\u0679\u0645 \u2192 \u062c\u06cc\u0646\u06a9\u0646\u0632 URL \u2192 https:\/\/jenkins.example.com\/ \u06a9\u06d2 \u0628\u0637\u0648\u0631 \u0633\u06cc\u0679 \u06a9\u0631\u06cc\u06ba\u06d4<\/p>\n<p>\u06cc\u06c1 \u0636\u0631\u0648\u0631\u06cc \u06c1\u06d2 \u06a9\u06cc\u0648\u0646\u06a9\u06c1 \u062c\u06cc\u0646\u06a9\u0646\u0632 \u0627\u0633 \u0628\u0646\u06cc\u0627\u062f\u06cc URL \u06a9\u0648 \u0628\u0646\u0627\u0646\u06d2 \u06a9\u06d2 \u0644\u06cc\u06d2 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u062a\u06d2 \u06c1\u06cc\u06ba:<\/p>\n<p>\u0627\u06af\u0631 \u06cc\u06c1 \u0635\u062d\u06cc\u062d \u0637\u0631\u06cc\u0642\u06d2 \u0633\u06d2 \u062a\u0631\u062a\u06cc\u0628 \u0646\u06c1\u06cc\u06ba \u062f\u06cc\u0627 \u06af\u06cc\u0627 \u06c1\u06d2 \u062a\u0648\u060c \u0622\u067e \u06a9\u06d2 GitHub \u0648\u06cc\u0628 \u06c1\u06a9\u0633 \u0646\u0627\u06a9\u0627\u0645 \u06c1\u0648 \u0633\u06a9\u062a\u06d2 \u06c1\u06cc\u06ba \u0627\u0648\u0631 \u062c\u06cc\u0646\u06a9\u0646\u0632 \u06a9\u06d2 \u062c\u0648 \u0628\u06be\u06cc \u0644\u0646\u06a9\u0633 \u062a\u06cc\u0627\u0631 \u06a9\u0631\u062a\u06d2 \u06c1\u06cc\u06ba \u0648\u06c1 \u063a\u0644\u0637 \u0627\u06cc\u0688\u0631\u06cc\u0633 (\u0627\u06a9\u062b\u0631 \u0622\u067e \u06a9\u06d2 \u0644\u0648\u06a9\u0644 \u06c1\u0648\u0633\u0679 \u06cc\u0627 \u0627\u0646\u062f\u0631\u0648\u0646\u06cc IP) \u06a9\u06cc \u0637\u0631\u0641 \u0627\u0634\u0627\u0631\u06c1 \u06a9\u0631\u06cc\u06ba \u06af\u06d2\u06d4<\/p>\n<h2 id=\"heading-7-first-time-jenkins-setup\">7. \u067e\u06c1\u0644\u0627 \u062c\u06cc\u0646\u06a9\u0646\u0632 \u0633\u06cc\u0679 \u0627\u067e<\/h2>\n<p>\u0627\u06af\u0631 \u0622\u067e \u067e\u06c1\u0644\u06cc \u0628\u0627\u0631 \u0627\u0633 \u0633\u0631\u0648\u0631 \u067e\u0631 \u062c\u06cc\u0646\u06a9\u0646\u0632 \u0686\u0644\u0627 \u0631\u06c1\u06d2 \u06c1\u06cc\u06ba\u060c \u062a\u0648 \u0627\u0628\u062a\u062f\u0627\u0626\u06cc \u0633\u06cc\u0679 \u0627\u067e \u0645\u06a9\u0645\u0644 \u06a9\u0631\u0646\u06d2 \u06a9\u06d2 \u0644\u06cc\u06d2 \u0627\u0633 \u0633\u06cc\u06a9\u0634\u0646 \u06a9\u06cc \u067e\u06cc\u0631\u0648\u06cc \u06a9\u0631\u06cc\u06ba\u06d4<\/p>\n<p>\u0627\u06af\u0631 \u0622\u067e \u067e\u06c1\u0644\u06d2 \u06c1\u06cc \u062c\u06cc\u0646\u06a9\u0646\u0632 \u06a9\u0648 \u06a9\u0646\u0641\u06cc\u06af\u0631 \u06a9\u0631 \u0686\u06a9\u06d2 \u06c1\u06cc\u06ba \u062a\u0648 \u0622\u067e \u0627\u0633 \u0633\u06cc\u06a9\u0634\u0646 \u06a9\u0648 \u0686\u06be\u0648\u0691 \u0633\u06a9\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4 \u062a\u0627\u06c1\u0645\u060c \u06cc\u0642\u06cc\u0646\u06cc \u0628\u0646\u0627\u0626\u06cc\u06ba \u06a9\u06c1 \u0645\u0637\u0644\u0648\u0628\u06c1 \u067e\u0644\u06af \u0627\u0646 \u0627\u0648\u0631 \u0633\u06cc\u0679\u0646\u06af\u0632 \u0627\u0646 \u0633\u06d2 \u0645\u06cc\u0644 \u06a9\u06be\u0627\u062a\u06cc \u06c1\u06cc\u06ba \u062c\u0648 \u0622\u067e \u0628\u0639\u062f \u0645\u06cc\u06ba \u0627\u0633 \u06af\u0627\u0626\u06cc\u0688 \u0645\u06cc\u06ba \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4<\/p>\n<ol>\n<li>\n<p>\u06a9\u06be\u0644\u0627 <code>https:\/\/jenkins.example.com<\/code>. \u0627\u067e\u0646\u0627 \u0627\u0628\u062a\u062f\u0627\u0626\u06cc \u0627\u06cc\u0688\u0645\u0646\u0633\u0679\u0631\u06cc\u0679\u0631 \u067e\u0627\u0633 \u0648\u0631\u0688 \u062d\u0627\u0635\u0644 \u06a9\u0631\u06cc\u06ba:<\/p>\n<pre><code class=\"language-bash\">docker exec projects-jenkins-staging cat \/var\/jenkins_home\/secrets\/initialAdminPassword\n<\/code><\/pre>\n<\/li>\n<li>\n<p>\u0627\u0633\u06d2 \u0686\u0633\u067e\u0627\u06ba \u06a9\u0631\u06cc\u06ba \u0627\u0648\u0631 \u0641\u06cc\u0686\u0631\u0688 \u067e\u0644\u06af \u0627\u0646 \u0627\u0646\u0633\u0679\u0627\u0644 \u06a9\u0631\u06cc\u06ba \u06a9\u0648 \u0645\u0646\u062a\u062e\u0628 \u06a9\u0631\u06cc\u06ba\u06d4<\/p>\n<\/li>\n<li>\n<p>\u0627\u06cc\u06a9 \u0627\u0646\u062a\u0638\u0627\u0645\u06cc \u0635\u0627\u0631\u0641 \u0628\u0646\u0627\u0626\u06cc\u06ba\u06d4<\/p>\n<\/li>\n<li>\n<p>\u062c\u06cc\u0646\u06a9\u0646\u0632 \u0645\u06cc\u0646\u062c\u0645\u0646\u0679 \u2192 \u067e\u0644\u06af \u0627\u0646\u0632 \u2192 \u062f\u0633\u062a\u06cc\u0627\u0628 \u0627\u0648\u0631 \u0627\u0646\u0633\u0679\u0627\u0644:<\/p>\n<\/li>\n<\/ol>\n<p>\u06cc\u06c1 \u0648\u06c1 \u062a\u0645\u0627\u0645 \u067e\u0644\u06af \u0627\u0646 \u06c1\u06cc\u06ba \u062c\u0646 \u06a9\u06cc \u0622\u067e \u06a9\u0648 \u0628\u0627\u0642\u06cc \u06af\u0627\u0626\u06cc\u0688 \u06a9\u06d2 \u0644\u06cc\u06d2 \u0636\u0631\u0648\u0631\u062a \u06c1\u0648\u06af\u06cc\u06d4<\/p>\n<h2 id=\"heading-8-add-the-github-credential\">8. GitHub \u0627\u0633\u0646\u0627\u062f \u0634\u0627\u0645\u0644 \u06a9\u0631\u06cc\u06ba\u06d4<\/h2>\n<p>\u062c\u06cc\u0646\u06a9\u0646\u0632 \u06a9\u0648 \u0622\u067e \u06a9\u06d2 GitHub \u0630\u062e\u06cc\u0631\u06c1 \u062a\u06a9 \u0631\u0633\u0627\u0626\u06cc \u06a9\u06d2 \u0644\u06cc\u06d2 \u0627\u062c\u0627\u0632\u062a \u062f\u0631\u06a9\u0627\u0631 \u06c1\u06d2\u06d4<\/p>\n<p>\u06cc\u06c1 \u0627\u06cc\u06a9 GitHub \u0630\u0627\u062a\u06cc \u0631\u0633\u0627\u0626\u06cc \u0679\u0648\u06a9\u0646 (PAT) \u06a9\u0627 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u062a\u06d2 \u06c1\u0648\u0626\u06d2 \u06a9\u06cc\u0627 \u062c\u0627\u062a\u0627 \u06c1\u06d2\u060c \u062c\u0648 \u0645\u062d\u0641\u0648\u0638 APIs \u0627\u0648\u0631 Git \u0622\u067e\u0631\u06cc\u0634\u0646\u0632 \u06a9\u06d2 \u0644\u06cc\u06d2 \u067e\u0627\u0633 \u0648\u0631\u0688 \u06a9\u06d2 \u0637\u0648\u0631 \u067e\u0631 \u06a9\u0627\u0645 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<p>\u0622\u067e \u067e\u0627\u0626\u067e \u0644\u0627\u0626\u0646 \u067e\u0631 \u0639\u0645\u0644 \u062f\u0631\u0622\u0645\u062f \u06a9\u06d2 \u062f\u0648\u0631\u0627\u0646 \u0627\u067e\u0646\u06d2 \u06a9\u0648\u0688 \u06a9\u0648 \u0628\u0627\u0632\u06cc\u0627\u0641\u062a \u06a9\u0631\u0646\u06d2 \u0627\u0648\u0631 \u0627\u067e\u0646\u06d2 \u0631\u0627\u0632\u0648\u06ba \u06a9\u0648 \u0627\u067e\u0646\u06d2 \u06a9\u0648\u0688 \u067e\u0631 \u0638\u0627\u06c1\u0631 \u06a9\u06cc\u06d2 \u0628\u063a\u06cc\u0631 \u0645\u062d\u0641\u0648\u0638 \u0637\u0631\u06cc\u0642\u06d2 \u0633\u06d2 \u062a\u0635\u062f\u06cc\u0642 \u06a9\u0631\u0646\u06d2 \u06a9\u06d2 \u0644\u06cc\u06d2 \u0627\u0633 \u0679\u0648\u06a9\u0646 \u06a9\u0648 \u062c\u06cc\u0646\u06a9\u0646\u0632 \u06a9\u06d2 \u0627\u0646\u062f\u0631 \u0628\u0637\u0648\u0631 \u0627\u0633\u0646\u0627\u062f \u0627\u0633\u0679\u0648\u0631 \u06a9\u0631 \u0633\u06a9\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4<\/p>\n<p>\u06cc\u06c1 \u0648\u0627\u062d\u062f \u0633\u0646\u062f SCM \u0686\u06cc\u06a9 \u0622\u0624\u0679 \u0627\u0648\u0631 \u062a\u0639\u06cc\u0646\u0627\u062a\u06cc \u06a9\u06d2 \u0648\u0642\u062a \u062f\u0648\u0646\u0648\u06ba \u06a9\u06d2 \u0644\u06cc\u06d2 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06c1\u0648\u062a\u06cc \u06c1\u06d2\u06d4 <code>git pull<\/code>.<\/p>\n<ol>\n<li>\n<p>GitHub \u0645\u06cc\u06ba \u0630\u0627\u062a\u06cc \u0631\u0633\u0627\u0626\u06cc \u06a9\u0627 \u0679\u0648\u06a9\u0646 (\u06a9\u0644\u0627\u0633\u06a9) \u0627\u0633 \u06a9\u0627 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u062a\u06d2 \u06c1\u0648\u0626\u06d2 \u0628\u0646\u0627\u0626\u06cc\u06ba: <code>repo<\/code> \u0631\u06cc\u0646\u062c<\/p>\n<\/li>\n<li>\n<p>\u062c\u06cc\u0646\u06a9\u0646\u0632 \u0645\u06cc\u06ba: \u062c\u06cc\u0646\u06a9\u0646\u0632 \u06a9\u0627 \u0646\u0638\u0645 \u06a9\u0631\u06cc\u06ba \u2192 \u0627\u0633\u0646\u0627\u062f \u2192 \u0633\u0633\u0679\u0645 \u2192 \u06af\u0644\u0648\u0628\u0644 \u2192 \u0627\u0633\u0646\u0627\u062f \u0634\u0627\u0645\u0644 \u06a9\u0631\u06cc\u06ba\u06d4<\/p>\n<\/li>\n<li>\n<p>\u0644\u06a9\u06be\u06cc\u06ba:<\/p>\n<ul>\n<li>\n<p>\u0642\u0633\u0645: \u067e\u0627\u0633 \u0648\u0631\u0688 \u06a9\u06d2 \u0633\u0627\u062a\u06be \u0635\u0627\u0631\u0641 \u0646\u0627\u0645<\/p>\n<\/li>\n<li>\n<p>\u0635\u0627\u0631\u0641 \u0646\u0627\u0645: GitHub \u0635\u0627\u0631\u0641 \u0646\u0627\u0645<\/p>\n<\/li>\n<li>\n<p>\u067e\u0627\u0633 \u0648\u0631\u0688: \u0679\u0648\u06a9\u0646<\/p>\n<\/li>\n<li>\n<p><strong>ID:<\/strong> <code>github_classic_token<\/code> <em>(Jenkinsfile \u0627\u0633 \u0639\u06cc\u0646 ID \u06a9\u0627 \u062d\u0648\u0627\u0644\u06c1 \u062f\u06cc\u062a\u0627 \u06c1\u06d2)<\/em><\/p>\n<\/li>\n<\/ul>\n<\/li>\n<\/ol>\n<h2 id=\"heading-9-create-the-pipeline-job\">9. \u0627\u06cc\u06a9 \u067e\u0627\u0626\u067e \u0644\u0627\u0626\u0646 \u062c\u0627\u0628 \u0628\u0646\u0627\u0626\u06cc\u06ba<\/h2>\n<p>\u0627\u0628 \u062c\u0628 \u06a9\u06c1 \u062c\u06cc\u0646\u06a9\u0646\u0632 \u06a9\u0648 \u0631\u06cc\u067e\u0648\u0632\u0679\u0631\u06cc \u062a\u06a9 \u0631\u0633\u0627\u0626\u06cc \u062d\u0627\u0635\u0644 \u06c1\u06d2\u060c \u0627\u06af\u0644\u0627 \u0645\u0631\u062d\u0644\u06c1 \u0627\u0633 \u0628\u0627\u062a \u06a9\u06cc \u0648\u0636\u0627\u062d\u062a \u06a9\u0631\u0646\u0627 \u06c1\u06d2 \u06a9\u06c1 \u062a\u0639\u06cc\u0646\u0627\u062a\u06cc \u06a9\u06cc\u0633\u06d2 \u0686\u0644\u06d2 \u06af\u06cc\u06d4<\/p>\n<p>\u0627\u06cc\u06a9 \u067e\u0627\u0626\u067e \u0644\u0627\u0626\u0646 \u06a9\u0627\u0645 \u062c\u06cc\u0646\u06a9\u0646\u0632 \u06a9\u0648 \u0628\u062a\u0627\u062a\u0627 \u06c1\u06d2:<\/p>\n<p>\u062c\u06cc\u0646\u06a9\u0646\u0632 \u0645\u06cc\u06ba \u0627\u06cc\u06a9 \u0646\u0626\u06cc \u067e\u0627\u0626\u067e \u0644\u0627\u0626\u0646 \u062c\u0627\u0628 \u0628\u0646\u0627\u0626\u06cc\u06ba \u0627\u0648\u0631 \u0627\u0633\u06d2 \u0627\u067e\u0646\u06d2 GitHub \u0631\u06cc\u067e\u0648\u0632\u0679\u0631\u06cc \u0633\u06d2 \u062c\u0648\u0691\u06cc\u06ba\u06d4 \u0627\u06cc\u06a9 \u0628\u0627\u0631 \u062c\u0628 \u06cc\u06c1 \u0633\u06cc\u0679 \u06c1\u0648 \u062c\u0627\u0626\u06d2 \u06af\u0627\u060c \u062c\u06cc\u0646\u06a9\u0646\u0632 \u06c1\u0631 \u0628\u0627\u0631 \u062c\u0628 \u0622\u067e \u062f\u0628\u0627\u0626\u06cc\u06ba \u06af\u06d2 \u062a\u0648 \u062e\u0648\u062f \u0628\u062e\u0648\u062f \u0627\u06cc\u06a9 \u062a\u0639\u06cc\u0646\u0627\u062a\u06cc \u06a9\u0648 \u0645\u062a\u062d\u0631\u06a9 \u06a9\u0631 \u062f\u06d2 \u06af\u0627\u06d4 <code>staging<\/code> \u062f\u0631\u062e\u062a \u06a9\u06cc \u0634\u0627\u062e\u06cc\u06ba\u06d4<\/p>\n<p>\u0627\u06cc\u06a9 \u0646\u06cc\u0627 \u06a9\u0627\u0645 \u0628\u0646\u0627 \u06a9\u0631 \u0634\u0631\u0648\u0639 \u06a9\u0631\u06cc\u06ba\u06d4<\/p>\n<p>\u0646\u06cc\u0627 \u0622\u0626\u0679\u0645 \u2192 \u067e\u0627\u0626\u067e \u0644\u0627\u0626\u0646 \u2192 \u0627\u06cc\u06a9 \u0646\u0627\u0645 \u06a9\u06cc \u0648\u0636\u0627\u062d\u062a \u06a9\u0631\u06cc\u06ba\u06d4 <code>projects-staging<\/code> \u2192 \u0679\u06be\u06cc\u06a9 \u06c1\u06d2\u06d4<\/p>\n<p>\u067e\u06be\u0631 \u06a9\u0627\u0645 \u06a9\u0648 \u062a\u0631\u062a\u06cc\u0628 \u062f\u06cc\u06ba\u06d4<\/p>\n<p>\u0627\u067e\u0646\u06cc \u062a\u0631\u062a\u06cc\u0628 \u06a9\u0648 \u0645\u062d\u0641\u0648\u0638 \u06a9\u0631\u06cc\u06ba\u06d4<\/p>\n<p>\u0627\u0633 \u0648\u0642\u062a\u060c \u062c\u06cc\u0646\u06a9\u0646\u0632 \u0622\u067e \u06a9\u06d2 \u0630\u062e\u06cc\u0631\u06d2 \u0633\u06d2 \u0645\u06a9\u0645\u0644 \u0637\u0648\u0631 \u067e\u0631 \u0645\u0646\u0633\u0644\u06a9 \u06c1\u06d2 \u0627\u0648\u0631 \u0622\u067e \u06a9\u06cc \u062a\u0639\u06cc\u0646\u0627\u062a\u06cc \u067e\u0627\u0626\u067e \u0644\u0627\u0626\u0646 \u06a9\u0648 \u062e\u0648\u062f \u0628\u062e\u0648\u062f \u0686\u0644\u0627\u0646\u06d2 \u06a9\u06d2 \u0644\u06cc\u06d2 \u062a\u06cc\u0627\u0631 \u06c1\u06d2\u06d4<\/p>\n<h2 id=\"heading-10-the-jenkinsfile-deploy-only-what-changed\">10. \u062c\u06cc\u0646\u06a9\u0646\u0632 \u0641\u0627\u0626\u0644 (\u0635\u0631\u0641 \u062a\u0628\u062f\u06cc\u0644\u06cc\u0627\u06ba \u062a\u0639\u06cc\u0646\u0627\u062a \u06a9\u0631\u06cc\u06ba)<\/h2>\n<p>\u0627\u0633\u06d2 \u0627\u067e\u0646\u06cc \u062c\u0691 \u0645\u06cc\u06ba \u0631\u06a9\u06be\u06cc\u06ba\u06d4 <strong>\u0627\u06cc\u067e<\/strong> \u0631\u06cc\u067e\u0648 (<code>projects-backend\/Jenkinsfile<\/code>)\u060c \u062f\u0631\u062e\u062a \u06a9\u06cc \u0634\u0627\u062e\u06cc\u06ba <code>staging<\/code>.<\/p>\n<pre><code class=\"language-groovy\">pipeline {\n  agent any\n\n  environment {\n    PROJECT_PATH = \"\/projects\/projects-prod-configs\/projects-backend\"\n    COMPOSE_FILE = \"docker-compose.staging.yml\"\n  }\n\n  stages {\n\n    stage('Checkout') {\n      steps {\n        checkout scm\n        echo \"Checkout completed for branch: ${env.BRANCH_NAME ?: 'staging'}\"\n      }\n    }\n\n    stage('Detect Changes') {\n      steps {\n        script {\n          def changedFiles = sh(\n            script: \"git diff --name-only HEAD~1 HEAD\",\n            returnStdout: true\n          ).trim()\n\n          echo \"Changed files:\\n${changedFiles}\"\n\n          def services = [] as Set\n          changedFiles.split('\\n').each { file ->\n            def svc  = file =~ \/^apps\\\/services\\\/([a-z0-9-]+)\\\/\/\n            def gw   = file =~ \/^apps\\\/gateways\\\/([a-z0-9-]+)\\\/\/\n            def core = file =~ \/^apps\\\/core\\\/([a-z0-9-]+)\\\/\/\n            if (svc)  { services << svc[0][1]  }\n            if (gw)   { services << gw[0][1]   }\n            if (core) { services << core[0][1] }\n          }\n          services = services.findAll { !it.endsWith('-e2e') }\n          env.CHANGED_SERVICES = services.join(' ')\n\n          echo \"Services to deploy: ${env.CHANGED_SERVICES ?: '(none)'}\"\n        }\n      }\n    }\n\n    stage('Deploy') {\n      when { expression { return env.CHANGED_SERVICES?.trim() } }\n      steps {\n        withCredentials([usernamePassword(\n          credentialsId: 'github_classic_token',\n          usernameVariable: 'GIT_USER',\n          passwordVariable: 'GIT_TOKEN'\n        )]) {\n          sh '''\n            set -eu\n            git config --global --add safe.directory \"${PROJECT_PATH}\"\n            cd \"${PROJECT_PATH}\"\n            git remote set-url origin \"https:\/\/github.com\/<org>\/projects-backend.git\"\n            git -c credential.helper= \\\n                -c \"credential.helper=!f() { echo username=\\({GIT_USER}; echo password=\\){GIT_TOKEN}; }; f\" \\\n                pull origin staging\n            docker compose -f \"\\({COMPOSE_FILE}\" up -d --build \\){CHANGED_SERVICES}\n          '''\n        }\n        echo \"Deployed: ${env.CHANGED_SERVICES}\"\n      }\n    }\n\n    stage('Skip Deployment') {\n      when { expression { return !env.CHANGED_SERVICES?.trim() } }\n      steps { echo \"No service changes detected \u2014 nothing to deploy.\" }\n    }\n  }\n}\n<\/org><\/code><\/pre>\n<p>\u06cc\u06c1\u0627\u06ba \u06c1\u0631 \u0627\u06cc\u06a9 \u0645\u0634\u06a9\u0644 \u0644\u0627\u0626\u0646 \u06a9\u06cc\u0648\u06ba \u06c1\u06d2:<\/p>\n<ul>\n<li>\n<p><code>git config --global --add safe.directory ...<\/code>    &#8211; \u06af\u0679 \u0631\u06cc\u067e\u0648\u0632\u0679\u0631\u06cc\u0648\u06ba \u067e\u0631 \u06a9\u0627\u0631\u0631\u0648\u0627\u0626\u06cc\u0648\u06ba \u06a9\u0648 \u0645\u0633\u062a\u0631\u062f \u06a9\u0631\u062a\u0627 \u06c1\u06d2 \u062c\u0646 \u06a9\u0627 \u0645\u0627\u0644\u06a9 UID \u0645\u0648\u062c\u0648\u062f\u06c1 \u0635\u0627\u0631\u0641 \u0633\u06d2 \u0645\u062e\u062a\u0644\u0641 \u06c1\u06d2\u06d4 \u0688\u0633\u06a9 \u067e\u0631 \u0627\u0633\u0679\u0648\u0631\u06cc\u062c \u06a9\u06cc \u0645\u0644\u06a9\u06cc\u062a \u06c1\u06d2: <code>developer<\/code>\u0644\u06cc\u06a9\u0646 \u06a9\u0646\u0679\u06cc\u0646\u0631 \u06a9\u06d2 \u0627\u0646\u062f\u0631 \u06af\u0679 \u0627\u0633 \u0637\u0631\u062d \u0686\u0644\u062a\u0627 \u06c1\u06d2: <code>root<\/code>. \u0627\u0633 \u0633\u06d2 \u0648\u0627\u0626\u0679 \u0644\u0633\u0679 \u0645\u06cc\u06ba \u0631\u0627\u0633\u062a\u06c1 \u0634\u0627\u0645\u0644 \u06c1\u0648 \u062c\u0627\u0626\u06d2 \u06af\u0627\u06d4<\/p>\n<\/li>\n<li>\n<p><code>git remote set-url origin \"https:\/\/...\"<\/code>    &#8211; \u0622\u0646 \u0688\u0633\u06a9 \u0631\u06cc\u0645\u0648\u0679 \u06a9\u0648 HTTPS \u0645\u06cc\u06ba \u062a\u0628\u062f\u06cc\u0644 \u06a9\u0631\u06a9\u06d2 <strong>\u0679\u0648\u06a9\u0646 \u062f\u0633\u062a\u06cc\u0627\u0628 \u06c1\u06cc\u06ba\u06d4<\/strong>. (PAT \u06a9\u06cc \u062a\u0648\u062b\u06cc\u0642 \u0646\u06c1\u06cc\u06ba \u06a9\u06cc \u062c\u0627 \u0633\u06a9\u062a\u06cc\u06d4 <code>git@github.com:<\/code> URL &#8211; SSH \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4) Idempotent &#8211; \u062f\u0648\u0628\u0627\u0631\u06c1 \u0686\u0644\u0627\u0646\u06d2 \u06a9\u06d2 \u0644\u06cc\u06d2 \u0645\u062d\u0641\u0648\u0638\u06d4<\/p>\n<\/li>\n<li>\n<p><code>git -c credential.helper=\"!f() { echo username=...; echo password=...; }; f\"<\/code>    \u2014 \u0627\u0633 \u06a9\u0645\u0627\u0646\u0688 \u06a9\u06d2 \u0644\u06cc\u06d2 \u06af\u0679 \u06a9\u0648 \u0635\u0627\u0631\u0641 \u0646\u0627\u0645\/\u0679\u0648\u06a9\u0646 \u0641\u0631\u0627\u06c1\u0645 \u06a9\u0631\u06cc\u06ba \u0628\u063a\u06cc\u0631 \u0679\u0648\u06a9\u0646 \u06a9\u0648 \u0688\u0633\u06a9 \u067e\u0631 \u0644\u06a9\u06be\u06d2 \u0627\u0648\u0631 \u0627\u0633\u06d2 \u0639\u0645\u0644 \u06a9\u06cc \u06a9\u0645\u0627\u0646\u0688 \u0644\u0627\u0626\u0646 \u067e\u0631 \u0638\u0627\u06c1\u0631 \u06a9\u06cc\u06d2 \u0628\u063a\u06cc\u0631\u06d4<\/p>\n<\/li>\n<li>\n<p><code>${CHANGED_SERVICES}<\/code>    \u0648\u06c1 \u062c\u0627\u0646 \u0628\u0648\u062c\u06be \u06a9\u0631 \u063a\u06cc\u0631 \u0646\u0642\u0644 \u0634\u062f\u06c1 \u06c1\u06cc\u06ba\u060c \u0644\u06c1\u0630\u0627 \u0645\u062a\u0639\u062f\u062f \u0633\u0631\u0648\u0633 \u06a9\u06d2 \u0646\u0627\u0645\u0648\u06ba \u06a9\u0648 \u0627\u0644\u06af \u0627\u0644\u06af \u062f\u0644\u0627\u0626\u0644 \u0645\u06cc\u06ba \u0628\u0691\u06be\u0627 \u062f\u06cc\u0627 \u06af\u06cc\u0627 \u06c1\u06d2\u06d4<\/p>\n<\/li>\n<\/ul>\n<h2 id=\"heading-11-end-to-end-test\">11. \u0627\u06cc\u0646\u0688 \u0679\u0648 \u0627\u06cc\u0646\u0688 \u0679\u06cc\u0633\u0679\u0646\u06af<\/h2>\n<p>\u0633\u06cc\u0679 \u0627\u067e \u0645\u06a9\u0645\u0644 \u06a9\u0631\u0646\u06d2 \u067e\u0631 \u063a\u0648\u0631 \u06a9\u0631\u0646\u06d2 \u0633\u06d2 \u067e\u06c1\u0644\u06d2\u060c \u0622\u067e \u06a9\u0648 \u062a\u0635\u062f\u06cc\u0642 \u06a9\u0631\u0646\u06cc \u0686\u0627\u06c1\u06cc\u06d2 \u06a9\u06c1 \u067e\u0648\u0631\u06cc \u067e\u0627\u0626\u067e \u0644\u0627\u0626\u0646 \u062a\u0648\u0642\u0639 \u06a9\u06d2 \u0645\u0637\u0627\u0628\u0642 \u06a9\u0627\u0645 \u06a9\u0631 \u0631\u06c1\u06cc \u06c1\u06d2\u06d4<\/p>\n<p>\u06cc\u06c1 \u0622\u062e\u0631 \u0633\u06d2 \u0622\u062e\u0631 \u062a\u06a9 \u062c\u0627\u0646\u0686 \u06cc\u0642\u06cc\u0646\u06cc \u0628\u0646\u0627\u062a\u06cc \u06c1\u06d2:<\/p>\n<ul>\n<li>\n<p>GitHub \u0648\u06cc\u0628 \u06c1\u06a9 \u062c\u06cc\u0646\u06a9\u0646\u0632 \u06a9\u0648 \u0635\u062d\u06cc\u062d \u0637\u0631\u06cc\u0642\u06d2 \u0633\u06d2 \u0645\u062a\u062d\u0631\u06a9 \u06a9\u0631 \u0631\u06c1\u0627 \u06c1\u06d2\u06d4<\/p>\n<\/li>\n<li>\n<p>\u062c\u06cc\u0646\u06a9\u0646\u0632 \u0627\u0633 \u0628\u0627\u062a \u06a9\u0627 \u067e\u062a\u06c1 \u0644\u06af\u0627 \u0633\u06a9\u062a\u06d2 \u06c1\u06cc\u06ba \u06a9\u06c1 \u06a9\u0648\u0646 \u0633\u06cc \u062e\u062f\u0645\u0627\u062a \u062a\u0628\u062f\u06cc\u0644 \u06c1\u0648\u0626\u06cc \u06c1\u06cc\u06ba\u06d4<\/p>\n<\/li>\n<li>\n<p>\u0635\u0631\u0641 \u0645\u062a\u0627\u062b\u0631\u06c1 \u062e\u062f\u0645\u0627\u062a \u06a9\u0648 \u062f\u0648\u0628\u0627\u0631\u06c1 \u062a\u0639\u0645\u06cc\u0631 \u0627\u0648\u0631 \u062a\u0639\u06cc\u0646\u0627\u062a \u06a9\u06cc\u0627 \u062c\u0627\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<\/li>\n<\/ul>\n<p>\u062f\u0648\u0633\u0631\u06d2 \u0627\u0644\u0641\u0627\u0638 \u0645\u06cc\u06ba\u060c \u06cc\u06c1 \u0627\u06cc\u06a9 \u062d\u0642\u06cc\u0642\u06cc \u067e\u06cc\u062f\u0627\u0648\u0627\u0631 \u06a9\u06cc \u062a\u0639\u06cc\u0646\u0627\u062a\u06cc \u06a9\u06cc \u0646\u0642\u0644 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<p>\u0627\u067e\u0646\u06d2 \u0630\u062e\u06cc\u0631\u06d2 \u0645\u06cc\u06ba \u06a9\u0686\u06be \u062a\u0628\u062f\u06cc\u0644\u06cc\u0627\u06ba \u06a9\u0631\u06a9\u06d2 \u0634\u0631\u0648\u0639 \u06a9\u0631\u06cc\u06ba\u06d4 \u0645\u062b\u0627\u0644 \u06a9\u06d2 \u0637\u0648\u0631 \u067e\u0631\u060c \u0641\u0627\u0626\u0644\u0648\u06ba \u06a9\u06d2 \u0627\u0646\u062f\u0631 \u062a\u0631\u0645\u06cc\u0645 \u06a9\u0631\u06cc\u06ba:<\/p>\n<p>app\/gateway\/student-apigw\/<\/p>\n<p>\u067e\u06be\u0631 \u0627\u067e\u0646\u06cc \u062a\u0628\u062f\u06cc\u0644\u06cc\u0627\u06ba \u06a9\u0631\u06cc\u06ba\u06d4 <code>staging<\/code> \u062f\u0631\u062e\u062a \u06a9\u06cc \u0634\u0627\u062e\u06cc\u06ba\u06d4<\/p>\n<p>\u062c\u0628 \u062f\u06be\u06a9\u0627 \u062f\u06cc\u0627 \u062c\u0627\u062a\u0627 \u06c1\u06d2\u060c \u062c\u06cc\u0646\u06a9\u0646\u0632 \u062e\u0648\u062f \u0628\u062e\u0648\u062f \u0648\u06cc\u0628 \u06c1\u06a9 \u06a9\u06d2 \u0630\u0631\u06cc\u0639\u06d2 \u0645\u062a\u062d\u0631\u06a9 \u06c1\u0648\u062c\u0627\u062a\u0627 \u06c1\u06d2\u06d4 \u0627\u06af\u0631 \u0646\u06c1\u06cc\u06ba\u060c \u062a\u0648 \u0622\u067e \u0627\u0633\u06d2 \u062f\u0633\u062a\u06cc \u0637\u0648\u0631 \u067e\u0631 \u06a9\u0644\u06a9 \u06a9\u0631 \u0633\u06a9\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4 <strong>\u0627\u0628\u06be\u06cc \u0628\u0646\u0627\u0626\u06cc\u06ba<\/strong>.<\/p>\n<p>\u0627\u0628 \u062a\u0639\u0645\u06cc\u0631 \u06a9\u06be\u0648\u0644\u06cc\u06ba\u06d4 <strong>\u06a9\u0646\u0633\u0648\u0644 \u0622\u0624\u0679 \u067e\u0679<\/strong> \u0627\u0648\u0631 \u0628\u06c1\u0627\u0624 \u0686\u06cc\u06a9 \u06a9\u0631\u06cc\u06ba\u06d4 \u0622\u067e \u06a9\u0648 \u06a9\u0686\u06be \u0627\u0633 \u0637\u0631\u062d \u0646\u0638\u0631 \u0622\u0626\u06d2 \u06af\u0627:<\/p>\n<ul>\n<li>\n<p>\u0628\u0631\u0627\u0646\u0686 \u0627\u062f\u0627\u0626\u06cc\u06af\u06cc \u0645\u06a9\u0645\u0644: \u062a\u06cc\u0627\u0631\u06cc<\/p>\n<\/li>\n<li>\n<p>\u062a\u0639\u06cc\u0646\u0627\u062a \u06a9\u0631\u0646\u06d2 \u06a9\u06cc \u062e\u062f\u0645\u062a: \u0637\u0627\u0644\u0628 \u0639\u0644\u0645-apigw<\/p>\n<\/li>\n<li>\n<p>\u06af\u0679 \u067e\u0644 \u0633\u0648\u0631\u0633 \u062a\u06cc\u0627\u0631 \u06a9\u0631\u06cc\u06ba (\u06a9\u0627\u0645\u06cc\u0627\u0628\u06cc)<\/p>\n<\/li>\n<li>\n<p>docker \u06a9\u0645\u067e\u0648\u0632 &#8230; up -d &#8211;build student-apigw<\/p>\n<\/li>\n<li>\n<p>\u062a\u0639\u06cc\u0646\u0627\u062a: \u0637\u0627\u0644\u0628 \u0639\u0644\u0645-apigw<\/p>\n<\/li>\n<\/ul>\n<p>\u0627\u06af\u0631 \u0622\u067e \u06cc\u06c1 \u062a\u0631\u062a\u06cc\u0628 \u062f\u06cc\u06a9\u06be\u062a\u06d2 \u06c1\u06cc\u06ba\u060c \u062a\u0648 \u0622\u067e \u06a9\u06cc \u067e\u0627\u0626\u067e \u0644\u0627\u0626\u0646 \u0635\u062d\u06cc\u062d \u0637\u0631\u06cc\u0642\u06d2 \u0633\u06d2 \u06a9\u0627\u0645 \u06a9\u0631 \u0631\u06c1\u06cc \u06c1\u06d2\u06d4<\/p>\n<p>\u0627\u06af\u0631 \u0622\u067e \u06a9\u0648 \u06a9\u0648\u0626\u06cc \u067e\u0631\u06cc\u0634\u0627\u0646\u06cc \u06c1\u0648\u062a\u06cc \u06c1\u06d2 \u062a\u0648 \u067e\u0631\u06cc\u0634\u0627\u0646 \u0646\u06c1 \u06c1\u0648\u06ba\u06d4 \u0628\u0631\u0627\u06c1 \u06a9\u0631\u0645 \u0633\u06cc\u06a9\u0634\u0646 12 \u067e\u0631 \u062c\u0627\u0626\u06cc\u06ba \u062c\u06c1\u0627\u06ba \u062a\u0645\u0627\u0645 \u0639\u0627\u0645 \u0645\u0633\u0627\u0626\u0644 \u0627\u0648\u0631 \u062d\u0644 \u062f\u0633\u062a\u0627\u0648\u06cc\u0632 \u06a9\u06cc\u06d2 \u06af\u0626\u06d2 \u06c1\u06cc\u06ba\u06d4<\/p>\n<h2 id=\"heading-12-troubleshooting-every-error-we-hit\">12. \u062e\u0631\u0627\u0628\u06cc\u0648\u06ba \u06a9\u0627 \u0633\u0631\u0627\u063a \u0644\u06af\u0627\u0646\u0627 &#8211; \u06a9\u0633\u06cc \u0628\u06be\u06cc \u062e\u0631\u0627\u0628\u06cc \u06a9\u0627 \u0633\u0627\u0645\u0646\u0627 \u06a9\u0631\u0646\u0627 \u067e\u0691\u0627<\/h2>\n<p>\u0627\u0633 \u062d\u0635\u06d2 \u0645\u06cc\u06ba \u0627\u0646 \u062d\u0642\u06cc\u0642\u06cc \u0645\u0633\u0627\u0626\u0644 \u06a9\u0627 \u0627\u062d\u0627\u0637\u06c1 \u06a9\u06cc\u0627 \u06af\u06cc\u0627 \u06c1\u06d2 \u062c\u0646 \u06a9\u0627 \u06c1\u0645\u06cc\u06ba \u0627\u0633 \u067e\u0627\u0626\u067e \u0644\u0627\u0626\u0646 \u06a9\u0648 \u0642\u0627\u0626\u0645 \u06a9\u0631\u062a\u06d2 \u0648\u0642\u062a \u0633\u0627\u0645\u0646\u0627 \u06a9\u0631\u0646\u0627 \u067e\u0691\u0627\u060c \u0627\u0648\u0631 \u0627\u0633 \u0633\u06d2 \u0628\u06be\u06cc \u0627\u06c1\u0645: <em>\u06c1\u0631 \u0641\u06a9\u0633 \u06a9\u06cc\u0648\u06ba \u06a9\u0627\u0645 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4<\/em>. &quot;\u06a9\u06cc\u0648\u06ba&#8221; \u06a9\u0648 \u0633\u0645\u062c\u06be\u0646\u0627 \u0622\u067e \u06a9\u0648 \u0627\u067e\u0646\u06d2 \u0633\u06cc\u0679 \u0627\u067e \u0645\u06cc\u06ba \u0627\u0633\u06cc \u0637\u0631\u062d \u06a9\u06d2 \u0645\u0633\u0627\u0626\u0644 \u06a9\u0648 \u0679\u06be\u06cc\u06a9 \u06a9\u0631\u0646\u06d2 \u0645\u06cc\u06ba \u0645\u062f\u062f \u06a9\u0631\u06d2 \u06af\u0627\u06d4<\/p>\n<h3 id=\"heading-cd-cant-cd-to-projectsprojects-prod-configsprojects-backend\">CD: \/projects\/projects-prod-configs\/projects-backend \u06a9\u0648 CD \u06a9\u0631\u0646\u06d2 \u0633\u06d2 \u0642\u0627\u0635\u0631 \u06c1\u06d2\u06d4<\/h3>\n<p><strong>\u0648\u062c\u06c1:<\/strong><br \/>\u062c\u06cc\u0646\u06a9\u0646\u0632 \u0641\u0627\u0626\u0644 \u0686\u0644\u062a\u0627 \u06c1\u06d2\u06d4 <code>cd $PROJECT_PATH<\/code>\u062a\u0627\u06c1\u0645\u060c \u0648\u06c1 \u0631\u0627\u0633\u062a\u06c1 \u06a9\u0646\u0679\u06cc\u0646\u0631 \u06a9\u06d2 \u0627\u0646\u062f\u0631 \u0645\u0648\u062c\u0648\u062f \u0646\u06c1\u06cc\u06ba \u06c1\u06d2\u06d4 \u06cc\u06c1 \u0639\u0627\u0645 \u0637\u0648\u0631 \u067e\u0631 \u06c1\u0648\u062a\u0627 \u06c1\u06d2 \u062c\u0628:<\/p>\n<ul>\n<li>\n<p>\u067e\u0631\u0648\u062c\u06cc\u06a9\u0679 \u06a9\u0648 \u0645\u06cc\u0632\u0628\u0627\u0646 \u067e\u0631 \u0646\u0642\u0644 \u0646\u06c1\u06cc\u06ba \u06a9\u06cc\u0627 \u06af\u06cc\u0627 \u06c1\u06d2\u060c \u06cc\u0627<\/p>\n<\/li>\n<li>\n<p>\u0628\u0627\u0626\u0646\u0688 \u0645\u0627\u0624\u0646\u0679 \u062f\u0631\u0633\u062a \u0637\u0631\u06cc\u0642\u06d2 \u0633\u06d2 \u062a\u0631\u062a\u06cc\u0628 \u0646\u06c1\u06cc\u06ba \u062f\u06cc\u0627 \u06af\u06cc\u0627 \u06c1\u06d2\u06d4<\/p>\n<\/li>\n<\/ul>\n<p><strong>\u062f\u0631\u0633\u062a \u06a9\u0631\u06cc\u06ba:<\/strong><\/p>\n<pre><code class=\"language-bash\">ls \/home\/developer\/projects\/projects-prod-configs\/projects-backend\n# If missing: git clone -b staging <url> there.\n<\/url><\/code><\/pre>\n<p>\u0628\u0627\u0626\u0646\u0688 \u0645\u0627\u0624\u0646\u0679 \u06a9\u0648 \u0686\u06cc\u06a9 \u06a9\u0631\u06cc\u06ba\u06d4<\/p>\n<pre><code class=\"language-plaintext\">docker inspect projects-jenkins-staging --format '{{range .Mounts}}{{.Source}} -> {{.Destination}}{{println}}{{end}}'\n<\/code><\/pre>\n<p>\u0627\u06af\u0631 \u06a9\u0646\u0679\u06cc\u0646\u0631 \u063a\u0627\u0626\u0628 \u06c1\u06d2 \u062a\u0648 \u0627\u0633\u06d2 \u062f\u0648\u0628\u0627\u0631\u06c1 \u0628\u0646\u0627\u0626\u06cc\u06ba\u06d4<\/p>\n<pre><code class=\"language-plaintext\">docker compose -f docker-compose.staging.yml up -d --force-recreate jenkins\n<\/code><\/pre>\n<p><strong>\u06cc\u06c1 \u06a9\u06cc\u0648\u06ba \u06a9\u0627\u0645 \u06a9\u0631\u062a\u0627 \u06c1\u06d2:<\/strong><\/p>\n<p>\u062c\u06cc\u0646\u06a9\u0646\u0632 \u0627\u06cc\u06a9 \u06a9\u0646\u0679\u06cc\u0646\u0631 \u06a9\u06d2 \u0627\u0646\u062f\u0631 \u0686\u0644\u062a\u0627 \u06c1\u06d2\u060c \u0644\u06cc\u06a9\u0646 \u0627\u0633 \u06a9\u0627 \u06a9\u0648\u0688 \u0645\u06cc\u0632\u0628\u0627\u0646 \u067e\u0631 \u0631\u06c1\u062a\u0627 \u06c1\u06d2\u06d4 \u0627\u06cc\u06a9 \u0628\u0627\u0626\u0646\u0688 \u0645\u0627\u0624\u0646\u0679 \u0627\u0646 \u06a9\u0648 \u062c\u0648\u0691\u062a\u0627 \u06c1\u06d2\u06d4 \u0627\u0633 \u06a9\u06d2 \u0628\u063a\u06cc\u0631\u060c \u062c\u06cc\u0646\u06a9\u0646\u0632 \u0622\u067e \u06a9\u06cc \u067e\u0631\u0648\u062c\u06cc\u06a9\u0679 \u0688\u0627\u0626\u0631\u06a9\u0679\u0631\u06cc \u062a\u06a9 \u0631\u0633\u0627\u0626\u06cc \u062d\u0627\u0635\u0644 \u0646\u06c1\u06cc\u06ba \u06a9\u0631 \u0633\u06a9\u06cc\u06ba \u06af\u06d2\u06d4<\/p>\n<h3 id=\"heading-fatal-detected-dubious-ownership-in-repository\">\u0645\u06c1\u0644\u06a9: \u0630\u062e\u06cc\u0631\u06c1 \u0645\u06cc\u06ba \u0645\u0628\u06c1\u0645 \u0645\u0644\u06a9\u06cc\u062a \u06a9\u0627 \u067e\u062a\u06c1 \u0686\u0644\u0627\u06d4<\/h3>\n<p><strong>\u0648\u062c\u06c1:<\/strong><br \/>\u0627\u06af\u0631 \u0630\u062e\u06cc\u0631\u06c1 \u06a9\u0627 \u0645\u0627\u0644\u06a9 \u0645\u0648\u062c\u0648\u062f\u06c1 \u0635\u0627\u0631\u0641 \u0633\u06d2 \u0645\u062e\u062a\u0644\u0641 \u06c1\u06d2 \u062a\u0648 \u06af\u0679 \u0631\u0633\u0627\u0626\u06cc \u06a9\u0648 \u0631\u0648\u06a9\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<p><strong>\u062f\u0631\u0633\u062a \u06a9\u0631\u06cc\u06ba:<\/strong><\/p>\n<pre><code class=\"language-plaintext\">git config --global --add safe.directory \"${PROJECT_PATH}\"\n<\/code><\/pre>\n<p><strong>\u06cc\u06c1 \u06a9\u06cc\u0648\u06ba \u06a9\u0627\u0645 \u06a9\u0631\u062a\u0627 \u06c1\u06d2:<\/strong><\/p>\n<p>\u06cc\u06c1 \u0648\u0627\u0636\u062d \u0637\u0648\u0631 \u067e\u0631 Git \u06a9\u0648 \u0628\u062a\u0627\u062a\u0627 \u06c1\u06d2 \u06a9\u06c1 \u0688\u0627\u0626\u0631\u06cc\u06a9\u0679\u0631\u06cc \u0642\u0627\u0628\u0644 \u0627\u0639\u062a\u0645\u0627\u062f \u06c1\u06d2\u060c \u0645\u0644\u06a9\u06cc\u062a \u06a9\u06cc \u0645\u0645\u0627\u062b\u0644\u062a \u0633\u06d2 \u0645\u062a\u0639\u0644\u0642 \u062d\u0641\u0627\u0638\u062a\u06cc \u067e\u0627\u0628\u0646\u062f\u06cc\u0648\u06ba \u06a9\u0648 \u0646\u0638\u0631\u0627\u0646\u062f\u0627\u0632 \u06a9\u0631\u062a\u06d2 \u06c1\u0648\u0626\u06d2\u06d4<\/p>\n<h3 id=\"heading-host-key-verification-failed-could-not-read-from-remote-repository\"><code>Host key verification failed<\/code>    \/ <code>Could not read from remote repository<\/code><\/h3>\n<h4 id=\"heading-cause\">\u0648\u062c\u06c1:<\/h4>\n<p>\u0630\u062e\u06cc\u0631\u06c1 SSH \u06a9\u06d2 \u0630\u0631\u06cc\u0639\u06d2 \u06c1\u06d2 (<code>git@github.com:...<\/code>\u0644\u06cc\u06a9\u0646:<\/p>\n<p>\u0645\u0632\u06cc\u062f \u0628\u0631\u0622\u06ba\u060c SSH \u06a9\u06d2 \u0630\u0631\u06cc\u0639\u06d2 GitHub \u0679\u0648\u06a9\u0646\u0632 \u06a9\u06cc \u062a\u0648\u062b\u06cc\u0642 \u0646\u06c1\u06cc\u06ba \u06a9\u06cc \u062c\u0627 \u0633\u06a9\u062a\u06cc \u06c1\u06d2\u06d4<\/p>\n<p><strong>\u062a\u0631\u0645\u06cc\u0645 (\u062a\u062c\u0648\u06cc\u0632 \u06a9\u0631\u062f\u06c1):<\/strong><\/p>\n<pre><code class=\"language-plaintext\">git remote set-url origin \"https:\/\/github.com\/<org>\/projects-backend.git\"\n<\/org><\/code><\/pre>\n<p><strong>\u06cc\u06c1 \u06a9\u06cc\u0648\u06ba \u06a9\u0627\u0645 \u06a9\u0631\u062a\u0627 \u06c1\u06d2:<\/strong><\/p>\n<p>HTTPS \u0679\u0648\u06a9\u0646 \u067e\u0631 \u0645\u0628\u0646\u06cc \u062a\u0648\u062b\u06cc\u0642 (PAT) \u06a9\u0627 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u060c \u062c\u0648 SSH \u06a9\u0646\u0641\u06cc\u06af\u0631\u06cc\u0634\u0646 \u06a9\u06d2 \u0628\u063a\u06cc\u0631 \u06a9\u0646\u0679\u06cc\u0646\u0631 \u06a9\u06d2 \u0627\u0646\u062f\u0631 \u06a9\u0627\u0645 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<h3 id=\"heading-unknown-shorthand-flag-f-in-f-docker-compose\"><code>unknown shorthand flag: 'f' in -f<\/code>    ( <code>docker compose<\/code>)<\/h3>\n<p><strong>\u0648\u062c\u06c1:<\/strong><br \/>\u0688\u0648\u06a9\u0631 \u0633\u06cc \u0627\u06cc\u0644 \u0622\u0626\u06cc \u0645\u0648\u062c\u0648\u062f \u06c1\u06d2\u060c \u0644\u06cc\u06a9\u0646 \u0688\u0648\u06a9\u0631 \u06a9\u0645\u067e\u0648\u0632 \u067e\u0644\u06af \u0627\u0646 \u06a9\u0646\u0679\u06cc\u0646\u0631 \u06a9\u06d2 \u0627\u0646\u062f\u0631 \u063a\u0627\u0626\u0628 \u06c1\u06d2\u06d4<\/p>\n<p><strong>\u062f\u0631\u0633\u062a \u06a9\u0631\u06cc\u06ba:<\/strong><\/p>\n<pre><code class=\"language-plaintext\">volumes:\n  - \/usr\/libexec\/docker\/cli-plugins:\/usr\/libexec\/docker\/cli-plugins:ro\n<\/code><\/pre>\n<p>\u0627\u06af\u0631 \u0636\u0631\u0648\u0631\u06cc \u06c1\u0648 \u062a\u0648 \u06c1\u062f\u0627\u06cc\u0627\u062a \u062a\u0644\u0627\u0634 \u06a9\u0631\u06cc\u06ba\u06d4<\/p>\n<pre><code class=\"language-plaintext\">find \/usr -name docker-compose -type f 2>\/dev\/null\n<\/code><\/pre>\n<p>\u0686\u06cc\u06a9 \u06a9\u0631\u06cc\u06ba:<\/p>\n<pre><code class=\"language-plaintext\">docker exec projects-jenkins-staging docker compose version\n<\/code><\/pre>\n<p><strong>\u06cc\u06c1 \u06a9\u06cc\u0648\u06ba \u06a9\u0627\u0645 \u06a9\u0631\u062a\u0627 \u06c1\u06d2:<\/strong><\/p>\n<p>Docker Compose v2 \u0627\u06cc\u06a9 CLI \u067e\u0644\u06af \u0627\u0646 \u06c1\u06d2\u06d4 \u0627\u06af\u0631 \u0645\u06cc\u06ba \u0627\u0633 \u0688\u0627\u0626\u0631\u06cc\u06a9\u0679\u0631\u06cc \u06a9\u0648 \u0645\u0627\u0624\u0646\u0679 \u06a9\u0631\u062a\u0627 \u06c1\u0648\u06ba\u06d4 <code>docker compose<\/code> \u0648\u06c1 \u06a9\u0645\u0627\u0646\u0688\u0632 \u062c\u0648 \u06a9\u0646\u0679\u06cc\u0646\u0631 \u06a9\u06d2 \u0627\u0646\u062f\u0631 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u06cc \u062c\u0627 \u0633\u06a9\u062a\u06cc \u06c1\u06cc\u06ba\u06d4<\/p>\n<h3 id=\"heading-wrong-timezone-in-build-timestamps-and-jenkins-ui\">\u062c\u06cc\u0646\u06a9\u0646\u0632 UI \u0645\u06cc\u06ba \u0679\u0627\u0626\u0645 \u0627\u0633\u0679\u06cc\u0645\u067e \u0627\u0648\u0631 \u0679\u0627\u0626\u0645 \u0632\u0648\u0646 \u06a9\u06cc \u062a\u0639\u0645\u06cc\u0631 \u063a\u0644\u0637 \u06c1\u06d2\u06d4<\/h3>\n<p><strong>\u062f\u0631\u0633\u062a \u06a9\u0631\u06cc\u06ba:<\/strong> env var \u0627\u0648\u0631 JVM \u062f\u0648\u0646\u0648\u06ba \u062c\u06be\u0646\u0688\u06d2 \u0633\u06cc\u0679 \u06a9\u0631\u06cc\u06ba \u0627\u0648\u0631 \u0645\u06cc\u0632\u0628\u0627\u0646 \u06a9\u06cc \u06a9\u0644\u0627\u06a9 \u0641\u0627\u0626\u0644 \u06a9\u0648 \u0628\u0627\u0626\u0646\u0688 \u06a9\u0631\u06cc\u06ba\u06d4<\/p>\n<pre><code class=\"language-yaml\">environment:\n  - TZ=Asia\/Dhaka\n  - JAVA_OPTS=... -Duser.timezone=Asia\/Dhaka\nvolumes:\n  - \/etc\/localtime:\/etc\/localtime:ro\n  - \/etc\/timezone:\/etc\/timezone:ro\n<\/code><\/pre>\n<p>\u0622\u067e <strong>~ \u06a9\u0631\u0646\u0627 \u06c1\u06d2\u06d4<\/strong> env-var \u062a\u0628\u062f\u06cc\u0644\u06cc\u0627\u06ba \u0644\u0627\u06af\u0648 \u06a9\u0631\u0646\u06d2 \u06a9\u06d2 \u0644\u06cc\u06d2 \u06a9\u0646\u0679\u06cc\u0646\u0631 \u06a9\u0648 \u062f\u0648\u0628\u0627\u0631\u06c1 \u0628\u0646\u0627\u0626\u06cc\u06ba\u06d4<\/p>\n<pre><code class=\"language-bash\">docker compose -f docker-compose.staging.yml up -d --force-recreate jenkins\n<\/code><\/pre>\n<p><strong>\u06cc\u06c1 \u06a9\u06cc\u0648\u06ba \u06a9\u0627\u0645 \u06a9\u0631\u062a\u0627 \u06c1\u06d2:<\/strong><br \/>\u062c\u06cc\u0646\u06a9\u0646\u0632 \u062c\u0627\u0648\u0627 \u067e\u0631 OS \u0633\u06d2 \u0622\u0632\u0627\u062f \u0627\u067e\u0646\u06d2 \u0679\u0627\u0626\u0645 \u0632\u0648\u0646 \u06a9\u06d2 \u0633\u0627\u062a\u06be \u0686\u0644\u062a\u0627 \u06c1\u06d2\u06d4<br \/>OS \u0679\u0627\u0626\u0645 \u0632\u0648\u0646\u060c JVM \u0679\u0627\u0626\u0645 \u0632\u0648\u0646\u060c \u0627\u0648\u0631 \u0645\u06cc\u0632\u0628\u0627\u0646 \u06af\u06be\u0691\u06cc \u06a9\u0648 \u0633\u06cc\u062f\u06be \u0645\u06cc\u06ba \u0644\u0627\u0646\u0627 \u06c1\u0631 \u062c\u06af\u06c1 \u0645\u0633\u062a\u0642\u0644 \u0679\u0627\u0626\u0645 \u0633\u0679\u06cc\u0645\u067e \u06a9\u0648 \u06cc\u0642\u06cc\u0646\u06cc \u0628\u0646\u0627\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<h3 id=\"heading-errsockettimeout-pnpm-install-fails\">ERR_SOCKET_TIMEOUT (pnpm \u0627\u0646\u0633\u0679\u0627\u0644\u06cc\u0634\u0646 \u0646\u0627\u06a9\u0627\u0645)<\/h3>\n<h4 id=\"heading-cause\">\u0648\u062c\u06c1:<\/h4>\n<p>\u0627\u06af\u0631 \u0622\u067e \u0645\u062a\u0648\u0627\u0632\u06cc \u0637\u0648\u0631 \u067e\u0631 \u0645\u062a\u0639\u062f\u062f \u062e\u062f\u0645\u0627\u062a \u0628\u0646\u0627\u062a\u06d2 \u06c1\u06cc\u06ba \u0627\u0648\u0631 pnpm \u0627\u0646\u0633\u0679\u0627\u0644 \u06a9\u0648 ~1500 \u067e\u06cc\u06a9\u062c\u0648\u06ba \u06a9\u06d2 \u0633\u0627\u062a\u06be \u0686\u0644\u0627\u062a\u06d2 \u06c1\u06cc\u06ba\u060c \u062a\u0648 \u0646\u06cc\u0679 \u0648\u0631\u06a9 \u0633\u06cc\u0631 \u06c1\u0648 \u062c\u0627\u0626\u06d2 \u06af\u0627 \u0627\u0648\u0631 \u0679\u0627\u0626\u0645 \u0622\u0624\u0679 \u06c1\u0648 \u062c\u0627\u0626\u06d2 \u06af\u0627\u06d4<\/p>\n<h4 id=\"heading-fixes\">\u0627\u0635\u0644\u0627\u062d\u0627\u062a:<\/h4>\n<p>a) \u0679\u0627\u0626\u0645 \u0622\u0624\u0679 + \u06a9\u0646\u06a9\u0631\u0646\u0633\u06cc \u06a9\u0646\u0679\u0631\u0648\u0644 \u0645\u06cc\u06ba \u0627\u0636\u0627\u0641\u06c1 \u06a9\u0631\u06cc\u06ba\u06d4<\/p>\n<pre><code class=\"language-xml\">RUN pnpm install --frozen-lockfile --ignore-scripts \n--network-timeout 600000 \n--network-concurrency 8\n<\/code><\/pre>\n<p>\u0648\u062c\u06c1: pnpm \u06a9\u0648 \u0645\u0632\u06cc\u062f \u0648\u0642\u062a \u062f\u06cc\u06ba \u0627\u0648\u0631 \u0646\u06cc\u0679 \u0648\u0631\u06a9 \u0627\u0648\u0648\u0631\u0644\u0648\u0688 \u06a9\u0648 \u06a9\u0645 \u06a9\u0631\u06cc\u06ba\u06d4<\/p>\n<p>b) pnpm \u06a9\u06cc\u0634\u06d2 \u06a9\u0648 \u0641\u0639\u0627\u0644 \u06a9\u0631\u06cc\u06ba (BuildKit)<\/p>\n<pre><code class=\"language-xml\">RUN --mount=type=cache,id=pnpm-store,target=\/root\/.local\/share\/pnpm\/store \npnpm install --frozen-lockfile --ignore-scripts\n<\/code><\/pre>\n<p>\u06a9\u06cc\u0648\u06ba: \u06c1\u0631 \u0628\u0627\u0631 \u0688\u0627\u0624\u0646 \u0644\u0648\u0688 \u06c1\u0648\u0646\u06d2 \u06a9\u06d2 \u0628\u062c\u0627\u0626\u06d2 \u0627\u0646\u062d\u0635\u0627\u0631 \u06a9\u0648 \u06a9\u06cc\u0634 \u06a9\u06cc\u0627 \u062c\u0627\u062a\u0627 \u06c1\u06d2 \u0627\u0648\u0631 \u062f\u0648\u0628\u0627\u0631\u06c1 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u06cc\u0627 \u062c\u0627\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<p>\u062c) \u063a\u06cc\u0631 \u0636\u0631\u0648\u0631\u06cc \u062a\u0639\u0645\u06cc\u0631 \u0646\u0648 \u0633\u06d2 \u06af\u0631\u06cc\u0632 \u06a9\u0631\u06cc\u06ba\u06d4<\/p>\n<pre><code class=\"language-xml\">docker compose -f \\(COMPOSE_FILE build \\)CHANGED_SERVICES docker compose -f \\(COMPOSE_FILE up -d --no-build \\)CHANGED_SERVICES\n<\/code><\/pre>\n<p>\u0648\u062c\u06c1: \u0635\u0631\u0641 \u062a\u0628\u062f\u06cc\u0644 \u0634\u062f\u06c1 \u062e\u062f\u0645\u0627\u062a \u06a9\u0648 \u062f\u0648\u0628\u0627\u0631\u06c1 \u0628\u0646\u0627\u0626\u06cc\u06ba \u2192 \u0646\u06cc\u0679 \u0648\u0631\u06a9 \u06a9\u0627 \u0628\u0648\u062c\u06be \u06a9\u0645 \u06a9\u0631\u06cc\u06ba \u2192 \u063a\u0644\u0637\u06cc\u0648\u06ba \u06a9\u0648 \u06a9\u0645 \u06a9\u0631\u06cc\u06ba\u06d4<\/p>\n<h3 id=\"heading-container-changes-dont-apply-after-editing-docker-composeyml\">docker-compose.yml \u0645\u06cc\u06ba \u062a\u0631\u0645\u06cc\u0645 \u06a9\u0631\u0646\u06d2 \u06a9\u06d2 \u0628\u0639\u062f \u06a9\u0646\u0679\u06cc\u0646\u0631 \u06a9\u06cc \u062a\u0628\u062f\u06cc\u0644\u06cc\u0627\u06ba \u0644\u0627\u06af\u0648 \u0646\u06c1\u06cc\u06ba \u06c1\u0648\u062a\u06cc \u06c1\u06cc\u06ba\u06d4<\/h3>\n<h4 id=\"heading-cause\">\u0648\u062c\u06c1:<\/h4>\n<p>\u0688\u0648\u06a9\u0631 \u06a9\u0645\u067e\u0648\u0632 \u0627\u067e -d \u0686\u0644\u0646\u06d2 \u0648\u0627\u0644\u06d2 \u06a9\u0646\u0679\u06cc\u0646\u0631\u0632 \u06a9\u0648 \u0627\u067e \u0688\u06cc\u0679 \u0646\u06c1\u06cc\u06ba \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<h4 id=\"heading-fix\">\u062f\u0631\u0633\u062a \u06a9\u0631\u06cc\u06ba:<\/h4>\n<pre><code class=\"language-xml\">docker compose -f docker-compose.staging.yml up -d --force-recreate jenkins\n<\/code><\/pre>\n<p><strong>\u06cc\u06c1 \u06a9\u06cc\u0648\u06ba \u06a9\u0627\u0645 \u06a9\u0631\u062a\u0627 \u06c1\u06d2:<\/strong><\/p>\n<p>\u06cc\u06c1 \u0688\u0648\u06a9\u0631 \u06a9\u0648 \u0627\u067e \u0688\u06cc\u0679 \u06a9\u0646\u0641\u06cc\u06af\u0631\u06cc\u0634\u0646 (env\u060c \u062d\u062c\u0645\u060c \u0644\u06cc\u0628\u0644) \u06a9\u06d2 \u0633\u0627\u062a\u06be \u06a9\u0646\u0679\u06cc\u0646\u0631 \u06a9\u0648 \u062f\u0648\u0628\u0627\u0631\u06c1 \u0628\u0646\u0627\u0646\u06d2 \u06a9\u0627 \u0633\u0628\u0628 \u0628\u0646\u06d2 \u06af\u0627\u06d4<\/p>\n<h3 id=\"heading-traefik-shows-default-certificate-no-https\">Traefik \u0688\u06cc\u0641\u0627\u0644\u0679 \u0633\u0631\u0679\u06cc\u0641\u06a9\u06cc\u0679 \u062f\u06a9\u06be\u0627\u062a\u0627 \u06c1\u06d2 (\u06a9\u0648\u0626\u06cc HTTPS \u0646\u06c1\u06cc\u06ba)\u06d4<\/h3>\n<h4 id=\"heading-common-causes\">\u0639\u0627\u0645 \u0648\u062c\u0648\u06c1\u0627\u062a:<\/h4>\n<p>DNS \u0633\u0631\u0648\u0631 \u067e\u0648\u0631\u0679 80 \u06a9\u06cc \u0637\u0631\u0641 \u0627\u0634\u0627\u0631\u06c1 \u0646\u06c1\u06cc\u06ba \u06a9\u0631\u062a\u0627 \u063a\u0644\u0637 \u0688\u0648\u06a9\u0631 \u0646\u06cc\u0679 \u0648\u0631\u06a9 \u0628\u0644\u0627\u06a9 \u06c1\u06d2\u06d4<\/p>\n<h4 id=\"heading-check\">\u0686\u06cc\u06a9 \u06a9\u0631\u06cc\u06ba:<\/h4>\n<pre><code class=\"language-xml\">dig +short jenkins.example.com docker logs projects-traefik-staging 2>&1 | grep -i acme\n<\/code><\/pre>\n<p><strong>\u06cc\u06c1 \u06a9\u06cc\u0648\u06ba \u06a9\u0627\u0645 \u06a9\u0631\u062a\u0627 \u06c1\u06d2:<\/strong><\/p>\n<p>\u0622\u0626\u06cc\u06d2 \u0627\u0646\u06a9\u0631\u067e\u0679 \u0627\u06cc\u06a9 HTTP-01 \u0686\u06cc\u0644\u0646\u062c \u06a9\u0627 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u060c \u0644\u06c1\u0630\u0627 \u0627\u0633\u06d2 \u067e\u0648\u0631\u0679 80 \u067e\u0631 \u0622\u067e \u06a9\u06d2 \u0633\u0631\u0648\u0631 \u062a\u06a9 \u067e\u06c1\u0646\u0686\u0646\u0627 \u0686\u0627\u06c1\u06cc\u06d2\u06d4 \u0627\u06af\u0631 \u0622\u067e \u06a9\u0627 DNS \u06cc\u0627 \u0646\u06cc\u0679 \u0648\u0631\u06a9\u0646\u06af \u063a\u0644\u0637 \u06c1\u06d2\u060c \u062a\u0648 \u0633\u0631\u0679\u06cc\u0641\u06a9\u06cc\u0679 \u06a9\u0627 \u0627\u062c\u0631\u0627\u0621 \u0646\u0627\u06a9\u0627\u0645 \u06c1\u0648 \u062c\u0627\u0626\u06d2 \u06af\u0627\u06d4<\/p>\n<h3 id=\"heading-jenkins-reverse-proxy-setup-is-broken\">\u062c\u06cc\u0646\u06a9\u0646\u0632: &quot;\u0622\u067e \u06a9\u06cc \u0631\u06cc\u0648\u0631\u0633 \u067e\u0631\u0627\u06a9\u0633\u06cc \u0633\u06cc\u0679\u0646\u06af\u0632 \u062e\u0631\u0627\u0628 \u06c1\u0648 \u06af\u0626\u06cc \u06c1\u06cc\u06ba\u06d4&#8221;<\/h3>\n<h4 id=\"heading-fix\">\u062f\u0631\u0633\u062a \u06a9\u0631\u06cc\u06ba:<\/h4>\n<p>\u062c\u06cc\u0646\u06a9\u0646\u0632 URL \u06a9\u0648 https:\/\/jenkins.example.com\/ \u067e\u0631 \u0633\u06cc\u0679 \u06a9\u0631\u06cc\u06ba\u06d4<br \/>\u06c1\u06cc\u0688\u0631 \u0686\u06cc\u06a9 \u06a9\u0631\u06cc\u06ba:<\/p>\n<pre><code class=\"language-xml\">X-Forwarded-Proto: https\n<\/code><\/pre>\n<p><strong>\u06cc\u06c1 \u06a9\u06cc\u0648\u06ba \u06a9\u0627\u0645 \u06a9\u0631\u062a\u0627 \u06c1\u06d2:<\/strong><\/p>\n<p>\u0622\u067e \u06a9\u0648 \u0645\u0639\u0644\u0648\u0645 \u06c1\u0648\u0646\u0627 \u0686\u0627\u06c1\u0626\u06d2 \u06a9\u06c1 \u062c\u06cc\u0646\u06a9\u0646\u0632 HTTPS \u06a9\u06d2 \u067e\u06cc\u0686\u06be\u06d2 \u06c1\u06d2\u06d4 \u0627\u0633 \u06a9\u06d2 \u0628\u063a\u06cc\u0631\u060c \u063a\u0644\u0637 \u06cc\u0648 \u0622\u0631 \u0627\u06cc\u0644 \u0628\u0646\u0627\u0626\u06d2 \u062c\u0627\u0626\u06cc\u06ba \u06af\u06d2 (https \u06a9\u06d2 \u0628\u062c\u0627\u0626\u06d2 HTTP)\u060c \u0631\u06cc \u0688\u0627\u0626\u0631\u06cc\u06a9\u0679\u0633 \u0627\u0648\u0631 \u0648\u06cc\u0628 \u06c1\u06a9\u0633 \u06a9\u0648 \u062a\u0648\u0691\u062a\u06d2 \u06c1\u0648\u0626\u06d2.<\/p>\n<h2 id=\"heading-13-mental-model-host-vs-container\">13. \u0630\u06c1\u0646\u06cc \u0645\u0627\u0688\u0644: \u0645\u06cc\u0632\u0628\u0627\u0646 \u0628\u0645\u0642\u0627\u0628\u0644\u06c1 \u06a9\u0646\u0679\u06cc\u0646\u0631<\/h2>\n<p>\u062a\u0631\u062a\u06cc\u0628 \u0645\u06cc\u06ba \u0628\u06c1\u062a \u0633\u06cc \u063a\u0644\u0637\u06cc\u0627\u06ba \u06a9\u06cc \u062c\u0627\u062a\u06cc \u06c1\u06cc\u06ba\u06d4 <strong>\u0645\u0627\u0633\u0679\u0631<\/strong> \u0641\u0627\u0626\u0644 \u0633\u0633\u0679\u0645 <strong>\u06a9\u0646\u0679\u06cc\u0646\u0631<\/strong> \u0641\u0627\u0626\u0644 \u0633\u0633\u0679\u0645. \u062c\u062f\u0648\u0644 \u0648\u0627\u0636\u062d \u0637\u0648\u0631 \u067e\u0631 \u06a9\u06c1\u062a\u0627 \u06c1\u06d2:<\/p>\n<table>\n<thead>\n<tr>\n<th>\u062c\u06cc\u0646\u06a9\u0646\u0632 \u06a9\u0646\u0679\u06cc\u0646\u0631 \u06a9\u06d2 \u0627\u0646\u062f\u0631<\/th>\n<th>\u0645\u06cc\u0632\u0628\u0627\u0646 \u06a9\u06d2 \u0630\u0631\u06cc\u0639\u06c1 \u0641\u0631\u0627\u06c1\u0645 \u06a9\u0631\u062f\u06c1<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td><code>\/var\/jenkins_home<\/code><\/td>\n<td>\u0688\u0627\u06a9\u0631 \u062d\u062c\u0645 <code>jenkins-data<\/code> (\u062c\u06cc\u0646\u06a9\u0646\u0632 \u06a9\u06cc \u062a\u0631\u062a\u06cc\u0628\u060c \u06a9\u0627\u0645\u060c \u0631\u0627\u0632)<\/td>\n<\/tr>\n<tr>\n<td><code>\/projects\/...<\/code><\/td>\n<td><code>\/home\/developer\/projects\/...<\/code>    (\u067e\u0631\u0648\u062c\u06cc\u06a9\u0679 \u0679\u0631\u06cc)<\/td>\n<\/tr>\n<tr>\n<td><code>\/usr\/bin\/docker<\/code><\/td>\n<td>\u0645\u06cc\u0632\u0628\u0627\u0646 \u06a9\u06cc <code>\/usr\/bin\/docker<\/code><\/td>\n<\/tr>\n<tr>\n<td><code>\/usr\/libexec\/docker\/cli-plugins\/docker-compose<\/code><\/td>\n<td>\u06c1\u0648\u0633\u0679 \u067e\u0644\u06af \u0627\u0646 ( can <code>docker compose<\/code> \u06a9\u0627\u0645)<\/td>\n<\/tr>\n<tr>\n<td><code>\/var\/run\/docker.sock<\/code><\/td>\n<td>\u0645\u06cc\u0632\u0628\u0627\u0646 \u0688\u0648\u06a9\u0631 \u0688\u06cc\u0645\u0648\u0646 (\u0645\u06cc\u0632\u0628\u0627\u0646 \u0627\u0646\u062c\u0646 \u067e\u0631 \u062a\u0639\u0645\u06cc\u0631\u0627\u062a \u06c1\u0648\u062a\u06cc \u06c1\u06cc\u06ba)<\/td>\n<\/tr>\n<tr>\n<td><code>\/etc\/localtime<\/code>, <code>\/etc\/timezone<\/code><\/td>\n<td>\u0645\u06cc\u0632\u0628\u0627\u0646 \u06af\u06be\u0691\u06cc<\/td>\n<\/tr>\n<tr>\n<td><code>~\/.ssh<\/code><\/td>\n<td><strong>\u06a9\u0686\u06be \u0646\u06c1\u06cc\u06ba<\/strong> &#8211; \u06cc\u06c1\u06cc \u0648\u062c\u06c1 \u06c1\u06d2 \u06a9\u06c1 SSH-to-GitHub \u0627\u0636\u0627\u0641\u06cc \u0633\u06cc\u0679 \u0627\u067e \u06a9\u06d2 \u0628\u063a\u06cc\u0631 \u06a9\u0627\u0645 \u0646\u06c1\u06cc\u06ba \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>\u0688\u06cc\u0628\u06af \u06a9\u0631\u062a\u06d2 \u0648\u0642\u062a\u060c \u06c1\u0645\u06cc\u0634\u06c1 \u062f\u0631\u062c \u0630\u06cc\u0644 \u0633\u0648\u0627\u0644\u0627\u062a \u067e\u0648\u0686\u06be\u06cc\u06ba: <em>&quot;\u06cc\u06c1 \u06a9\u0645\u0627\u0646\u0688 \u06a9\u0633 \u0641\u0627\u0626\u0644 \u0633\u0633\u0679\u0645 \u06a9\u06d2 \u0627\u0646\u062f\u0631 \u0686\u0644 \u0631\u06c1\u0627 \u06c1\u06d2\u060c \u0627\u0648\u0631 \u06a9\u06cc\u0627 \u0622\u067e \u062c\u0633 \u0641\u0627\u0626\u0644\/\u0641\u0648\u0644\u0688\u0631 \u06a9\u06cc \u062a\u0644\u0627\u0634 \u06a9\u0631 \u0631\u06c1\u06d2 \u06c1\u06cc\u06ba \u0648\u06c1 \u0648\u06c1\u0627\u06ba \u0645\u0648\u062c\u0648\u062f \u06c1\u06d2\u061f&#8221;<\/em><\/p>\n<h2 id=\"heading-14-daily-operations-cheat-sheet\">14. \u0631\u0648\u0632\u0627\u0646\u06c1 \u0622\u067e\u0631\u06cc\u0634\u0646\u0632 \u0686\u06cc\u0679 \u0634\u06cc\u0679<\/h2>\n<pre><code class=\"language-bash\"># Recreate Jenkins after changing compose\ncd \/home\/developer\/Projects\/projects-prod-configs\ndocker compose -f docker-compose.staging.yml up -d --force-recreate jenkins\n\n# Tail Jenkins logs\ndocker logs -f projects-jenkins-staging\n\n# Open a shell inside the Jenkins container\ndocker exec -it projects-jenkins-staging bash\n\n# From inside the container \u2014 sanity checks\ndocker compose version\nls \/projects\/projects-prod-configs\/projects-backend\ngit -C \/projects\/projects-prod-configs\/projects-backend remote -v\n\n# Manually trigger the same deploy the pipeline does\ncd \/projects\/projects-configs\/projects-backend\ngit pull origin staging\ndocker compose -f docker-compose.staging.yml up -d --build student-apigw\n\n# Inspect Traefik routing decisions\ndocker logs projects-traefik-staging 2>&1 | grep -i jenkins\n\n# Check renewed certs\ndocker exec projects-traefik-staging cat \/etc\/traefik\/acme.json | head -50\n<\/code><\/pre>\n<h2 id=\"heading-15-what-id-do-differently-next-time\">15. \u0627\u06af\u0644\u06cc \u0628\u0627\u0631 \u0686\u06cc\u0632\u06cc\u06ba \u0645\u062e\u062a\u0644\u0641 \u0637\u0631\u06cc\u0642\u06d2 \u0633\u06d2 \u06a9\u0631\u06cc\u06ba\u06d4<\/h2>\n<ul>\n<li>\n<p><strong>\u067e\u0631\u06cc \u0628\u0644\u0688 \u0628\u06cc\u0633 \u0627\u0645\u06cc\u062c<\/strong> \u062a\u0645\u0627\u0645 node_modules \u0634\u0627\u0645\u0644 \u06c1\u06cc\u06ba\u06d4 ~1500 \u067e\u06cc\u06a9\u062c\u0632 \u00d7 15 \u0633\u0631\u0648\u0633\u0632 \u06a9\u06d2 \u0633\u0627\u062a\u06be\u060c \u06c1\u0631 \u06a9\u0644\u06cc\u0646 \u0628\u0644\u0688 ~22,000 \u0679\u0631\u0628\u0627\u0644\u0632 \u06a9\u0648 \u062f\u0648\u0628\u0627\u0631\u06c1 \u0688\u0627\u0624\u0646 \u0644\u0648\u0688 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4 \u0645\u0634\u062a\u0631\u06a9\u06c1 \u0628\u0646\u06cc\u0627\u062f \u067e\u0631 90% \u06a9\u06cc \u0628\u0686\u062a \u06c1\u0648\u062a\u06cc \u06c1\u06d2\u06d4<\/p>\n<\/li>\n<li>\n<p><strong>\u0646\u062c\u06cc \u0627\u06cc\u0646 \u067e\u06cc \u0627\u06cc\u0645 \u067e\u0631\u0627\u06a9\u0633\u06cc \u0686\u0644\u0627\u0646\u0627<\/strong> \u0627\u0633\u06cc \u0688\u0648\u06a9\u0631 \u0646\u06cc\u0679 \u0648\u0631\u06a9 \u067e\u0631 (Verdaccio\/Nexus\/GitHub \u067e\u06cc\u06a9\u06cc\u062c) &#8211; \u0639\u062f\u0645 \u0627\u0633\u062a\u062d\u06a9\u0627\u0645 \u06a9\u0648 \u062e\u062a\u0645 \u06a9\u0631\u06cc\u06ba <code>npmjs.org<\/code> \u06cc\u06c1 \u0645\u06a9\u0645\u0644 \u0637\u0648\u0631 \u067e\u0631 \u062e\u062a\u0645 \u06c1\u0648 \u062c\u0627\u062a\u0627 \u06c1\u06d2.<\/p>\n<\/li>\n<li>\n<p><strong>\u06c1\u0631 \u0633\u0631\u0648\u0633 \u06a9\u06d2 \u0644\u06cc\u06d2 \u062c\u06cc\u0646\u06a9\u0646\u0632 \u0641\u0627\u0626\u0644<\/strong> \u0627\u06af\u0631 \u0622\u067e \u06a9\u06cc \u0633\u0631\u0648\u0633 \u0679\u0648\u0644\u0646\u06af \u0633\u06d2 \u0627\u0644\u06af \u06c1\u06d2\u06d4 \u0627\u06cc\u06a9 Jenkinsfile \u06a9\u06d2 \u0633\u0627\u062a\u06be\u060c \u062a\u0645\u0627\u0645 \u0679\u06cc\u0645\u06cc\u06ba \u0627\u06cc\u06a9 \u06c1\u06cc \u067e\u0627\u0626\u067e \u0644\u0627\u0626\u0646 \u06a9\u06cc \u062a\u0639\u0631\u06cc\u0641 \u06a9\u06d2 \u0644\u06cc\u06d2 \u0645\u0642\u0627\u0628\u0644\u06c1 \u06a9\u0631\u062a\u06cc \u06c1\u06cc\u06ba\u06d4<\/p>\n<\/li>\n<li>\n<p><strong>\u062a\u0628\u062f\u06cc\u0644\u06cc<\/strong> <code>git diff HEAD~1 HEAD<\/code>    \u06a9\u06d2 \u0633\u0627\u062a\u06be <code>git diff $(git merge-base HEAD origin\/staging~1) HEAD<\/code> \u06cc\u06c1 \u0627\u0633 \u0628\u0627\u062a \u06a9\u0648 \u06cc\u0642\u06cc\u0646\u06cc \u0628\u0646\u0627\u062a\u0627 \u06c1\u06d2 \u06a9\u06c1 \u0622\u067e \u0627\u0633\u06a9\u0648\u0627\u0634 \u06a9\u06d2 \u0627\u0646\u0636\u0645\u0627\u0645 \u0627\u0648\u0631 \u0632\u0628\u0631\u062f\u0633\u062a\u06cc \u062f\u06be\u06a9\u06d2 \u06a9\u06cc \u0648\u062c\u06c1 \u0633\u06d2 \u062d\u0627\u062f\u062b\u0627\u062a\u06cc \u0637\u0648\u0631 \u067e\u0631 \u062e\u062f\u0645\u0627\u062a \u06a9\u0648 \u0646\u06c1\u06cc\u06ba \u0686\u06be\u0648\u0691\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4<\/p>\n<\/li>\n<li>\n<p><strong>\u0631\u0627\u0632\u0648\u06ba \u06a9\u0648 \u0648\u0627\u0644\u0679 \u0645\u06cc\u06ba \u0645\u0646\u062a\u0642\u0644 \u06a9\u0631\u06cc\u06ba\u06d4<\/strong> (HashiCorp Vault\/AWS Secrets Manager\/doppler)\u06d4 \u062c\u06cc\u0646\u06a9\u0646\u0632 \u06a9\u0627 \u067e\u06cc \u0627\u06d2 \u0679\u06cc \u06a9\u0627\u0645 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u060c \u0644\u06cc\u06a9\u0646 \u0645\u062a\u0639\u062f\u062f \u0645\u0644\u0627\u0632\u0645\u062a\u0648\u06ba \u0645\u06cc\u06ba \u06af\u06be\u0648\u0645\u0646\u0627 \u0627\u06cc\u06a9 \u062a\u06a9\u0644\u06cc\u0641 \u06c1\u06d2\u06d4<\/p>\n<\/li>\n<li>\n<p><strong>\u062c\u06cc\u0646\u06a9\u0646\u0632 \u0645\u06cc\u06ba \u06a9\u0646\u0641\u06cc\u06af\u0631\u06cc\u0634\u0646-\u0627\u06cc\u0633-\u06a9\u0648\u0688 (JCasC) \u06a9\u0627 \u0627\u0633\u062a\u0639\u0645\u0627\u0644<\/strong> \u0644\u06c1\u0630\u0627 \u062c\u06cc\u0646\u06a9\u0646\u0632 \u06a9\u0627 \u067e\u0648\u0631\u0627 \u0633\u06cc\u0679 \u0627\u067e (\u0646\u0648\u06a9\u0631\u06cc\u0627\u06ba\u060c \u0627\u0633\u0646\u0627\u062f \u06a9\u06cc \u062a\u0639\u0631\u06cc\u0641\u06cc\u06ba\u060c \u067e\u0644\u06af \u0627\u0646) \u06af\u0679 \u0645\u06cc\u06ba \u0631\u06c1\u062a\u0627 \u06c1\u06d2\u06d4 \u0633\u0631\u0648\u0631 \u06a9\u0648 \u062f\u0648\u0628\u0627\u0631\u06c1 \u0628\u0646\u0627\u0646\u0627 \u067e\u06be\u0631 \u0627\u06cc\u06a9 \u0648\u0627\u062d\u062f \u06a9\u0645\u0627\u0646\u0688 \u0622\u067e\u0631\u06cc\u0634\u0646 \u06c1\u06d2\u06d4<\/p>\n<\/li>\n<\/ul>\n<h2 id=\"heading-closing-thoughts\">\u0627\u062e\u062a\u062a\u0627\u0645\u06cc \u062e\u06cc\u0627\u0644\u0627\u062a<\/h2>\n<p>\u067e\u0627\u0626\u067e \u0644\u0627\u0626\u0646 \u062e\u0648\u062f \u062a\u06cc\u0646 \u0645\u0631\u0627\u062d\u0644 \u067e\u0631 \u0645\u0634\u062a\u0645\u0644 \u06c1\u06d2: <strong>\u0686\u06cc\u06a9 \u0622\u0624\u0679 \u2192 \u062a\u0628\u062f\u06cc\u0644\u06cc\u0648\u06ba \u06a9\u0627 \u067e\u062a\u06c1 \u0644\u06af\u0627\u0626\u06cc\u06ba \u2192 \u062a\u0639\u06cc\u0646\u0627\u062a \u06a9\u0631\u06cc\u06ba\u06d4<\/strong> &#8211; \u0644\u06cc\u06a9\u0646 \u0633\u0628 \u0633\u06d2 \u0632\u06cc\u0627\u062f\u06c1 \u0627\u0635\u0644 \u067e\u06cc\u062f\u0627\u0648\u0627\u0631 \u06a9\u06cc \u062a\u0631\u062a\u06cc\u0628\u0627\u062a \u06c1\u06cc\u06ba <strong>\u0631\u0634\u062a\u06c1<\/strong>: \u0631\u06cc\u0648\u0631\u0633 \u067e\u0631\u0627\u06a9\u0633\u06cc\u060c \u0633\u0631\u0679\u06cc\u0641\u06a9\u06cc\u0679\u060c \u0628\u0627\u0626\u0646\u0688 \u0645\u0627\u0624\u0646\u0679\u060c \u0627\u0633\u0646\u0627\u062f\u060c \u0679\u0627\u0626\u0645 \u0632\u0648\u0646\u060c \u06a9\u06cc\u0634 \u0628\u0646\u0627\u0626\u06cc\u06ba\u06d4 \u0627\u0646 \u0645\u06cc\u06ba \u0633\u06d2 \u06a9\u0648\u0626\u06cc \u0628\u06be\u06cc \u063a\u06cc\u0631 \u0645\u0644\u06a9\u06cc \u0646\u06c1\u06cc\u06ba \u06c1\u06d2\u06d4 \u0648\u06c1 \u0645\u0644 \u06a9\u0631 \u0641\u06cc\u0635\u0644\u06c1 \u06a9\u0631\u062a\u06d2 \u06c1\u06cc\u06ba \u06a9\u06c1 \u0622\u06cc\u0627 \u062c\u0645\u0639\u06c1 \u06a9\u06cc \u062f\u0648\u067e\u06c1\u0631 \u06a9\u06cc \u062a\u0639\u06cc\u0646\u0627\u062a\u06cc \u062e\u0627\u0645\u0648\u0634\u06cc \u0633\u06d2 \u0633\u0628\u0632 \u06c1\u0648 \u062c\u0627\u0626\u06d2 \u06af\u06cc \u06cc\u0627 \u06c1\u0641\u062a\u06d2 \u06a9\u06d2 \u0622\u062e\u0631 \u0645\u06cc\u06ba \u06a9\u06be\u0627 \u062c\u0627\u0626\u06d2 \u06af\u06cc\u06d4<\/p>\n<p>\u0648\u0631\u06a9\u0646\u06af \u067e\u0627\u0626\u067e \u0644\u0627\u0626\u0646 \u062d\u0627\u0635\u0644 \u06a9\u0631\u0646\u06d2 \u06a9\u06d2 \u0644\u06cc\u06d2 \u0633\u06cc\u06a9\u0634\u0646 1-11 \u067e\u0631 \u0639\u0645\u0644 \u06a9\u0631\u06cc\u06ba\u06d4 \u06a9\u0627\u0645 \u062c\u0627\u0631\u06cc \u0631\u06a9\u06be\u0646\u06d2 \u06a9\u06d2 \u0644\u06cc\u06d2 \u0628\u0631\u0627\u06c1 \u06a9\u0631\u0645 \u0633\u06cc\u06a9\u0634\u0646 12 \u06a9\u0648 \u0628\u06a9 \u0645\u0627\u0631\u06a9 \u06a9\u0631\u06cc\u06ba\u06d4<\/p>\n<p>\u0645\u0628\u0627\u0631\u06a9 \u0634\u067e\u0646\u06af.<\/p>\n<\/p><\/div>\n","protected":false},"excerpt":{"rendered":"<p>\u06cc\u06c1 \u0679\u06cc\u0648\u0679\u0648\u0631\u06cc\u0644 \u0627\u06cc\u06a9 \u0648\u0627\u062d\u062f \u0644\u06cc\u0646\u06a9\u0633 \u0633\u0631\u0648\u0631 \u067e\u0631 \u062c\u06cc\u0646\u06a9\u0646\u0632\u060c \u0688\u0648\u06a9\u0631 \u06a9\u0645\u067e\u0648\u0632\u060c \u0627\u0648\u0631 \u0679\u0631\u06cc\u0641\u06a9 \u06a9\u0627 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u062a\u06d2 \u06c1\u0648\u0626\u06d2 \u067e\u06cc\u062f\u0627\u0648\u0627\u0631 \u06a9\u06d2 \u0644\u06cc\u06d2 \u062a\u06cc\u0627\u0631 CI\/CD \u067e\u0627\u0626\u067e \u0644\u0627\u0626\u0646 \u0628\u0646\u0627\u0646\u06d2 \u06a9\u06d2 \u0644\u06cc\u06d2 \u0627\u06cc\u06a9 \u0645\u06a9\u0645\u0644\u060c \u0639\u0645\u0644\u06cc \u0631\u06c1\u0646\u0645\u0627 \u06c1\u06d2\u06d4 \u062e\u0648\u062f\u06a9\u0627\u0631 \u062a\u062c\u062f\u06cc\u062f \u06a9\u0631\u0646\u06d2 \u0648\u0627\u0644\u06d2 HTTPS \u06a9\u0627 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u062a\u06d2 \u06c1\u0648\u0626\u06d2 \u0627\u067e\u0646\u06cc \u0645\u0631\u0636\u06cc \u06a9\u06d2 \u0688\u0648\u0645\u06cc\u0646 \u0645\u06cc\u06ba \u062e\u062f\u0645\u0627\u062a \u06a9\u0648 \u06a9\u0633 \u0637\u0631\u062d \u0638\u0627\u06c1\u0631 \u06a9\u0631\u0646\u0627 \u06c1\u06d2 \u0627\u0648\u0631 \u0627\u06cc\u06a9 \u0633\u0645\u0627\u0631\u0679 [&hellip;]<\/p>\n","protected":false},"author":7,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"site-sidebar-layout":"default","site-content-layout":"","ast-site-content-layout":"default","site-content-style":"default","site-sidebar-style":"default","ast-global-header-display":"","ast-banner-title-visibility":"","ast-main-header-display":"","ast-hfb-above-header-display":"","ast-hfb-below-header-display":"","ast-hfb-mobile-header-display":"","site-post-title":"","ast-breadcrumbs-content":"","ast-featured-img":"","footer-sml-layout":"","ast-disable-related-posts":"","theme-transparent-header-meta":"","adv-header-id-meta":"","stick-header-meta":"","header-above-stick-meta":"","header-main-stick-meta":"","header-below-stick-meta":"","astra-migrate-meta-layouts":"default","ast-page-background-enabled":"default","ast-page-background-meta":{"desktop":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"tablet":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"mobile":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""}},"ast-content-background-meta":{"desktop":{"background-color":"var(--ast-global-color-4)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"tablet":{"background-color":"var(--ast-global-color-4)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"mobile":{"background-color":"var(--ast-global-color-4)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""}},"footnotes":""},"categories":[1],"tags":[],"class_list":["post-22972","post","type-post","status-publish","format-standard","hentry","category-blog"],"_links":{"self":[{"href":"https:\/\/umang.pk\/ur\/wp-json\/wp\/v2\/posts\/22972","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/umang.pk\/ur\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/umang.pk\/ur\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/umang.pk\/ur\/wp-json\/wp\/v2\/users\/7"}],"replies":[{"embeddable":true,"href":"https:\/\/umang.pk\/ur\/wp-json\/wp\/v2\/comments?post=22972"}],"version-history":[{"count":0,"href":"https:\/\/umang.pk\/ur\/wp-json\/wp\/v2\/posts\/22972\/revisions"}],"wp:attachment":[{"href":"https:\/\/umang.pk\/ur\/wp-json\/wp\/v2\/media?parent=22972"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/umang.pk\/ur\/wp-json\/wp\/v2\/categories?post=22972"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/umang.pk\/ur\/wp-json\/wp\/v2\/tags?post=22972"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}