{"id":77,"date":"2025-07-04T00:45:56","date_gmt":"2025-07-03T21:45:56","guid":{"rendered":"https:\/\/ali-aslan.com\/?p=77"},"modified":"2025-07-04T00:32:10","modified_gmt":"2025-07-03T21:32:10","slug":"koddan-konteynere-github-actions-docker-hub-ve-docker-compose-ile-ci-cd","status":"publish","type":"post","link":"https:\/\/ali-aslan.com\/?p=77","title":{"rendered":"Koddan Konteynere: GitHub Actions, Docker Hub ve Docker Compose ile CI\/CD"},"content":{"rendered":"\n<p>Bir \u00f6nceki g\u00f6nderimde CI\/CD kavramlar\u0131n\u0131 detayl\u0131ca konu\u015fmu\u015ftuk bu yaz\u0131mda, ba\u015ftan sonra bir Github Actions olu\u015fturaca\u011f\u0131z.<\/p>\n\n\n<h4 class=\"wp-block-heading\" id=\"on-hazirliklar\"><strong>&Ouml;n Haz&#305;rl&#305;klar<\/strong><\/h4>\n\n\n\n<p>\u00d6ncelikle, GitHub Actions\u2019\u0131n CI\/CD pipeline\u2019\u0131n\u0131z\u0131 otomatik olarak alg\u0131lay\u0131p \u00e7al\u0131\u015ft\u0131rabilmesi i\u00e7in proje k\u00f6k dizininizde \u015fu yolu olu\u015fturmal\u0131s\u0131n\u0131z:<\/p>\n\n\n<pre class=\"wp-block-code plover-prism prism-github-dark-theme language-cs\"><code>.github\/\n&#9492;&#9472;&#9472; workflows\/\n    &#9492;&#9472;&#9472; deploy.yml<\/code><\/pre>\n\n\n<ul class=\"wp-block-list\" style=\"\">\n<li>\n<strong>Dosya Konumu olarak<\/strong> <code>.github\/workflows\/<\/code> klas&ouml;r&uuml; alt&#305;nda<\/li>\n\n\n\n<li>\n<strong>Dosya ad&#305;:<\/strong> istedi&#287;iniz ba&#351;ka bir isim de verebilirsiniz uzant&#305;s&#305; <code>.yml<\/code> olmak &#351;art&#305;yla<br><br>bu sayede github action&#8217;u tan&#305;yarak otamatik olarak tetikleyicisine g&ouml;re &ccedil;al&#305;&#351;acakt&#305;r.<\/li>\n<\/ul>\n\n\n\n<p>Settings > Secret and variables b\u00f6l\u00fcm\u00fcnden sunucumuzun ve docker hub bilgilerimizi secret olarak tan\u0131mlat\u0131p giriyoruz.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"888\" src=\"http:\/\/ali-aslan.com\/wp-content\/uploads\/2025\/07\/ClientSecret-1024x888.png\" alt=\"\" class=\"wp-image-80\" srcset=\"https:\/\/ali-aslan.com\/wp-content\/uploads\/2025\/07\/ClientSecret-1024x888.png 1024w, https:\/\/ali-aslan.com\/wp-content\/uploads\/2025\/07\/ClientSecret-300x260.png 300w, https:\/\/ali-aslan.com\/wp-content\/uploads\/2025\/07\/ClientSecret-768x666.png 768w, https:\/\/ali-aslan.com\/wp-content\/uploads\/2025\/07\/ClientSecret.png 1047w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n<ol id=\"block-300cf41c-f463-4ab3-b66e-a6f3e32ab3a5\" class=\"wp-block-list\">\n<li>\n<strong>Tetkik (Trigger) Ayarlar&#305;<\/strong><ul class=\"wp-block-list\" style=\"\">\n<li>\n<code><strong>main<\/strong><\/code> dal&#305;na yap&#305;lan <code><strong>push<\/strong><\/code> veya <code><strong>pull request<\/strong><\/code> olaylar&#305;nda  otomasyonumuzun &ccedil;al&#305;&#351;aca&#287;&#305;n&#305; belirttik,<\/li>\n<\/ul>\n<\/li>\n<\/ol>\n\n\n<pre class=\"wp-block-code plover-prism prism-github-dark-theme language-cs\"><code>on:\n  push:\n    branches: [ main ]\n  pull_request:\n    branches: [ main ]<\/code><\/pre>\n\n\n<ol start=\"2\" class=\"wp-block-list\">\n<li>\n<strong>&Ccedil;al&#305;&#351;ma Ortam&#305;<\/strong><ul class=\"wp-block-list\" style=\"\">\n<li>&Ccedil;al&#305;&#351;ma ortam&#305; Ubuntu&rsquo;nun en g&uuml;ncel imaj&#305; (<code>ubuntu-latest<\/code>) ayarlad&#305;k.<\/li>\n\n\n\n<li> CI\/CD&#8217;nin hangi makine &uuml;zerinde &ccedil;al&#305;&#351;t&#305;r&#305;laca&#287;&#305;n&#305; belirtmekteyiz &#351;ayet .Net Framework kullansam windows sanal makine ya da iOS\/macOS uygulamas&#305; derlemek istesem mecburen &#8220;macos-latest&#8221; kullanmam gerekirdi.<\/li>\n<\/ul>\n<\/li>\n<\/ol>\n\n\n<pre class=\"wp-block-code plover-prism prism-github-dark-theme language-cs\"><code>jobs:\n  build-and-deploy:\n    runs-on: ubuntu-latest<\/code><\/pre>\n\n\n<ol start=\"3\" class=\"wp-block-list\">\n<li>\n<strong><strong>Kodun &#304;ndirilmesi<\/strong><\/strong><ul class=\"wp-block-list\" style=\"\">\n<li>\n<code>actions\/checkout@v3<\/code> ile repodaki en g&uuml;ncel kod sanal makineye &ccedil;ekilir.<\/li>\n<\/ul>\n<\/li>\n<\/ol>\n\n\n<pre class=\"wp-block-code plover-prism prism-github-dark-theme language-cs\"><code>    steps:\n      - name: Checkout code\n        uses: actions\/checkout@v3<\/code><\/pre>\n\n\n<ol start=\"4\" class=\"wp-block-list\">\n<li>\n<strong><strong>Docker Buildx Kurulumu<\/strong><\/strong><ul class=\"wp-block-list\" style=\"\">\n<li>&Ccedil;oklu mimari build deste&#287;i i&ccedil;in <code>docker\/setup-buildx-action@v3<\/code> ile Buildx eklentisi y&uuml;klenir.<\/li>\n<\/ul>\n<\/li>\n<\/ol>\n\n\n<pre class=\"wp-block-code plover-prism prism-github-dark-theme language-cs\"><code>      - name: Set up Docker Buildx\n        uses: docker\/setup-buildx-action@v3\n<\/code><\/pre>\n\n\n<ol start=\"5\" class=\"wp-block-list\">\n<li>\n<strong>Docker Hub&rsquo;a Giri&#351;<\/strong><ul class=\"wp-block-list\" style=\"\">\n<li>\n<code>docker\/login-action@v3<\/code> ile, GitHub Secrets&rsquo;dan al&#305;nan secret bilgileriyle Docker Hub&rsquo;a othorizasyon yap&#305;l&#305;r.<\/li>\n<\/ul>\n<\/li>\n<\/ol>\n\n\n<pre class=\"wp-block-code plover-prism prism-github-dark-theme language-cs\"><code>      - name: Login to Docker Hub\n        uses: docker\/login-action@v3\n        with:\n          username: ${{ secrets.DOCKER_USERNAME }}\n          password: ${{ secrets.DOCKER_PASSWORD }}<\/code><\/pre>\n\n\n<ol start=\"6\" class=\"wp-block-list\">\n<li>\n<strong>Docker Compose Kurulumu<\/strong><ul class=\"wp-block-list\" style=\"\">\n<li>Yaz&#305;l&#305;m&#305;m&#305;n bir &ccedil;ok ihtiyac&#305; oldu&#287;undan ve hepsini ayr&#305; ayr&#305; build etmek yerine tek bir docker compose dosyas&#305; b&uuml;t&uuml;n par&ccedil;alar&#305; ayn&#305; anda build ederek g&uuml;ncellemek i&ccedil;in  sanal makineye docker compose y&uuml;kl&uuml;yoruz <\/li>\n<\/ul>\n<\/li>\n<\/ol>\n\n\n<pre class=\"wp-block-code plover-prism prism-github-dark-theme language-cs\"><code>      - name: Set up Docker Compose\n        run: |\n            sudo curl -L \"https:\/\/github.com\/docker\/compose\/releases\/download\/v2.5.0\/docker-compose-$(uname -s)-$(uname -m)\" -o \/usr\/local\/bin\/docker-compose\n            sudo chmod +x \/usr\/local\/bin\/docker-compose<\/code><\/pre>\n\n\n<ol start=\"7\" class=\"wp-block-list\">\n<li>\n<strong>&#304;majlar&#305;n Build &amp; Push Edilmesi<\/strong><ul class=\"wp-block-list\" style=\"\">\n<li>Docker Compose dosya yolunu vererek t&uuml;m servisleri ayn&#305; anda build alarak docker build imajlar&#305;n&#305; docker hub imaj repository&#8217;sine y&uuml;kl&uuml;yoruz<\/li>\n<\/ul>\n<\/li>\n<\/ol>\n\n\n<pre class=\"wp-block-code plover-prism prism-github-dark-theme language-cs\"><code>      - name: Build and Push Docker images\n        run: |\n          docker-compose -f docker\/docker-compose.yml build\n          docker-compose -f docker\/docker-compose.yml push<\/code><\/pre>\n\n\n<ol start=\"7\" class=\"wp-block-list\">\n<li>\n<strong>Uzak Sunucuya SSH ile Ba&#287;lanma &amp; Docker Hub Giri&#351;i<\/strong><ul class=\"wp-block-list\" style=\"\">\n<li>En g&uuml;ncel yaz&#305;l&#305;m&#305;m&#305;z&#305;n prod ortama deploy etmek i&ccedil;in sanal makinemizden SSH ile sunucuya ba&#287;lan&#305;yoruz ve imajlar&#305; &ccedil;ekebilmek i&ccedil;in docker hub&#8217;a login oluyoruz asl&#305;nda kendimiz tek bir sefer docker hub&#8217;a login olursak bu tekrardan login olmaya gerek yok ancak sanal makine bagland&#305;&#287;&#305;m&#305;zdan her seferinde login olmak zorunday&#305;z.<\/li>\n<\/ul>\n<\/li>\n<\/ol>\n\n\n<pre class=\"wp-block-code plover-prism prism-github-dark-theme language-cs\"><code>      - name: Login to Docker Hub on server\n        uses: appleboy\/ssh-action@master\n        with:\n          host: ${{ secrets.SERVER_HOST }}\n          username: ${{ secrets.SERVER_USER }}\n          key: ${{ secrets.SSH_PRIVATE_KEY }}\n          port: ${{ secrets.SSH_PORT }}\n          script: |\n            echo ${{ secrets.DOCKER_PASSWORD }} | docker login -u ${{ secrets.DOCKER_USERNAME }} --password-stdin<\/code><\/pre>\n\n\n<ol start=\"9\" class=\"wp-block-list\">\n<li>\n<strong>Sunucuda Deploy (CD)<\/strong><ul class=\"wp-block-list\" style=\"\">\n<li>Sunucudaki docker compose dosyas&#305;n&#305;n <code>\/var\/www\/app<\/code> dizinine gidilir, son imaj&#305; &ccedil;ekiyoruz ve up -d ile canl&#305;ya al&#305;yoruz asl&#305;nda burada hatal&#305; olmas&#305; durumunda roll-back stratejiside geli&#351;tirilebilirdi. <\/li>\n<\/ul>\n<\/li>\n<\/ol>\n\n\n<pre class=\"wp-block-code plover-prism prism-github-dark-theme language-cs\"><code>      - name: Deploy on server\n        uses: appleboy\/ssh-action@master\n        with:\n          host: ${{ secrets.SERVER_HOST }}\n          username: ${{ secrets.SERVER_USER }}\n          key: ${{ secrets.SSH_PRIVATE_KEY }}\n          port: ${{ secrets.SSH_PORT }}\n          script: |\n            cd \/var\/www\/app\n            docker-compose -f docker\/docker-compose.yml pull\n            docker-compose -f docker\/docker-compose.yml up -d<\/code><\/pre>\n\n\n\n<p>Not: GitHub Actions, kendi ba\u015f\u0131na \u201ctek bir pipeline\u201d de\u011fildir; asl\u0131nda <strong>CI\/CD i\u015f ak\u0131\u015flar\u0131n\u0131z\u0131 tan\u0131mlay\u0131p \u00e7al\u0131\u015ft\u0131rabilece\u011finiz bir otomasyon platformudur<\/strong>;<\/p>\n\n\n<ul class=\"wp-block-list\" style=\"\">\n<li>\n<strong>Workflow (&#304;&#351; Ak&#305;&#351;&#305;):<\/strong> .github\/workflows\/ alt&#305;na koydu&#287;unuz her bir yml dosyas&#305;, <strong>birer workflow<\/strong> yani i&#351; ak&#305;&#351;&#305;d&#305;r.<\/li>\n\n\n\n<li>\n<strong>Job (&#304;&#351;):<\/strong> her workflow i&ccedil;inde birden fazla job tan&#305;mlayabiliriz i&#351;leri paralel veya ard&#305;&#351;&#305;k &ccedil;al&#305;&#351;t&#305;rabiliriz.<\/li>\n\n\n\n<li>\n<strong>Step (Ad&#305;m):<\/strong> Her job, komutlar&#305; veya eylemleri (actions) bar&#305;nd&#305;ran ad&#305;mlar dizisidir.<\/li>\n<\/ul>\n\n\n\n<p>Bu yap\u0131 sayesinde, \u201cCI\/CD pipeline\u201d kavram\u0131n\u0131 \u015f\u00f6yle diyebiliriz:<\/p>\n\n\n<ul class=\"wp-block-list\" style=\"\">\n<li><strong>Pipeline = Workflow + Job&rsquo;lar + Step&rsquo;ler<\/strong><\/li>\n<\/ul>\n\n\n\n<p>Yani GitHub Actions ile istedi\u011finiz say\u0131da pipeline (i\u015f ak\u0131\u015f\u0131) olu\u015fturur, her birinde derleme, test, imaj build\/push ve deploy gibi ad\u0131mlar\u0131 tasarlar\u0131z ve github actions platformu da bu tan\u0131mlar\u0131 okuyup uygun runnerlar\u0131(sanal makineleri) \u00e7al\u0131\u015ft\u0131rarak CI\/CD s\u00fcrecinizi otomatikle\u015ftirir.<\/p>\n\n\n\n<p>\u0130\u015flemlerimizin sonunda action ba\u015far\u0131 ile ger\u00e7ekle\u015fiyor ve yazd\u0131\u011f\u0131m\u0131z son kod ba\u015far\u0131l\u0131 \u015fekilde sunucumuza g\u00fcncelleniyor.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1121\" height=\"747\" src=\"https:\/\/ali-aslan.com\/wp-content\/uploads\/2025\/07\/Actions-edited.png\" alt=\"\" class=\"wp-image-81\" srcset=\"https:\/\/ali-aslan.com\/wp-content\/uploads\/2025\/07\/Actions-edited.png 1121w, https:\/\/ali-aslan.com\/wp-content\/uploads\/2025\/07\/Actions-edited-300x200.png 300w, https:\/\/ali-aslan.com\/wp-content\/uploads\/2025\/07\/Actions-edited-1024x682.png 1024w, https:\/\/ali-aslan.com\/wp-content\/uploads\/2025\/07\/Actions-edited-768x512.png 768w\" sizes=\"auto, (max-width: 1121px) 100vw, 1121px\" \/><\/figure>\n","protected":false},"excerpt":{"rendered":"<p>Bir \u00f6nceki g\u00f6nderimde CI\/CD kavramlar\u0131n\u0131 detayl\u0131ca konu\u015fmu\u015ftuk bu yaz\u0131mda, ba\u015ftan sonra bir Github Actions olu\u015fturaca\u011f\u0131z. &Ouml;n Haz&#305;rl&#305;klar \u00d6ncelikle, GitHub Actions\u2019\u0131n CI\/CD pipeline\u2019\u0131n\u0131z\u0131 otomatik olarak alg\u0131lay\u0131p \u00e7al\u0131\u015ft\u0131rabilmesi i\u00e7in proje k\u00f6k dizininizde \u015fu yolu olu\u015fturmal\u0131s\u0131n\u0131z: Settings > Secret and variables b\u00f6l\u00fcm\u00fcnden sunucumuzun ve docker hub bilgilerimizi secret olarak tan\u0131mlat\u0131p giriyoruz. Not: GitHub Actions, kendi ba\u015f\u0131na \u201ctek bir [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":"[]"},"categories":[6],"tags":[],"class_list":["post-77","post","type-post","status-publish","format-standard","hentry","category-devops"],"_links":{"self":[{"href":"https:\/\/ali-aslan.com\/index.php?rest_route=\/wp\/v2\/posts\/77","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/ali-aslan.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/ali-aslan.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/ali-aslan.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/ali-aslan.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=77"}],"version-history":[{"count":2,"href":"https:\/\/ali-aslan.com\/index.php?rest_route=\/wp\/v2\/posts\/77\/revisions"}],"predecessor-version":[{"id":82,"href":"https:\/\/ali-aslan.com\/index.php?rest_route=\/wp\/v2\/posts\/77\/revisions\/82"}],"wp:attachment":[{"href":"https:\/\/ali-aslan.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=77"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/ali-aslan.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=77"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/ali-aslan.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=77"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}