{"id":69351,"date":"2020-02-18T14:44:06","date_gmt":"2020-02-18T11:44:06","guid":{"rendered":"https:\/\/prohoster.info\/blog\/blog_prohoster\/sozdanie-ci-cd-czepochki-i-avtomatizacziya-raboty-s-docker"},"modified":"2020-03-03T16:15:00","modified_gmt":"2020-03-03T13:15:00","slug":"sozdanie-ci-cd-czepochki-i-avtomatizacziya-raboty-s-docker","status":"publish","type":"post","link":"https:\/\/prohoster.info\/sq\/blog\/administrirovanie\/sozdanie-ci-cd-czepochki-i-avtomatizacziya-raboty-s-docker","title":{"rendered":"Krijimi i nj\u00eb zinxhiri CI\/CD dhe automatizimi i pun\u00ebs me Docker","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p>Un\u00eb dozha faqet e mia t\u00eb para n\u00eb fund t\u00eb viteve '90. At\u00ebher\u00eb ishte shum\u00eb e thjesht\u00eb t'i b\u00ebnim ato funksionale. Kishim nj\u00eb server Apache n\u00eb ndonj\u00eb host t\u00eb zakonsh\u00ebm, ku mund t\u00eb lidhesha p\u00ebrmes FTP-s\u00eb, duke shkruar n\u00eb shiritin e shfletuesit di\u00e7ka si <code>ftp:\/\/ftp.example.com<\/code>. Pastaj duhej t\u00eb tregoheshin emri dhe fjal\u00ebkalimi p\u00ebr t\u00eb ngarkuar skedaret n\u00eb server. Ishin koh\u00eb t\u00eb tjera, gjith\u00e7ka ishte m\u00eb e thjesht\u00eb se tani.<\/p>\n<p><noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/ruvds\/blog\/488668\/\"><img decoding=\"async\" alt=\"Krijimi i nj\u00eb zinxhiri CI\/CD dhe automatizimi i pun\u00ebs me Docker\" src=\"\/wp-content\/uploads\/2020\/02\/0861cdd82770ef4695ffac7a09777c52.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/a><\/noindex><\/p>\n<p>Gjat\u00eb dy dekadave q\u00eb nga ajo koh\u00eb, gjith\u00e7ka ka ndryshuar duksh\u00ebm. Faqet jan\u00eb b\u00ebr\u00eb m\u00eb komplekse, duhet t\u00eb mblidhen para se t\u00eb dalin n\u00eb prodhim. Nj\u00eb server i vet\u00ebm \u00ebsht\u00eb b\u00ebr\u00eb nj\u00eb shum\u00ebllojshm\u00ebri serverash, q\u00eb punojn\u00eb n\u00ebn balancuesit e ngarkes\u00ebs, dhe p\u00ebrdorimi i sistemeve t\u00eb kontrollit t\u00eb versioneve \u00ebsht\u00eb b\u00ebr\u00eb di\u00e7ka e zakonshme.<\/p>\n<p>P\u00ebr projektin tim personal, un\u00eb kisha nj\u00eb konfigurim t\u00eb ve\u00e7ant\u00eb. Dhe e dija se m\u00eb nevojitej mund\u00ebsia p\u00ebr t\u00eb \u00e7elur faqen n\u00eb prodhim, duke kryer vet\u00ebm nj\u00eb veprim: sh\u00ebnimin e kodit n\u00eb nj\u00eb deg\u00eb. <code>master<\/code> n\u00eb GitHub. Un\u00eb gjithashtu dija se p\u00ebr t\u00eb siguruar funksionimin e aplikacionit tim t\u00eb vog\u00ebl n\u00eb web, nuk doja t\u00eb merresha me menaxhimin e nj\u00eb klasteri t\u00eb madh Kubernetes, ose t\u00eb p\u00ebrdorja teknologjin\u00eb Docker Swarm, ose t\u00eb mbaja nj\u00eb \u043f\u0430\u0440\u043a serverash me pod-e, agjent\u00eb dhe kompleksitete t\u00eb tjera. P\u00ebr t\u00eb arritur q\u00ebllimin e maksimalizimit t\u00eb thjesht\u00ebsis\u00eb s\u00eb pun\u00ebs, m\u00eb duhej t\u00eb njihem me CI\/CD.<\/p>\n<p>N\u00ebse keni nj\u00eb projekt t\u00eb vog\u00ebl (n\u00eb k\u00ebt\u00eb rast flasim p\u00ebr nj\u00eb projekt Node.js) dhe d\u00ebshironi t\u00eb m\u00ebsoni se si t\u00eb automatizoni shp\u00ebrndarjen e k\u00ebtij projekti, duke siguruar q\u00eb ajo q\u00eb ruhet n\u00eb repository t\u00eb p\u00ebrputhet sakt\u00ebsisht me at\u00eb q\u00eb punon n\u00eb prodhim, besoj se ky artikull mund t'ju interesoj\u00eb.<br \/>\n<noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/p>\n<h2>K\u00ebrkesat paraprake<\/h2>\n<p>\nPritet q\u00eb lexuesi i k\u00ebtij artikulli t\u00eb ket\u00eb njohuri bazike n\u00eb p\u00ebrdorimin e komandave n\u00eb terminal dhe n\u00eb shkruarjen e skripteve Bash. P\u00ebr m\u00eb tep\u00ebr, do t'i nevojiten llogari <noindex><a rel=\"nofollow\" href=\"https:\/\/travis-ci.org\/\">Travis CI<\/a><\/noindex> dhe <noindex><a rel=\"nofollow\" href=\"https:\/\/hub.docker.com\/\">Docker Hub<\/a><\/noindex>.<\/p>\n<h2>Q\u00ebllimet<\/h2>\n<p>\nNuk do t\u00eb them se ky artikull mund t\u00eb quhet pa marr\u00eb parasysh 'udh\u00ebzimi m\u00ebsimor'. Ky \u00ebsht\u00eb m\u00eb shum\u00eb nj\u00eb dokument ku tregoj at\u00eb q\u00eb kam m\u00ebsuar dhe p\u00ebrshkruaj procesin e testimit dhe implementimit t\u00eb kodit n\u00eb prodhim q\u00eb i b\u00ebhet n\u00eb nj\u00eb kalim t\u00eb automatizuar.<\/p>\n<p>K\u00ebtu \u00ebsht\u00eb si u formua procesi im i pun\u00ebs.<\/p>\n<p>P\u00ebr kodin q\u00eb d\u00ebrgohet n\u00eb \u00e7do deg\u00eb t\u00eb repositorit, p\u00ebrve\u00e7 <code>master<\/code>, b\u00ebhen k\u00ebto veprime:<\/p>\n<ul>\n<li>Niset nd\u00ebrtimi i projektit n\u00eb Travis CI.<\/li>\n<li>Kryhen t\u00eb gjitha testet modulare, integruese dhe end-to-end.<\/li>\n<\/ul>\n<p>\nVet\u00ebm p\u00ebr kodin q\u00eb arrin n\u00eb <code>master<\/code>, kryhet e siguiente:<\/p>\n<ul>\n<li>T\u00eb gjitha ato q\u00eb jan\u00eb th\u00ebn\u00eb m\u00eb sip\u00ebr, plus...<\/li>\n<li>Nd\u00ebrtohet imazhi Docker me kodin aktual, konfigurimet dhe ambientin.<\/li>\n<li>Postohet imazhi n\u00eb Docker Hub.<\/li>\n<li>Konektimi me serverin e prodhimit.<\/li>\n<li>Ngarkohet imazhi nga Docker Hub n\u00eb server.<\/li>\n<li>Ndalohet kontejneri aktual dhe nisett nj\u00eb i ri, bazuar n\u00eb imazhin e ri.<\/li>\n<\/ul>\n<p>\nN\u00ebse nuk dini asgj\u00eb p\u00ebr Docker, p\u00ebr imazhet dhe kontejner\u00ebt \u2014 mos u shqet\u00ebsoni. Un\u00eb do t'ju tregoj gjith\u00e7ka rreth k\u00ebsaj.<\/p>\n<h2>\u00c7far\u00eb \u00ebsht\u00eb CI\/CD?<\/h2>\n<p>\nAcroni CI\/CD q\u00ebndron p\u00ebr \"integrim t\u00eb vazhduesh\u00ebm\/zhvillim t\u00eb vazhduesh\u00ebm\".<\/p>\n<h3>\u258dIntegrimi i vazhduesh\u00ebm<\/h3>\n<p>\nIntegrimi i vazhduesh\u00ebm \u00ebsht\u00eb nj\u00eb proces ku zhvilluesit b\u00ebjn\u00eb komitete n\u00eb depo kryesore t\u00eb kodit burimor t\u00eb projektit (zakonisht n\u00eb nj\u00eb deg\u00eb <code>master<\/code>). Cil\u00ebsia e kodit sigurohet p\u00ebrmes testimit automatizuar.<\/p>\n<h3>\u258dZhvillimi i vazhduesh\u00ebm<\/h3>\n<p>\nZhvillimi i vazhduesh\u00ebm \u00ebsht\u00eb nj\u00eb shp\u00ebrndarje t\u00eb shpesht\u00eb automatizuar t\u00eb kodit n\u00eb prodhim. Pjesa e dyt\u00eb e akronimit CI\/CD ndonj\u00ebher\u00eb shpjegohet si \"d\u00ebrgimi i vazhduesh\u00ebm\". Kjo, n\u00eb p\u00ebrgjith\u00ebsi, \u00ebsht\u00eb e nj\u00ebjta gj\u00eb si \"zhvillimi i vazhduesh\u00ebm\", por \"d\u00ebrgimi i vazhduesh\u00ebm\" n\u00ebnkupton nevoj\u00ebn p\u00ebr konfirmimin manual t\u00eb ndryshimeve p\u00ebrpara se t\u00eb filloj\u00eb procesi i shp\u00ebrndarjes s\u00eb projektit.<\/p>\n<h2>Fillimi i pun\u00ebs<\/h2>\n<p>\nAplikacioni mbi t\u00eb cilin po e m\u00ebsoj k\u00ebt\u00eb \u00ebsht\u00eb <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/taniarascia\/takenote\">TakeNote<\/a><\/noindex>. Ky \u00ebsht\u00eb nj\u00eb projekt web-i mbi t\u00eb cilin po punoj, i destinuar p\u00ebr t\u00eb b\u00ebr\u00eb sh\u00ebnime. Fillimisht, p\u00ebrpiqesha t\u00eb b\u00ebja <noindex><a rel=\"nofollow\" href=\"https:\/\/jamstack.org\/\">JAMStack<\/a><\/noindex>-projekt, ose vet\u00ebm nj\u00eb aplikacion frontend pa server, p\u00ebr t\u00eb shfryt\u00ebzuar mund\u00ebsit\u00eb standarde p\u00ebr hostimin dhe dislokimin e projekteve q\u00eb ofron <noindex><a rel=\"nofollow\" href=\"https:\/\/www.netlify.com\/\">Netlify<\/a><\/noindex>. Me rritjen e kompleksitetit t\u00eb aplikacionit, m\u00eb nevojitej t\u00eb krijoja gjithashtu pjes\u00ebn e serverit, dhe kjo do t\u00eb thoshte se do t\u00eb duhej t\u00eb formuloja nj\u00eb strategji t\u00eb vet\u00ebn p\u00ebr integrimin e automatizuar dhe dislokimin automatizuar t\u00eb projektit.<\/p>\n<p>N\u00eb rastin tim, aplikacioni p\u00ebrb\u00ebhet nga nj\u00eb server Express, q\u00eb funksionon n\u00eb ambientin Node.js, q\u00eb sh\u00ebrben nj\u00eb aplikacion React me nj\u00eb faqe dhe mb\u00ebshtet nj\u00eb API t\u00eb mbrojtur serveri. Kjo arkitektur\u00eb ndjek nj\u00eb strategji q\u00eb mund t\u00eb gjendet n\u00eb <noindex><a rel=\"nofollow\" href=\"https:\/\/www.taniarascia.com\/full-stack-cookies-localstorage-react-express\/\">k\u00ebt\u00eb<\/a><\/noindex> udh\u00ebzues p\u00ebr autentifikimin fullstack.<\/p>\n<p>Un\u00eb konsultova me <noindex><a rel=\"nofollow\" href=\"http:\/\/qualitytesting.tech\/\">nj\u00eb tjet\u00ebr<\/a><\/noindex>, i cili \u00ebsht\u00eb ekspert n\u00eb automatizim, dhe e pyeta se \u00e7far\u00eb duhet t\u00eb b\u00ebja p\u00ebr ta b\u00ebr\u00eb gjith\u00e7ka t\u00eb funksionoj\u00eb ashtu si\u00e7 m\u00eb nevojitej. Ai m\u00eb dha nj\u00eb ide se si duhet t\u00eb dukej procesi i automatizuar i pun\u00ebs, i p\u00ebrshkruar n\u00eb seksionin \u2018Q\u00ebllimet\u2019 t\u00eb k\u00ebtij artikulli. Ajo q\u00eb vendosa p\u00ebrpara vetes si q\u00ebllime t\u00eb tilla, do t\u00eb thoshte se duhej t\u00eb kuptoja se si t\u00eb p\u00ebrdorja Docker.<\/p>\n<h2>Docker<\/h2>\n<p>\nDocker \u2014 \u00ebsht\u00eb nj\u00eb mjet q\u00eb, fal\u00eb teknologjis\u00eb s\u00eb kontejnerizimit, lejon shp\u00ebrndarjen e leht\u00eb t\u00eb aplikacioneve dhe gjithashtu mund\u00ebsin\u00eb e instalimit dhe funksionimit t\u00eb tyre n\u00eb t\u00eb nj\u00ebjtin mjedis, p\u00ebrve\u00e7 n\u00ebse vet\u00eb platforma Docker punon n\u00eb mjedise t\u00eb ndryshme. P\u00ebr t\u00eb filluar, m\u00eb nevojitej t\u00eb siguroja mjetet e komand\u00ebs (CLI) t\u00eb Docker. <noindex><a rel=\"nofollow\" href=\"https:\/\/docs.docker.com\/install\/\">Udh\u00ebzimi<\/a><\/noindex> p\u00ebr instalimin e Docker-it nuk mund t\u00eb quhet shum\u00eb i sakt\u00eb dhe i kuptuesh\u00ebm, por nga ai mund t\u00eb m\u00ebsohet se p\u00ebr t\u00eb b\u00ebr\u00eb hapin e par\u00eb t\u00eb instalimit, \u00ebsht\u00eb e nevojshme t\u00eb shkarkohet Docker Desktop (p\u00ebr Mac ose Windows).<\/p>\n<p>Docker Hub \u2014 \u00ebsht\u00eb ngjash\u00ebm si <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/\">GitHub<\/a><\/noindex> p\u00ebr repozitat git, ose regjistri <noindex><a rel=\"nofollow\" href=\"https:\/\/www.npmjs.com\/\">npm<\/a><\/noindex> p\u00ebr paketat JavaScript. Ky \u00ebsht\u00eb nj\u00eb repozit online p\u00ebr imazhet Docker. K\u00ebshtu lidhet Docker Desktop.<\/p>\n<p>Pra, p\u00ebr t\u00eb filluar pun\u00ebn me Docker, nevojiten dy gj\u00ebra:<\/p>\n<ul>\n<li>Instaloni <noindex><a rel=\"nofollow\" href=\"https:\/\/www.docker.com\/get-started\">Docker Desktop<\/a><\/noindex>.<\/li>\n<li>Regjistrohuni n\u00eb <noindex><a rel=\"nofollow\" href=\"https:\/\/hub.docker.com\/\">Docker Hub<\/a><\/noindex>.<\/li>\n<\/ul>\n<p>\nPas k\u00ebsaj, mund t\u00eb kontrolloni funksionimin e Docker CLI duke ekzekutuar komand\u00ebn e m\u00ebposhtme p\u00ebr t\u00eb kontrolluar versionin e Docker:<\/p>\n<pre><code class=\"plaintext\">docker -v<\/code><\/pre>\n<p>\nPastaj, hyni n\u00eb Docker Hub, duke futur, kur t'ju k\u00ebrkohet, emrin tuaj t\u00eb p\u00ebrdoruesit dhe fjal\u00ebkalimin:<\/p>\n<pre><code class=\"plaintext\">docker login<\/code><\/pre>\n<p>\nP\u00ebr t\u00eb p\u00ebrdorur Docker, duhet t\u00eb kuptoni konceptet e imazheve dhe kontejner\u00ebve.<\/p>\n<h3>\u258dImazhet<\/h3>\n<p>\nNj\u00eb imazh \u00ebsht\u00eb di\u00e7ka si nj\u00eb plan, q\u00eb p\u00ebrmban udh\u00ebzime p\u00ebr nd\u00ebrtimin e nj\u00eb kontenieri. Ai \u00ebsht\u00eb nj\u00eb snapshots i pandryshuesh\u00ebm i sistemit t\u00eb skedar\u00ebve dhe konfigurimeve t\u00eb aplikacionit. Zhvilluesit mund t\u00eb shk\u00ebmbejn\u00eb leht\u00ebsisht imazhe.<\/p>\n<pre><code class=\"plaintext\"># \u0412\u044b\u0432\u043e\u0434 \u0441\u0432\u0435\u0434\u0435\u043d\u0438\u0439 \u043e\u0431\u043e \u0432\u0441\u0435\u0445 \u043e\u0431\u0440\u0430\u0437\u0430\u0445\ndocker images<\/code><\/pre>\n<p>\nKy komand\u00eb do t\u00eb shfaq\u00eb nj\u00eb tabel\u00eb me titullin si m\u00eb posht\u00eb:<\/p>\n<pre><code class=\"plaintext\">REPOSITORY \u00a0 \u00a0 TAG     IMAGE ID \u00a0 \u00a0 CREATED     SIZE\n---<\/code><\/pre>\n<p>\nM\u00eb pas do t\u00eb shohim disa shembuj t\u00eb komandave n\u00eb k\u00ebt\u00eb format \u2014 s\u00eb pari shfaqet komanda me koment, e m\u00eb pas nj\u00eb shembull se \u00e7far\u00eb ajo mund t\u00eb jap\u00eb si rezultat.<\/p>\n<h3>\u258dKontenier\u00ebt<\/h3>\n<p>\nKonteneri \u00ebsht\u00eb nj\u00eb paket\u00eb ekzekutiv\u00eb q\u00eb p\u00ebrmban gjith\u00e7ka q\u00eb nevojitet p\u00ebr t\u00eb ekzekutuar aplikacionin. Aplikacioni n\u00eb k\u00ebt\u00eb qasje do t\u00eb funksionoj\u00eb gjithmon\u00eb nj\u00ebsoj, pavar\u00ebsisht nga infrastruktura: n\u00eb nj\u00eb mjedis t\u00eb izoluar dhe n\u00eb t\u00eb nj\u00ebjtin ambient. Kjo do t\u00eb thot\u00eb se n\u00eb mjedise t\u00eb ndryshme, ekzekutimet e imazhit t\u00eb nj\u00ebjt\u00eb jan\u00eb t\u00eb mundshme.<\/p>\n<pre><code class=\"plaintext\"># \u041f\u0435\u0440\u0435\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u0435 \u0432\u0441\u0435\u0445 \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u043e\u0432\ndocker ps -a\nCONTAINER ID \u00a0 \u00a0 IMAGE     COMMAND \u00a0 \u00a0 CREATED     STATUS     PORTS \u00a0 \u00a0 NAMES\n---<\/code><\/pre>\n<p><\/p>\n<h3>\u258dEtiketat<\/h3>\n<p>\nEtiketa \u00ebsht\u00eb nj\u00eb tregues p\u00ebr nj\u00eb version t\u00eb ve\u00e7ant\u00eb t\u00eb imazhit.<\/p>\n<h3>\u258dK\u00ebshilla e shkurt\u00ebr p\u00ebr komandat Docker<\/h3>\n<p>\nJa nj\u00eb p\u00ebrmbledhje e disa komandave t\u00eb p\u00ebrdorura shpesh n\u00eb Docker.<\/p>\n<p>Ekipa<\/p>\n<p>Konteksti<\/p>\n<p>Veprimi<\/p>\n<p><noindex><a rel=\"nofollow\" href=\"https:\/\/docs.docker.com\/engine\/reference\/commandline\/build\/\">docker build<\/a><\/noindex><\/p>\n<p>Imazhi<\/p>\n<p>Nd\u00ebrtimi i nj\u00eb imazhi nga Dockerfile<\/p>\n<p><noindex><a rel=\"nofollow\" href=\"https:\/\/docs.docker.com\/engine\/reference\/commandline\/tag\/\">docker tag<\/a><\/noindex><\/p>\n<p>Imazhi<\/p>\n<p>Etiketimi i imazhit<\/p>\n<p><noindex><a rel=\"nofollow\" href=\"https:\/\/docs.docker.com\/engine\/reference\/commandline\/images\/\">docker images<\/a><\/noindex><\/p>\n<p>Imazhi<\/p>\n<p>Shfaqja e list\u00ebs s\u00eb imazheve<\/p>\n<p><noindex><a rel=\"nofollow\" href=\"https:\/\/docs.docker.com\/engine\/reference\/run\/\">docker run<\/a><\/noindex><\/p>\n<p>Kontejner<\/p>\n<p>Ekzekutimi i kontenierit n\u00eb baz\u00eb t\u00eb imazhit<\/p>\n<p><noindex><a rel=\"nofollow\" href=\"https:\/\/docs.docker.com\/engine\/reference\/commandline\/push\/\">docker push<\/a><\/noindex><\/p>\n<p>Imazhi<\/p>\n<p>D\u00ebrgimi i imazhit n\u00eb regjistrin<\/p>\n<p><noindex><a rel=\"nofollow\" href=\"http:\/\/about:blank\">docker pull<\/a><\/noindex><\/p>\n<p>Imazhi<\/p>\n<p>Ngarkimi i imazhit nga regjistri<\/p>\n<p><noindex><a rel=\"nofollow\" href=\"https:\/\/docs.docker.com\/engine\/reference\/commandline\/ps\/\">docker ps<\/a><\/noindex><\/p>\n<p>Kontejner<\/p>\n<p>Shfaqja e list\u00ebs s\u00eb kontejner\u00ebve<\/p>\n<p><noindex><a rel=\"nofollow\" href=\"https:\/\/docs.docker.com\/engine\/reference\/commandline\/system_prune\/\">docker system prune<\/a><\/noindex><\/p>\n<p>Imazh\/Kontejner<\/p>\n<p>Fshirja e kontejner\u00ebve dhe imazheve t\u00eb pavaruara<\/p>\n<h3>\u258dSkedari Dockerfile<\/h3>\n<p>\nE di si t\u00eb nis nj\u00eb aplikacion p\u00ebr prodhim lokal. Kam nj\u00eb konfigurim Webpack, i cili \u00ebsht\u00eb menduar p\u00ebr nd\u00ebrtimin e nj\u00eb aplikacioni t\u00eb gatsh\u00ebm React. M\u00eb pas, kam nj\u00eb komand\u00eb q\u00eb nis nj\u00eb server, i bazuar n\u00eb Node.js, n\u00eb portin <code>5000<\/code>. Kjo duket k\u00ebshtu:<\/p>\n<pre><code class=\"plaintext\">npm i \u00a0 \u00a0 \u00a0 \u00a0 # instalimi i var\u00ebsive\nnpm run build # nd\u00ebrtimi i aplikacionit React\nnpm run start # nisja e serverit Node<\/code><\/pre>\n<p>\nDuhet t\u00eb theksoj se nuk kam nj\u00eb aplikacion shembuj p\u00ebr k\u00ebt\u00eb material. Por k\u00ebtu, p\u00ebr eksperimentet, do t\u00eb p\u00ebrshtatet ndonj\u00eb aplikacion t\u00eb thjesht\u00eb Node.<\/p>\n<p>P\u00ebr t\u00eb p\u00ebrdorur kontejnerin, do t'ju nevojitet t\u00eb jepni udh\u00ebzime p\u00ebr Docker. Kjo b\u00ebhet p\u00ebrmes nj\u00eb skedari, i quajtur <code>Dockerfile<\/code>, q\u00eb ndodhet n\u00eb direktorin\u00eb rr\u00ebnj\u00ebsore t\u00eb projektit. Ky skedar, fillimisht, duket mjaft i pazakont\u00eb.<\/p>\n<p>Por ajo q\u00eb p\u00ebrmban, thjesht p\u00ebrshkruan, me komanda t\u00eb ve\u00e7anta, di\u00e7ka t\u00eb ngjashme me konfigurimin e mjedisit t\u00eb pun\u00ebs. Ja disa nga k\u00ebto komanda:<\/p>\n<ul>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/docs.docker.com\/engine\/reference\/builder\/#from\">FROM<\/a><\/noindex> \u2014 Kjo komand\u00eb fillon skedarin. Ajo specifikon imazhin baz\u00eb, mbi t\u00eb cilin nd\u00ebrtohet kontejneri.<\/li>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/docs.docker.com\/engine\/reference\/builder\/#copy\">COPY<\/a><\/noindex> \u2014 Kopjimi i skedar\u00ebve nga burimi lokal n\u00eb kontejner.<\/li>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/docs.docker.com\/engine\/reference\/builder\/#workdir\">WORKDIR<\/a><\/noindex> \u2014 P\u00ebrcaktimi i direktoris\u00eb punuese p\u00ebr komandat q\u00eb vijn\u00eb.<\/li>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/docs.docker.com\/engine\/reference\/builder\/#run\">RUN<\/a><\/noindex> \u2014 Ekzekutimi i komandave.<\/li>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/docs.docker.com\/engine\/reference\/builder\/#expose\">EXPOSE<\/a><\/noindex> \u2014 Konfigurimi i portit.<\/li>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/docs.docker.com\/engine\/reference\/builder\/#entrypoint\">ENTRYPOINT<\/a><\/noindex> \u2014 P\u00ebrcaktimi i komand\u00ebs q\u00eb do t\u00eb ekzekutohet.<\/li>\n<\/ul>\n<p>\n<code>Dockerfile<\/code> mund t\u00eb duket di\u00e7ka si kjo:<\/p>\n<pre><code class=\"plaintext\"># \u0417\u0430\u0433\u0440\u0443\u0437\u0438\u0442\u044c \u0431\u0430\u0437\u043e\u0432\u044b\u0439 \u043e\u0431\u0440\u0430\u0437\nFROM node:12-alpine\n\n# \u0421\u043a\u043e\u043f\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0444\u0430\u0439\u043b\u044b \u0438\u0437 \u0442\u0435\u043a\u0443\u0449\u0435\u0439 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0438 \u0432 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u044e app\/\nCOPY . app\/\n\n# \u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c app\/ \u0432 \u0440\u043e\u043b\u0438 \u0440\u0430\u0431\u043e\u0447\u0435\u0439 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0438\nWORKDIR app\/\n\n# \u0423\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 (\u043a\u043e\u043c\u0430\u043d\u0434\u0430 npm ci \u043f\u043e\u0445\u043e\u0436\u0430 npm i, \u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0434\u043b\u044f \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0445 \u0441\u0431\u043e\u0440\u043e\u043a)\nRUN npm ci --only-production\n\n# \u0421\u043e\u0431\u0440\u0430\u0442\u044c \u043a\u043b\u0438\u0435\u043d\u0442\u0441\u043a\u043e\u0435 React-\u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0434\u043b\u044f \u043f\u0440\u043e\u0434\u0430\u043a\u0448\u043d\u0430\nRUN npm run build\n\n# \u041f\u0440\u043e\u0441\u043b\u0443\u0448\u0438\u0432\u0430\u0442\u044c \u0443\u043a\u0430\u0437\u0430\u043d\u043d\u044b\u0439 \u043f\u043e\u0440\u0442\nEXPOSE 5000\n\n# \u0417\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c Node-\u0441\u0435\u0440\u0432\u0435\u0440\nENTRYPOINT npm run start<\/code><\/pre>\n<p>\nN\u00eb var\u00ebsi t\u00eb imazhit baz\u00eb t\u00eb zgjedhur, mund t\u00eb jet\u00eb e nevojshme t\u00eb instaloni var\u00ebsi shtes\u00eb. \u00cbsht\u00eb e v\u00ebrtet\u00eb q\u00eb disa imazhe baz\u00eb (si\u00e7 \u00ebsht\u00eb Node Alpine Linux) jan\u00eb krijuar p\u00ebr ta b\u00ebr\u00eb sa m\u00eb t\u00eb vog\u00ebl t\u00eb mundshme. Si rezultat, disa programe q\u00eb mund t\u00eb prisni t\u00eb mungojn\u00eb.<\/p>\n<h3>\u258dNd\u00ebrtimi, etiketimi dhe ekzekutimi i kontejnerit<\/h3>\n<p>\nNd\u00ebrtimi dhe ekzekutimi lokal i kontejnerit \u2014 \u00ebsht\u00eb, pasi kemi <code>Dockerfile<\/code>, detyra jan\u00eb mjaft t\u00eb thjeshta. Para se ta d\u00ebrgoni imazhin n\u00eb Docker Hub, duhet ta testoni lokalsh\u00ebm.<\/p>\n<h3>\u258dNd\u00ebrtimi<\/h3>\n<p>\nS\u00eb pari, duhet t\u00eb nd\u00ebrtoni <noindex><a rel=\"nofollow\" href=\"https:\/\/docs.docker.com\/engine\/reference\/commandline\/build\/\">imazhi<\/a><\/noindex>, duke specifikuar emrin, dhe, e cila nuk \u00ebsht\u00eb e domosdoshme, etiket\u00ebn (n\u00ebse nuk caktohet etiketa, sistemi automatikisht do t\u00eb caktoj\u00eb nj\u00eb etiket\u00eb p\u00ebr imazhin) <code>latest<\/code>).<\/p>\n<pre><code class=\"plaintext\"># \u0421\u0431\u043e\u0440\u043a\u0430 \u043e\u0431\u0440\u0430\u0437\u0430\ndocker build -t &lt;image&gt;:&lt;tag&gt; .<\/code><\/pre>\n<p>\nPas ekzekutimit t\u00eb k\u00ebsaj komande, mund t\u00eb shikoni se si Docker kryen nd\u00ebrtimin e imazhit.<\/p>\n<pre><code class=\"plaintext\">D\u00ebrgimi i kontekstit t\u00eb nd\u00ebrtimit n\u00eb daemon-in Docker \u00a0 2.88MB\nHapi 1\/9 : NGA node:12-alpine\n\u00a0---&gt; ...ekzekutimi i fazave t\u00eb nd\u00ebrtimit...\nNd\u00ebrtimi me sukses 123456789123\nEtiketimi me sukses &lt;imazhi&gt;:&lt;etiketa&gt;<\/code><\/pre>\n<p>\nKrijimi mund t\u00eb marr\u00eb disa minuta - gjith\u00e7ka varet nga sa shum\u00eb var\u00ebsi keni. Pasi t\u00eb p\u00ebrfundoj\u00eb krijimi, mund t\u00eb ekzekutoni komand\u00ebn <code>docker images<\/code> dhe t\u00eb shihni p\u00ebrshkrimin e imazhit tuaj t\u00eb ri.<\/p>\n<pre><code class=\"plaintext\">REPOSITORY          TAG               IMAGE ID             CREATED              SIZE\n             latest            123456789123        Para nj\u00eb minute   x.xxGB<\/code><\/pre>\n<p><\/p>\n<h3>\u258d Nisja<\/h3>\n<p>\nImazhi \u00ebsht\u00eb krijuar. Dhe kjo do t\u00eb thot\u00eb se mbi t\u00eb mund t\u00eb nisni nj\u00eb kontejner. Duke qen\u00eb se un\u00eb dua q\u00eb t\u00eb kem mund\u00ebsin\u00eb t\u00eb aksesoj aplikacionin, i cili punon n\u00eb kontejner, n\u00eb adres\u00ebn <code>localhost:5000<\/code>, un\u00eb, n\u00eb an\u00ebn e majt\u00eb t\u00eb \u00e7iftit <code>5000:5000<\/code> n\u00eb komand\u00ebn tjet\u00ebr kam vendosur <code>5000<\/code>. N\u00eb an\u00ebn e djatht\u00eb \u00ebsht\u00eb porta e kontejnerit.<\/p>\n<pre><code class=\"plaintext\"># \u0417\u0430\u043f\u0443\u0441\u043a \u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u043f\u043e\u0440\u0442\u0430 5000 \u0438 \u043f\u043e\u0440\u0442\u0430 \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u0430 5000\ndocker run -p 5000:5000 &lt;image&gt;:&lt;tag&gt;<\/code><\/pre>\n<p>\nTani, kur kontejneri \u00ebsht\u00eb krijuar dhe nisur, mund t\u00eb p\u00ebrdorni komand\u00ebn <code>docker ps<\/code> p\u00ebr t\u00eb par\u00eb informacionet rreth k\u00ebtij kontejneri (apo mund t\u00eb p\u00ebrdorni komand\u00ebn <code>docker ps -a<\/code>, e cila shfaq informacionet p\u00ebr t\u00eb gjith\u00eb kontejner\u00ebt, jo vet\u00ebm p\u00ebr ata q\u00eb jan\u00eb aktiv\u00eb).<\/p>\n<pre><code class=\"plaintext\">ID KONTENERI        IMAZHI               KOMANDA                   KRIJUAR              STATUS                     PORTET                     EMRAT\n987654321234                     \"\/bin\/sh -c 'npm run\u2026\"   6 sekonda m\u00eb par\u00eb        Aktiv 6 sekonda             0.0.0.0:5000-&gt;5000\/tcp   stoic_darwin<\/code><\/pre>\n<p>\nN\u00ebse tani kaloni n\u00eb adres\u00ebn <code>localhost:5000<\/code> \u2014 mund t\u00eb shihni faqen e nj\u00eb aplikacioni n\u00eb funksionim, e cila duket nj\u00ebsoj si faqe aplikacioni q\u00eb funksionon n\u00eb ambientin e prodhimit.<\/p>\n<h3>\u258dQ\u00ebllimi i etiket\u00ebs dhe publikimi<\/h3>\n<p>\nP\u00ebr ta p\u00ebrdorur nj\u00ebrin nga imazhet e krijuara n\u00eb serverin e prodhimit, ne duhet t\u00eb kemi mund\u00ebsin\u00eb ta ngarkojm\u00eb k\u00ebt\u00eb imazh n\u00eb Docker Hub. Kjo do t\u00eb thot\u00eb se s\u00eb pari duhet t\u00eb krijojm\u00eb nj\u00eb depo n\u00eb Docker Hub p\u00ebr projektin. Pas k\u00ebsaj, do t\u00eb kemi nj\u00eb vend ku mund ta d\u00ebrgojm\u00eb imazh. Imazhi duhet t\u00eb rinovohet n\u00eb m\u00ebnyr\u00eb q\u00eb emri i tij t\u00eb filloj\u00eb me emrin ton\u00eb t\u00eb p\u00ebrdoruesit n\u00eb Docker Hub. M\u00eb pas duhet t\u00eb vij\u00eb emri i depozit\u00ebs. N\u00eb fund t\u00eb emrit mund t\u00eb ket\u00eb nj\u00eb etiket\u00eb t\u00eb \u00e7far\u00ebdo dore. M\u00eb posht\u00eb \u00ebsht\u00eb nj\u00eb shembull i em\u00ebrimit t\u00eb imazheve sipas k\u00ebsaj skeme.<\/p>\n<p>Tani mund t\u00eb nd\u00ebrtojm\u00eb imazhin duke i dh\u00ebn\u00eb nj\u00eb em\u00ebr t\u00eb ri dhe t\u00eb ekzekutojm\u00eb komand\u00ebn <code>docker push<\/code> p\u00ebr ta d\u00ebrguar n\u00eb depozit\u00ebn e Docker Hub.<\/p>\n<pre><code class=\"plaintext\">docker build -t \/ : .\ndocker tag \/ : \/ :latest\ndocker push \/ :\n\n# N\u00eb praktik\u00eb, kjo mund t\u00eb duket, p\u00ebr shembull, k\u00ebshtu:\ndocker build -t user\/app:v1.0.0 .\ndocker tag user\/app:v1.0.0 user\/app:latest\ndocker push user\/app:v1.0.0<\/code><\/pre>\n<p>\nN\u00ebse gjith\u00e7ka shkon si\u00e7 duhet, imazhi do t\u00eb jet\u00eb i disponuesh\u00ebm n\u00eb Docker Hub dhe do t\u00eb jet\u00eb leht\u00ebsisht i shkarkuesh\u00ebm n\u00eb server ose i transferuesh\u00ebm tek zhvillues t\u00eb tjer\u00eb.<\/p>\n<h2>Hapat e ardhsh\u00ebm<\/h2>\n<p>\nN\u00eb k\u00ebt\u00eb moment, ne kemi konfirmuar q\u00eb aplikacioni, si nj\u00eb kontejner Docker, funksionon lokal. Ne kemi ngarkuar kontejnerin n\u00eb Docker Hub. T\u00eb gjitha k\u00ebto do t\u00eb thot\u00eb se ne kemi avancuar shum\u00eb n\u00eb arritjen e q\u00ebllimit. Tani duhet t\u00eb zgjidhim dy \u00e7\u00ebshtje t\u00eb tjera:<\/p>\n<ul>\n<li>Konfigurimi i mjetit CI p\u00ebr testimin dhe vendosjen e kodit.<\/li>\n<li>Konfigurimi i serverit t\u00eb prodhimit n\u00eb m\u00ebnyr\u00eb q\u00eb ai t\u00eb mund t\u00eb ngarkoj\u00eb dhe ekzekutoj\u00eb kodin ton\u00eb.<\/li>\n<\/ul>\n<p>\nN\u00eb rastin ton\u00eb, si zgjidhje CI\/CD p\u00ebrdoret <noindex><a rel=\"nofollow\" href=\"https:\/\/travis-ci.org\/\">Travis CI<\/a><\/noindex>. Si server \u2014 <noindex><a rel=\"nofollow\" href=\"https:\/\/www.digitalocean.com\/\">DigitalOcean<\/a><\/noindex>.<\/p>\n<p>Duhet t\u00eb theksohet se k\u00ebtu mund t\u00eb p\u00ebrdoret edhe nj\u00eb kombinim tjet\u00ebr sh\u00ebrbimesh. P\u00ebr shembull, n\u00eb vend t\u00eb Travis CI mund t\u00eb p\u00ebrdorim CircleCI ose Github Actions. Dhe n\u00eb vend t\u00eb DigitalOcean \u2014 AWS ose Linode.<\/p>\n<p>Ne kemi vendosur t\u00eb punojm\u00eb me Travis CI, dhe n\u00eb k\u00ebt\u00eb sh\u00ebrbim kam krijuar tashm\u00eb disa konfigurime. Prandaj tani do t\u00eb tregoj shkurtimisht se si ta p\u00ebrgatisim p\u00ebr pun\u00eb.<\/p>\n<h2>Travis CI<\/h2>\n<p>\nTravis CI \u2014 nj\u00eb mjet p\u00ebr testimin dhe deploy-in e kodit. Nuk do t\u00eb doja t\u00eb hyj n\u00eb detaje t\u00eb konfigurimit t\u00eb Travis CI, pasi \u00e7do projekt \u00ebsht\u00eb unik dhe kjo nuk do t\u00eb sjell\u00eb shum\u00eb p\u00ebrfitim. Por do t\u00eb flas p\u00ebr t\u00eb gjitha bazat q\u00eb do t'ju ndihmojn\u00eb t\u00eb filloni n\u00eb rast se vendosni t\u00eb p\u00ebrdorni Travis CI. \u00c7far\u00ebdo q\u00eb t\u00eb zgjidhni \u2014 Travis CI, CircleCI, Jenkins, ose di\u00e7ka tjet\u00ebr, metoda e konfigurimit do t\u00eb jen\u00eb t\u00eb ngjashme.<\/p>\n<p>P\u00ebr t\u00eb filluar me Travis CI, shkoni te <noindex><a rel=\"nofollow\" href=\"https:\/\/travis-ci.org\/\">faqen e projektit<\/a><\/noindex> dhe krijoni nj\u00eb llogari. M\u00eb pas, integroni Travis CI me llogarin\u00eb tuaj n\u00eb GitHub. N\u00eb procesin e konfigurimit, do t'ju duhet t\u00eb tregoni repo q\u00eb d\u00ebshironi t\u00eb automatizoni dhe t\u00eb aktivizoni aksesin n\u00eb t\u00eb. (Un\u00eb p\u00ebrdor GitHub, por jam e sigurt q\u00eb Travis CI mund t\u00eb integrohet edhe me BitBucket, edhe me GitLab, dhe sh\u00ebrbime t\u00eb tjera t\u00eb ngjashme).<\/p>\n<p>\u00c7do her\u00eb q\u00eb Travis CI fillon pun\u00ebn, aktivizohet nj\u00eb server q\u00eb ekzekuton komandat e caktuara n\u00eb skedarin e konfigurimit, duke p\u00ebrfshir\u00eb deploy-in e deg\u00ebve p\u00ebrkat\u00ebse t\u00eb repo-s.<\/p>\n<h3>\u258dCikli i jet\u00ebs s\u00eb detyr\u00ebs<\/h3>\n<p>\nSkedari i konfigurimit t\u00eb Travis CI, i quajtur <code>.travis.yml<\/code> dhe ruan n\u00eb direktorin\u00eb kryesore t\u00eb projektit, mb\u00ebshtet konceptin e ngjarjeve <noindex><a rel=\"nofollow\" href=\"https:\/\/docs.travis-ci.com\/user\/job-lifecycle\/\">t\u00eb ciklit t\u00eb jet\u00ebs<\/a><\/noindex> t\u00eb detyrave. K\u00ebto jan\u00eb ngjarjet, t\u00eb renditura n\u00eb rendin n\u00eb t\u00eb cilin ndodhin:<\/p>\n<ul>\n<li><code>apt addons<\/code><\/li>\n<li><code>komponentet e cache<\/code><\/li>\n<li><code>before_install<\/code><\/li>\n<li><code>install<\/code><\/li>\n<li><code>before_script<\/code><\/li>\n<li><code>script<\/code><\/li>\n<li><code>before_cache<\/code><\/li>\n<li><code>after_success ose after_failure<\/code><\/li>\n<li><code>before_deploy<\/code><\/li>\n<li><code>deploy<\/code><\/li>\n<li><code>after_deploy<\/code><\/li>\n<li><code>after_script<\/code><\/li>\n<\/ul>\n<p><\/p>\n<h3>\u258dTestimi<\/h3>\n<p>\nN\u00eb skedarin e konfigurimit do t\u00eb konfiguroj serverin lokal Travis CI. Si gjuh\u00eb kam zgjedhur versionin Node 12 dhe i kam b\u00ebr\u00eb t\u00eb ditur sistemit q\u00eb t\u00eb instalohet var\u00ebsit\u00eb e nevojshme p\u00ebr p\u00ebrdorimin e Docker.<\/p>\n<p>Gjith\u00e7ka q\u00eb \u00ebsht\u00eb listuar n\u00eb <code>.travis.yml<\/code>, do t\u00eb ekzekutohet kur t\u00eb kryhen t\u00eb gjitha pull-request-et n\u00eb t\u00eb gjitha deg\u00ebt e repositorit, p\u00ebrve\u00e7 n\u00ebse ndryshe \u00ebsht\u00eb specifikuar. Kjo \u00ebsht\u00eb nj\u00eb ve\u00e7ori e dobishme, pasi do t\u00eb thot\u00eb q\u00eb mund t\u00eb testojm\u00eb t\u00eb gjith\u00eb kodin q\u00eb hyn n\u00eb repositor. Kjo lejon t\u00eb dim\u00eb n\u00ebse kodi \u00ebsht\u00eb i gatsh\u00ebm p\u00ebr t\u00eb u shkruar n\u00eb deg\u00ebn <code>master<\/code>, dhe nuk do ta prish\u00eb procesin e nd\u00ebrtimit t\u00eb projektit. N\u00eb k\u00ebt\u00eb konfigurim global, un\u00eb e b\u00ebj gjith\u00e7ka lokal, aktive serverin e zhvilluesit Webpack n\u00eb sfond (kjo \u00ebsht\u00eb nj\u00eb ve\u00e7ori e procesit tim t\u00eb pun\u00ebs) dhe ekzekutoj testet.<\/p>\n<p>N\u00ebse d\u00ebshironi q\u00eb n\u00eb repositorin tuaj t\u00eb shfaqen simbole me informacion p\u00ebr mbulimin e kodit nga testet, <noindex><a rel=\"nofollow\" href=\"https:\/\/www.taniarascia.com\/display-build-status-and-test-coverage\/\">k\u00ebtu<\/a><\/noindex> mund t\u00eb gjeni nj\u00eb udh\u00ebzues t\u00eb shkurt\u00ebr p\u00ebr p\u00ebrdorimin e Jest, Travis CI dhe Coveralls p\u00ebr mbledhjen dhe paraqitjen e k\u00ebtyre t\u00eb dh\u00ebnave.<\/p>\n<p>Ja p\u00ebrmbajtja e skedarit <code>.travis.yml<\/code>:<\/p>\n<pre><code class=\"plaintext\"># \u0423\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c \u044f\u0437\u044b\u043a\nlanguage: node_js\n\n# \u0423\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c \u0432\u0435\u0440\u0441\u0438\u044e Node.js\nnode_js:\n\u00a0\u00a0- '12'\n\nservices:\n\u00a0\u00a0# \u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043a\u043e\u043c\u0430\u043d\u0434\u043d\u0443\u044e \u0441\u0442\u0440\u043e\u043a\u0443 Docker\n\u00a0\u00a0- docker\n\ninstall:\n\u00a0\u00a0# \u0423\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u0434\u043b\u044f \u0442\u0435\u0441\u0442\u043e\u0432\n\u00a0\u00a0- npm ci\n\nbefore_script:\n\u00a0\u00a0# \u0417\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c \u0441\u0435\u0440\u0432\u0435\u0440 \u0438 \u043a\u043b\u0438\u0435\u043d\u0442 \u0434\u043b\u044f \u0442\u0435\u0441\u0442\u043e\u0432\n\u00a0\u00a0- npm run dev &amp;\n\nscript:\n\u00a0\u00a0# \u0417\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c \u0442\u0435\u0441\u0442\u044b\n\u00a0\u00a0- npm run test<\/code><\/pre>\n<p>\nK\u00ebtu p\u00ebrfundojn\u00eb ato veprime q\u00eb kryhen p\u00ebr t\u00eb gjitha deg\u00ebt e depozit\u00ebs dhe p\u00ebr k\u00ebrkesat p\u00ebr bashkim.<\/p>\n<h3>\u258dZhvillimi<\/h3>\n<p>\nDuke u bazuar n\u00eb supozimin se t\u00eb gjitha testet automatike p\u00ebrfunduan me sukses, ne mund t\u00eb publikojm\u00eb kodin n\u00eb serverin e prodhimit. T\u00eb gjitha k\u00ebto p\u00ebrb\u00ebjn\u00eb nga kodi n\u00eb deg\u00ebn <code>master<\/code>, ne u japim sistemit udh\u00ebzime p\u00ebrkat\u00ebse n\u00eb cil\u00ebsimet e zhvillimit. Para se t\u00eb provoni t\u00eb p\u00ebrdorni n\u00eb projektin tuaj kodin q\u00eb do t\u00eb shqyrtojm\u00eb m\u00eb pas, do t\u00eb doja t'ju paralajm\u00ebroja se duhet t\u00eb keni nj\u00eb skenar t\u00eb v\u00ebrtet\u00eb q\u00eb thirret p\u00ebr publikimin.<\/p>\n<pre><code class=\"plaintext\">deploy:\n  # Nd\u00ebrto kontejnerin Docker dhe d\u00ebrgoje n\u00eb Docker Hub\n  provider: script\n  script: bash deploy.sh\n  on:\n    branch: master<\/code><\/pre>\n<p>\nSkenari i publikimit zgjidh dy detyra:<\/p>\n<ul>\n<li>Nd\u00ebrtesa, etiketimi dhe d\u00ebrgimi i imazhit n\u00eb Docker Hub me mjete CI (n\u00eb rastin ton\u00eb, \u00ebsht\u00eb Travis CI).<\/li>\n<li>Ngarkimi i imazhit n\u00eb server, ndalimi i kontejnerit t\u00eb vjet\u00ebr dhe nisja e t\u00eb riut (n\u00eb rastin ton\u00eb, serveri funksionon n\u00eb platform\u00ebn DigitalOcean).<\/li>\n<\/ul>\n<p>\nS\u00eb pari, duhet t\u00eb konfigurojm\u00eb nj\u00eb proces automatik p\u00ebr nd\u00ebrtimin, etiketimin dhe d\u00ebrgimin e imazhit n\u00eb Docker Hub. E gjith\u00eb kjo \u00ebsht\u00eb shum\u00eb e ngjashme me at\u00eb q\u00eb kemi b\u00ebr\u00eb tashm\u00eb manualisht, p\u00ebrve\u00e7 se k\u00ebtu na nevojitet nj\u00eb strategji p\u00ebr caktimin e etiketave unike p\u00ebr imazhet dhe automatizimi i hyrjes n\u00eb sistem. Kam pasur v\u00ebshtir\u00ebsi me disa detaje t\u00eb skriptit t\u00eb implementimit, si strategjia e etiketimit, hyrja n\u00eb sistem, kodimi i \u00e7el\u00ebsave SSH dhe vendosja e lidhjes SSH. Por, p\u00ebr fat t\u00eb mir\u00eb, i dashuri im \u00ebsht\u00eb shum\u00eb i mir\u00eb me bash, ashtu si me shum\u00eb gj\u00ebra t\u00eb tjera. Ai m\u00eb ndihmoi t\u00eb shkruaj k\u00ebt\u00eb skript.<\/p>\n<p>Pra, pjesa e par\u00eb e skriptit \u00ebsht\u00eb d\u00ebrgimi i imazhit n\u00eb Docker Hub. Ta b\u00ebsh k\u00ebt\u00eb \u00ebsht\u00eb mjaft e thjesht\u00eb. Skema e etiketimit q\u00eb kam p\u00ebrdorur p\u00ebrfshin kombinimin e hash-it git dhe etiket\u00ebs git, n\u00ebse ekziston. Kjo siguron krijimin e nj\u00eb etikete unike dhe leht\u00ebson identifikimin e nd\u00ebrtimit mbi t\u00eb cilin \u00ebsht\u00eb bazuar. <code>DOCKER_USERNAME<\/code> dhe <code>DOCKER_PASSWORD<\/code> \u2014 jan\u00eb variabla t\u00eb personalizuar t\u00eb ambientit q\u00eb mund t\u00eb caktosh p\u00ebrmes nd\u00ebrfaqes Travis CI. Travis CI do t\u00eb p\u00ebrpunoj\u00eb automatikisht t\u00eb dh\u00ebnat sekrete n\u00eb m\u00ebnyr\u00eb q\u00eb ato t\u00eb mos bien n\u00eb duar t\u00eb gabshme.<\/p>\n<p>Ja pjesa e par\u00eb e skriptit <code>deploy.sh<\/code>.<\/p>\n<pre><code class=\"plaintext\">#!\/bin\/sh\nset -e # \u041e\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c \u0441\u043a\u0440\u0438\u043f\u0442 \u043f\u0440\u0438 \u043d\u0430\u043b\u0438\u0447\u0438\u0438 \u043e\u0448\u0438\u0431\u043e\u043a\n\nIMAGE=&quot;&lt;username&gt;\/&lt;repository&gt;&quot; \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 # \u041e\u0431\u0440\u0430\u0437 Docker\nGIT_VERSION=$(git describe --always --abbrev --tags --long) # Git-\u0445\u044d\u0448 \u0438 \u0442\u0435\u0433\u0438\n\n# \u0421\u0431\u043e\u0440\u043a\u0430 \u0438 \u0442\u0435\u0433\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u043e\u0431\u0440\u0430\u0437\u0430\ndocker build -t ${IMAGE}:${GIT_VERSION} .\ndocker tag ${IMAGE}:${GIT_VERSION} ${IMAGE}:latest\n\n# \u0412\u0445\u043e\u0434 \u0432 Docker Hub \u0438 \u0432\u044b\u0433\u0440\u0443\u0437\u043a\u0430 \u043e\u0431\u0440\u0430\u0437\u0430\necho &quot;${DOCKER_PASSWORD}&quot; | docker login -u &quot;${DOCKER_USERNAME}&quot; --password-stdin\ndocker push ${IMAGE}:${GIT_VERSION}<\/code><\/pre>\n<p>\nAjo, se si do t\u00eb duket pjesa e dyt\u00eb e skriptit, varet plot\u00ebsisht nga hosti q\u00eb po p\u00ebrdorni dhe m\u00ebnyra se si \u00ebsht\u00eb organizuar lidhja me t\u00eb. N\u00eb rastin tim, pasi po p\u00ebrdor Digital Ocean, p\u00ebr lidhjen me serverin p\u00ebrdoren komandat <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/digitalocean\/doctl\">doctl<\/a><\/noindex>. Nd\u00ebrsa kur punoni me AWS, do t\u00eb p\u00ebrdoret utilita <code>aws<\/code>, e k\u00ebshtu me radh\u00eb.<\/p>\n<p>T\u00eb konfiguroni pun\u00ebn e serverit nuk ishte shum\u00eb e komplikuar. N\u00eb k\u00ebt\u00eb m\u00ebnyr\u00eb, un\u00eb konfigurova nj\u00eb droplet t\u00eb bazuar n\u00eb imazhin baz\u00eb. Duhet t\u00eb theksoj se sistemi q\u00eb kam zgjedhur k\u00ebrkon nj\u00eb instalim manual t\u00eb Docker nj\u00eb her\u00eb dhe nj\u00eb nisje manuale t\u00eb Docker nj\u00eb her\u00eb. P\u00ebr instalimin e Docker, un\u00eb p\u00ebrdorova Ubuntu 18.04, k\u00ebshtu q\u00eb ju, n\u00ebse gjithashtu p\u00ebrdorni Ubuntu, p\u00ebr t\u00eb b\u00ebr\u00eb t\u00eb nj\u00ebjt\u00ebn gj\u00eb, mund t\u00eb ndiqni <noindex><a rel=\"nofollow\" href=\"https:\/\/phoenixnap.com\/kb\/how-to-install-docker-on-ubuntu-18-04\">k\u00ebtu<\/a><\/noindex> udh\u00ebzimin e thjesht\u00eb.<\/p>\n<p>Nuk po flas k\u00ebtu p\u00ebr komandat e konkretizuar p\u00ebr sh\u00ebrbimin, pasi ky aspekt mund t\u00eb ndryshoj\u00eb ndjesh\u00ebm n\u00eb raste t\u00eb ndryshme. Un\u00eb do t\u00eb jap vet\u00ebm nj\u00eb plan t\u00eb p\u00ebrgjithsh\u00ebm t\u00eb veprimeve q\u00eb do t\u00eb kryhen pas lidhjes p\u00ebrmes SSH me serverin ku do t\u00eb zhvillohet projekti:<\/p>\n<ul>\n<li>Duhet t\u00eb gjeni kontejnerin q\u00eb aktualisht po ekzekutohet dhe ta ndaloni at\u00eb.<\/li>\n<li>M\u00eb pas duhet, n\u00eb sfond, t\u00eb nisni nj\u00eb kontejner t\u00eb ri.<\/li>\n<li>Do t\u00eb nevojitet t\u00eb vendosni portin lokal t\u00eb serverit n\u00eb vler\u00ebn <code>80<\/code> \u2014 kjo do t'ju lejoj\u00eb t\u00eb hyni n\u00eb faqen e internetit n\u00eb adres\u00ebn si <code>example.com<\/code>, pa specifikuar portin, dhe jo duke p\u00ebrdorur adres\u00ebn si <code>example.com:5000<\/code>.<\/li>\n<li>Dhe, p\u00ebrfundimisht, duhet t\u00eb hiqni t\u00eb gjitha kontejner\u00ebt dhe imazhet e vjetra.<\/li>\n<\/ul>\n<p>\nK\u00ebtu \u00ebsht\u00eb vazhdimi i skriptit.<\/p>\n<pre><code class=\"plaintext\"># \u041d\u0430\u0439\u0442\u0438 ID \u0440\u0430\u0431\u043e\u0442\u0430\u044e\u0449\u0435\u0433\u043e \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u0430\nCONTAINER_ID=$(docker ps | grep takenote | cut -d&quot; &quot; -f1)\n\n# \u041e\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c \u0441\u0442\u0430\u0440\u044b\u0439 \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440, \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c \u043d\u043e\u0432\u044b\u0439, \u043e\u0447\u0438\u0441\u0442\u0438\u0442\u044c \u0441\u0438\u0441\u0442\u0435\u043c\u0443\ndocker stop ${CONTAINER_ID}\ndocker run --restart unless-stopped -d -p 80:5000 ${IMAGE}:${GIT_VERSION}\ndocker system prune -a -f<\/code><\/pre>\n<p><\/p>\n<h2>Disa gj\u00ebra q\u00eb duhet t\u00eb keni parasysh<\/h2>\n<p>\nMund t\u00eb ndodh\u00eb q\u00eb kur t\u00eb lidhni me serverin p\u00ebrmes SSH nga Travis CI, do t\u00eb shihni nj\u00eb paralajm\u00ebrim q\u00eb nuk do t\u00eb lejoj\u00eb vazhdimin e instalimit, pasi sistemi do t\u00eb pres\u00eb reagimin e p\u00ebrdoruesit.<\/p>\n<pre><code class=\"plaintext\">Autenticiteti i hostit ' ()' nuk mund t\u00eb vendoset.\nNyja e \u00e7el\u00ebsit RSA \u00ebsht\u00eb .\nA jeni t\u00eb sigurt q\u00eb doni t\u00eb vazhdoni t\u00eb lidheni (po\/jo)?<\/code><\/pre>\n<p>\nKam m\u00ebsuar se \u00e7el\u00ebsi i vargut mund t\u00eb kodifikohet n\u00eb base64 p\u00ebr t\u00eb ruajtur at\u00eb n\u00eb nj\u00eb format ku \u00ebsht\u00eb e leht\u00eb dhe e sigurt t\u00eb punoni me t\u00eb. Gjat\u00eb faz\u00ebs s\u00eb instalimit, mund t\u00eb dekodoni \u00e7el\u00ebsin publik dhe ta regjistroni at\u00eb n\u00eb skedarin <code>known_hosts<\/code> p\u00ebr t'u liruar nga gabimi i p\u00ebrshkruar m\u00eb sip\u00ebr.<\/p>\n<pre><code class=\"plaintext\">echo  | base64 # shfaq<\/code><\/pre>\n<p>\nN\u00eb praktik\u00eb, kjo komand\u00eb mund t\u00eb duket k\u00ebshtu:<\/p>\n<pre><code class=\"plaintext\">echo \"123.45.67.89 ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAklOUpkDHrfHY17SbrmTIpNLTGK9Tjom\/BWDSU\nGPl+nafzlHDTYW7hdI4yZ5ew18JH4JW9jbhUFrviQzM7xlELEVf4h9lFX5QVkbPppSwg0cda3\nPbv7kOdJ\/MTyBlWXFCR+HAo3FXRitBqxiX1nKhXpHAZsMciLq8V6RjsNAQwdsdMFvSlVK\/7XA\nt3FaoJoAsncM1Q9x5+3V0Ww68\/eIFmb1zuUFljQJKprrX88XypNDvjYNby6vw\/Pb0rwert\/En\nmZ+AW4OZPnTPI89ZPmVMLuayrD2cE86Z\/il8b+gw3r3+1nKatmIkjn2so1d01QraTlMqVSsbx\nNrRFi9wrf+M7Q== you@example.com\" | base64<\/code><\/pre>\n<p>\nJa k\u00ebtu \u00ebsht\u00eb si duket ajo q\u00eb ajo jep \u2014 nj\u00eb varg n\u00eb kodimin base64:<\/p>\n<pre><code class=\"plaintext\">MTIzLjQ1LjY3Ljg5IHNzaC1yc2EgQUFBQUIzTnphQzF5YzJFQUFBQUJJd0FBQVFFQWtsT1Vwa0RIcmZIWTE3U2JybVRJcE5MVEdLOVRqb20vQldEU1UKR1BsK25hZnpsSERUWVc3aGRJNHpaNWV3MThKSDRKVzlqYmhVRnJ2aVF6TTd4bEVMRVZmNGg5bEZYNVFWa2JQcHBTd2cwY2RhMwpQYnY3a09kSi9NVHlCbFdYRkNSK0hBbzNGWFJpdEJxeGlYMW5LaFhwSEFac01jaUxxOFY2UmpzTkFRd2RzZE1GdlNsVksvN1hBCnQzRmFvSm9Bc25jTTFROXg1KzNWMFd3NjgvZUlGbWIxenVVRmxqUUpLcHJyWDg4WHlwTkR2allOYnk2dncvUGIwcndlcnQvRW4KbVorQVc0T1pQblRQSTg5WlBtVk1MdWF5ckQyY0U4NlovaWw4YitndzNyMysxbkthdG1Ja2puMnNvMWQwMVFyYVRsTXFWU3NieApOclJGaTl3cmYrTTdRPT0geW91QGV4YW1wbGUuY29tCg==<\/code><\/pre>\n<p>\nJa \u00ebsht\u00eb komanda, p\u00ebr t\u00eb cil\u00ebn u fol m\u00eb sip\u00ebr<\/p>\n<pre><code class=\"plaintext\">install:\n  - echo  | base64 -d &gt;&gt; $HOME\/.ssh\/known_hosts<\/code><\/pre>\n<p>\nT\u00eb nj\u00ebjtin qasje mund t\u00eb p\u00ebrdorim me \u00e7el\u00ebsin privat kur krijojm\u00eb nj\u00eb lidhje, sepse ju, p\u00ebr t\u00eb hyr\u00eb n\u00eb server, mund t\u00eb nevojitet \u00e7el\u00ebsi privat. Kur punoni me \u00e7el\u00ebsin, duhet ta siguroni ruajtjen e tij n\u00eb nj\u00eb variab\u00ebl mjedisi n\u00eb Travis CI dhe t\u00eb siguroheni q\u00eb ai t\u00eb mos printohet askund.<\/p>\n<p>Nj\u00eb gj\u00eb tjet\u00ebr q\u00eb meriton v\u00ebmendje \u00ebsht\u00eb se mund t'ju nevojitet t\u00eb ndihmoni gjith\u00eb skriptin e implementimit, i paraqitur si nj\u00eb rresht, p\u00ebr shembull \u2014 p\u00ebrmes <code>doctl<\/code>. Kjo mund t\u00eb k\u00ebrkoj\u00eb disa p\u00ebrpjekje shtes\u00eb.<\/p>\n<pre><code class=\"plaintext\">doctl compute ssh  --ssh-command \"t\u00eb gjitha komandat do t\u00eb jen\u00eb k\u00ebtu &amp;&amp; k\u00ebtu\"<\/code><\/pre>\n<p><\/p>\n<h2>TLS\/SSL dhe balancimi i ngarkes\u00ebs<\/h2>\n<p>\nPasi b\u00ebra t\u00eb gjitha ato q\u00eb u diskutuan m\u00eb sip\u00ebr, problemi i fundit q\u00eb u paraqit ishte se serveri nuk kishte SSL. Duke qen\u00eb se p\u00ebrdor nj\u00eb server Node.js, p\u00ebr t\u00eb b\u00ebr\u00eb <noindex><a rel=\"nofollow\" href=\"https:\/\/www.digitalocean.com\/community\/tutorials\/how-to-secure-a-containerized-node-js-application-with-nginx-let-s-encrypt-and-docker-compose\">t\u00eb funksionoj\u00eb<\/a><\/noindex> proksi i kthyer Nginx dhe Let\u2019s Encrypt, duhet t\u00eb punosh shum\u00eb.<\/p>\n<p>Nuk m\u00eb p\u00eblqente aspak t\u00eb b\u00ebja t\u00eb gjitha k\u00ebto konfigurime SSL manualisht, k\u00ebshtu q\u00eb thjesht krijova nj\u00eb balancues ngarkese dhe regjistrova informacionin e tij n\u00eb DNS. N\u00eb rastin e DigitalOcean, p\u00ebr shembull, krijimi i nj\u00eb certificati self-signed q\u00eb auto-update n\u00eb balancuesin e ngarkes\u00ebs \u00ebsht\u00eb nj\u00eb procedur\u00eb e thjesht\u00eb, pa pages\u00eb dhe e shpejt\u00eb. Ky qasje ka gjithashtu nj\u00eb avantazh t\u00eb shtuar, q\u00eb \u00ebsht\u00eb se n\u00ebse \u00ebsht\u00eb e nevojshme, leht\u00ebson shum\u00eb konfigurimin e SSL n\u00eb shum\u00eb servera q\u00eb punojn\u00eb pas balancuesit t\u00eb ngarkes\u00ebs. Kjo i lejon server\u00ebt vet\u00eb t\u00eb mos \u201cmendojn\u00eb\u201d fare p\u00ebr SSL, por megjithat\u00eb t\u00eb p\u00ebrdorin, si zakonisht, portin <code>80<\/code>. Pra, konfigurimi i SSL n\u00eb balancuesin e ngarkes\u00ebs \u00ebsht\u00eb shum\u00eb m\u00eb i leht\u00eb dhe m\u00eb komod se metodat alternativ\u00eb t\u00eb konfigurimit t\u00eb SSL.<\/p>\n<p>Tani mund t\u00eb mbyllni t\u00eb gjitha portet n\u00eb server q\u00eb pranojn\u00eb lidhje okolike \u2014 p\u00ebrve\u00e7 portit <code>80<\/code>, i cili p\u00ebrdoret p\u00ebr komunikim me balancuesin e ngarkes\u00ebs, dhe portit <code>22<\/code> p\u00ebr SSH. Si rezultat, p\u00ebrpjekja p\u00ebr t'u drejtuar drejtp\u00ebrs\u00ebdrejti n\u00eb server p\u00ebrmes porteve t\u00eb tjera, p\u00ebrve\u00e7 k\u00ebtyre dy, do t\u00eb d\u00ebshtoj\u00eb.<\/p>\n<h2>P\u00ebrfundimet<\/h2>\n<p>\nPas pas, pas kam b\u00ebra gjith\u00e7ka q\u00eb p\u00ebrmenda n\u00eb k\u00ebt\u00eb material, nuk kisha m\u00eb frik\u00eb nga platforma Docker as nga konceptet e automatizuara t\u00eb rrjedhave CI\/CD. Arrita t\u00eb konfigurita nj\u00eb rrjedh\u00eb t\u00eb integrimit t\u00eb vazhduesh\u00ebm, gjat\u00eb t\u00eb cil\u00ebs realizohet testimi i kodit para se t\u00eb kaloj\u00eb n\u00eb prodhim dhe shp\u00ebrndarja automatike e kodit n\u00eb server. T\u00eb gjitha k\u00ebto jan\u00eb ende relativisht t\u00eb reja p\u00ebr mua, dhe jam e sigurt q\u00eb ka m\u00ebnyra p\u00ebr t\u00eb p\u00ebrmir\u00ebsuar procesin tim t\u00eb pun\u00ebs automatizuar dhe ta b\u00ebj at\u00eb m\u00eb efikas. Prandaj, n\u00ebse keni ide p\u00ebr k\u00ebt\u00eb, m\u00eb <noindex><a rel=\"nofollow\" href=\"mailto:hello@taniarascia.com\">informoni.<\/a><\/noindex> Shpresoj q\u00eb ky artikull ju ka ndihmuar n\u00eb pun\u00ebn tuaj. Dua t\u00eb besoj se, duke e lexuar at\u00eb, ju m\u00ebsuat t\u00eb pakt\u00ebn aq sa m\u00ebsova un\u00eb, nd\u00ebrsa u merresha me gjith\u00e7ka q\u00eb kam p\u00ebrmendur n\u00eb t\u00eb.<\/p>\n<p><b>P.S.<\/b> N\u00eb sh\u00ebrbimin ton\u00eb <noindex><a rel=\"nofollow\" href=\"https:\/\/ruvds.com\/ru-rub\/marketplace#order\">merkatplace-in ton\u00eb<\/a><\/noindex> ka nj\u00eb imazh <noindex><a rel=\"nofollow\" href=\"https:\/\/ruvds.com\/ru-rub\/marketplace\/docker#advantages\">Docker<\/a><\/noindex>, i cili instalohet me nj\u00eb klik. Mund t\u00eb kontrolloni pun\u00ebn e kontejner\u00ebve n\u00eb <noindex><a rel=\"nofollow\" href=\"https:\/\/ruvds.com\/\">VPS<\/a><\/noindex>. T\u00eb gjith\u00eb klient\u00ebt e rinj ofrohen falas 3 dit\u00eb p\u00ebr testim.<\/p>\n<p><b>T\u00eb nderuar lexues!<\/b> A p\u00ebrdorni teknologjit\u00eb CI\/CD n\u00eb projektet tuaja?<\/p>\n<p><noindex><a rel=\"nofollow\" href=\"https:\/\/ruvds.com\/ru-rub\/#order\"><img decoding=\"async\" alt=\"Krijimi i nj\u00eb zinxhiri CI\/CD dhe automatizimi i pun\u00ebs me Docker\" src=\"\/wp-content\/uploads\/2020\/02\/3fbfa90ea56a3d9b6b89ba945eb94570.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/a><\/noindex><br \/>\n<br \/>Burimi: <a content=\"nofollow\" rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/ruvds\/blog\/488668\/\">habr.com<\/a> <\/p>","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"excerpt":{"rendered":"<p>\u042f \u043d\u0430\u043f\u0438\u0441\u0430\u043b\u0430 \u043c\u043e\u0438 \u043f\u0435\u0440\u0432\u044b\u0435 \u0441\u0430\u0439\u0442\u044b \u0432 \u043a\u043e\u043d\u0446\u0435 90-\u0445. \u0422\u043e\u0433\u0434\u0430 \u043f\u0440\u0438\u0432\u043e\u0434\u0438\u0442\u044c \u0438\u0445 \u0432 \u0440\u0430\u0431\u043e\u0447\u0435\u0435 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u0431\u044b\u043b\u043e \u043e\u0447\u0435\u043d\u044c \u043f\u0440\u043e\u0441\u0442\u043e. \u0411\u044b\u043b Apache-\u0441\u0435\u0440\u0432\u0435\u0440 \u043d\u0430 \u043a\u0430\u043a\u043e\u043c-\u043d\u0438\u0431\u0443\u0434\u044c \u043e\u0431\u0449\u0435\u043c \u0445\u043e\u0441\u0442\u0438\u043d\u0433\u0435, \u043d\u0430 \u044d\u0442\u043e\u0442 \u0441\u0435\u0440\u0432\u0435\u0440 \u043c\u043e\u0436\u043d\u043e \u0431\u044b\u043b\u043e \u0432\u043e\u0439\u0442\u0438 \u043f\u043e FTP, \u043d\u0430\u043f\u0438\u0441\u0430\u0432 \u0432 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u043d\u043e\u0439 \u0441\u0442\u0440\u043e\u043a\u0435 \u043d\u0435\u0447\u0442\u043e \u0432\u0440\u043e\u0434\u0435 ftp:\/\/ftp.example.com. \u041f\u043e\u0442\u043e\u043c \u043d\u0430\u0434\u043e \u0431\u044b\u043b\u043e \u0432\u0432\u0435\u0441\u0442\u0438 \u0438\u043c\u044f \u0438 \u043f\u0430\u0440\u043e\u043b\u044c \u0438 \u0432\u044b\u0433\u0440\u0443\u0437\u0438\u0442\u044c \u0444\u0430\u0439\u043b\u044b \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440. \u0414\u0440\u0443\u0433\u0438\u0435 \u0431\u044b\u043b\u0438 \u0432\u0440\u0435\u043c\u0435\u043d\u0430, \u0432\u0441\u0451 \u0442\u043e\u0433\u0434\u0430 [&hellip;]<\/p>\n","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"author":1,"featured_media":69352,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[688],"tags":[],"class_list":["post-69351","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-administrirovanie"],"aioseo_notices":[],"aioseo_head":"\n\t\t<!-- All in One SEO 5.0.0.1 - aioseo.com -->\n\t<meta name=\"description\" content=\"\u042f \u043d\u0430\u043f\u0438\u0441\u0430\u043b\u0430 \u043c\u043e\u0438 \u043f\u0435\u0440\u0432\u044b\u0435 \u0441\u0430\u0439\u0442\u044b \u0432 \u043a\u043e\u043d\u0446\u0435 90-\u0445. \u0422\u043e\u0433\u0434\u0430 \u043f\u0440\u0438\u0432\u043e\u0434\u0438\u0442\u044c \u0438\u0445 \u0432 \u0440\u0430\u0431\u043e\u0447\u0435\u0435 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u0431\u044b\u043b\u043e \u043e\u0447\u0435\u043d\u044c \u043f\u0440\u043e\u0441\u0442\u043e.\" \/>\n\t<meta name=\"robots\" content=\"max-image-preview:large\" \/>\n\t<meta name=\"author\" content=\"Yuri Gagarin\"\/>\n\t<link rel=\"canonical\" href=\"https:\/\/prohoster.info\/sq\/blog\/administrirovanie\/sozdanie-ci-cd-czepochki-i-avtomatizacziya-raboty-s-docker\" \/>\n\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.0.1\" \/>\n\t\t<meta property=\"og:locale\" content=\"sq_AL\" \/>\n\t\t<meta property=\"og:site_name\" content=\"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b\" \/>\n\t\t<meta property=\"og:type\" content=\"article\" \/>\n\t\t<meta property=\"og:title\" content=\"\ud83e\udd47\u0421\u043e\u0437\u0434\u0430\u043d\u0438\u0435 CI\/CD-\u0446\u0435\u043f\u043e\u0447\u043a\u0438 \u0438 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0437\u0430\u0446\u0438\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 Docker | ProHoster\" \/>\n\t\t<meta property=\"og:description\" content=\"\u042f \u043d\u0430\u043f\u0438\u0441\u0430\u043b\u0430 \u043c\u043e\u0438 \u043f\u0435\u0440\u0432\u044b\u0435 \u0441\u0430\u0439\u0442\u044b \u0432 \u043a\u043e\u043d\u0446\u0435 90-\u0445. \u0422\u043e\u0433\u0434\u0430 \u043f\u0440\u0438\u0432\u043e\u0434\u0438\u0442\u044c \u0438\u0445 \u0432 \u0440\u0430\u0431\u043e\u0447\u0435\u0435 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u0431\u044b\u043b\u043e \u043e\u0447\u0435\u043d\u044c \u043f\u0440\u043e\u0441\u0442\u043e.\" \/>\n\t\t<meta property=\"og:url\" content=\"https:\/\/prohoster.info\/sq\/blog\/administrirovanie\/sozdanie-ci-cd-czepochki-i-avtomatizacziya-raboty-s-docker\" \/>\n\t\t<meta property=\"og:image\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:secure_url\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:width\" content=\"350\" \/>\n\t\t<meta property=\"og:image:height\" content=\"350\" \/>\n\t\t<meta property=\"article:published_time\" content=\"2020-02-18T11:44:06+00:00\" \/>\n\t\t<meta property=\"article:modified_time\" content=\"2020-03-03T13:15:00+00:00\" \/>\n\t\t<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<meta property=\"article:author\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<!-- All in One SEO -->\n\n","aioseo_head_json":{"title":"\ud83e\udd47Krijimi i nj\u00eb zinxhiri CI\/CD dhe automatizimi i pun\u00ebs me Docker | ProHoster","description":"Un\u00eb kam shkruar faqet e mia t\u00eb para n\u00eb fund t\u00eb viteve '90. At\u00ebher\u00eb, kishte shum\u00eb leht\u00ebsi p\u00ebr t'i b\u00ebr\u00eb ato funksionale.","canonical_url":"https:\/\/prohoster.info\/sq\/blog\/administrirovanie\/sozdanie-ci-cd-czepochki-i-avtomatizacziya-raboty-s-docker","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"sq_AL","og:site_name":"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b","og:type":"article","og:title":"\ud83e\udd47\u0421\u043e\u0437\u0434\u0430\u043d\u0438\u0435 CI\/CD-\u0446\u0435\u043f\u043e\u0447\u043a\u0438 \u0438 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0437\u0430\u0446\u0438\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 Docker | ProHoster","og:description":"\u042f \u043d\u0430\u043f\u0438\u0441\u0430\u043b\u0430 \u043c\u043e\u0438 \u043f\u0435\u0440\u0432\u044b\u0435 \u0441\u0430\u0439\u0442\u044b \u0432 \u043a\u043e\u043d\u0446\u0435 90-\u0445. \u0422\u043e\u0433\u0434\u0430 \u043f\u0440\u0438\u0432\u043e\u0434\u0438\u0442\u044c \u0438\u0445 \u0432 \u0440\u0430\u0431\u043e\u0447\u0435\u0435 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u0431\u044b\u043b\u043e \u043e\u0447\u0435\u043d\u044c \u043f\u0440\u043e\u0441\u0442\u043e.","og:url":"https:\/\/prohoster.info\/sq\/blog\/administrirovanie\/sozdanie-ci-cd-czepochki-i-avtomatizacziya-raboty-s-docker","og:image":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:secure_url":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:width":350,"og:image:height":350,"article:published_time":"2020-02-18T11:44:06+00:00","article:modified_time":"2020-03-03T13:15:00+00:00","article:publisher":"https:\/\/www.facebook.com\/prohoster","article:author":"https:\/\/www.facebook.com\/prohoster"},"aioseo_meta_data":{"post_id":"69351","title":null,"description":null,"keywords":null,"keyphrases":{"focus":[],"additional":[]},"primary_term":null,"canonical_url":null,"og_title":null,"og_description":null,"og_object_type":"default","og_image_type":"default","og_image_url":null,"og_image_width":null,"og_image_height":null,"og_image_custom_url":null,"og_image_custom_fields":null,"og_video":null,"og_custom_url":null,"og_article_section":null,"og_article_tags":null,"twitter_use_og":false,"twitter_card":"default","twitter_image_type":"default","twitter_image_url":null,"twitter_image_custom_url":null,"twitter_image_custom_fields":null,"twitter_title":null,"twitter_description":null,"schema":{"blockGraphs":[],"customGraphs":[],"default":{"data":{"Article":[],"Course":[],"Dataset":[],"FAQPage":[],"Movie":[],"Person":[],"Product":[],"ProductReview":[],"Car":[],"Recipe":[],"Service":[],"SoftwareApplication":[],"WebPage":[]},"graphName":"","isEnabled":true},"graphs":[]},"schema_type":null,"schema_type_options":null,"pillar_content":false,"robots_default":true,"robots_noindex":false,"robots_noarchive":false,"robots_nosnippet":false,"robots_nofollow":false,"robots_noimageindex":false,"robots_noodp":false,"robots_notranslate":false,"robots_max_snippet":null,"robots_max_videopreview":null,"robots_max_imagepreview":"large","priority":null,"frequency":null,"local_seo":null,"seo_analyzer_scan_date":null,"breadcrumb_settings":null,"limit_modified_date":false,"reviewed_by":null,"ai":null,"created":"2021-02-28 19:24:45","updated":"2026-08-11 12:50:24","focus_keyword":null,"additional_keywords":null,"truseo_locale":null},"gt_translate_keys":[{"key":"link","format":"url"}],"_links":{"self":[{"href":"https:\/\/prohoster.info\/sq\/wp-json\/wp\/v2\/posts\/69351","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/sq\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/sq\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/sq\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/sq\/wp-json\/wp\/v2\/comments?post=69351"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/sq\/wp-json\/wp\/v2\/posts\/69351\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/prohoster.info\/sq\/wp-json\/wp\/v2\/media\/69352"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/sq\/wp-json\/wp\/v2\/media?parent=69351"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/sq\/wp-json\/wp\/v2\/categories?post=69351"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/sq\/wp-json\/wp\/v2\/tags?post=69351"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}