{"id":279,"date":"2026-08-14T12:00:00","date_gmt":"2026-08-14T12:00:00","guid":{"rendered":"https:\/\/konteynerium.com\/?p=218"},"modified":"2026-10-06T11:34:00","modified_gmt":"2026-10-06T11:34:00","slug":"cicd-ile-docker-github-actions-otomatik-build-deploy","status":"publish","type":"post","link":"https:\/\/konteynerium.com\/index.php\/2026\/08\/14\/cicd-ile-docker-github-actions-otomatik-build-deploy\/","title":{"rendered":"CI\/CD ile Docker: GitHub Actions ile Otomatik Build ve Deploy"},"content":{"rendered":"<p>Bir imaj\u0131 elle build edip elle sunucuya ta\u015f\u0131mak, tek ki\u015filik k\u00fc\u00e7\u00fck projelerde i\u015fe yarasa da ekiple \u00e7al\u0131\u015f\u0131rken h\u0131zla s\u00fcrd\u00fcr\u00fclemez hale gelir. CI\/CD (Continuous Integration \/ Continuous Deployment), kod her push edildi\u011finde imaj\u0131 otomatik build eden, test eden ve gerekirse otomatik da\u011f\u0131tan bir boru hatt\u0131 (pipeline) kurman\u0131z\u0131 sa\u011flar. Bu yaz\u0131da GitHub Actions \u00fczerinden u\u00e7tan uca \u00e7al\u0131\u015fan ger\u00e7ek\u00e7i bir \u00f6rnek kuruyoruz.<\/p>\n<h2>Neden CI\/CD?<\/h2>\n<ul>\n<li><strong>Tutarl\u0131l\u0131k:<\/strong> \u0130maj her zaman ayn\u0131, temiz ortamda build edilir \u2014 &#8220;bende \u00e7al\u0131\u015f\u0131yordu&#8221; sorunu build a\u015famas\u0131nda da ortadan kalkar.<\/li>\n<li><strong>H\u0131z:<\/strong> Kod push edildi\u011fi anda test ve build otomatik ba\u015flar, elle m\u00fcdahale gerekmez.<\/li>\n<li><strong>G\u00fcvenlik:<\/strong> Zafiyet taramas\u0131 gibi kontroller pipeline&#8217;a eklenerek, sorunlu bir imaj\u0131n production&#8217;a ula\u015fmas\u0131 en ba\u015ftan engellenir.<\/li>\n<\/ul>\n<h2>Basit bir GitHub Actions pipeline&#8217;\u0131<\/h2>\n<p><code>.github\/workflows\/docker-build.yml<\/code> dosyas\u0131nda tan\u0131mlanan bu ak\u0131\u015f; her <code>main<\/code> dal\u0131na push&#8217;ta imaj\u0131 build eder, test eder ve registry&#8217;e g\u00f6nderir:<\/p>\n<pre><code>name: Docker Build ve Push\n\non:\n  push:\n    branches: [main]\n\njobs:\n  build:\n    runs-on: ubuntu-latest\n    steps:\n      - name: Kodu \u00e7ek\n        uses: actions\/checkout@v4\n\n      - name: Docker Buildx kur\n        uses: docker\/setup-buildx-action@v3\n\n      - name: Docker Hub'a giri\u015f yap\n        uses: docker\/login-action@v3\n        with:\n          username: ${{ secrets.DOCKERHUB_USERNAME }}\n          password: ${{ secrets.DOCKERHUB_TOKEN }}\n\n      - name: \u0130maj\u0131 build et ve g\u00f6nder\n        uses: docker\/build-push-action@v5\n        with:\n          context: .\n          push: true\n          tags: |\n            kullanici-adi\/benim-api:latest\n            kullanici-adi\/benim-api:${{ github.sha }}\n          cache-from: type=gha\n          cache-to: type=gha,mode=max<\/code><\/pre>\n<p><code>cache-from<\/code>\/<code>cache-to: type=gha<\/code> sat\u0131rlar\u0131, Docker katman \u00f6nbelle\u011fini GitHub Actions&#8217;\u0131n kendi \u00f6nbellek deposunda tutar \u2014 de\u011fi\u015fmeyen katmanlar (\u00f6rne\u011fin ba\u011f\u0131ml\u0131l\u0131k kurulumu) her build&#8217;de s\u0131f\u0131rdan \u00e7al\u0131\u015fmaz, bu da pipeline&#8217;\u0131 ciddi \u00f6l\u00e7\u00fcde h\u0131zland\u0131r\u0131r.<\/p>\n<h2>Build&#8217;den \u00f6nce zafiyet taramas\u0131 ekleyin<\/h2>\n<p>\u0130maj push edilmeden \u00f6nce, bilinen g\u00fcvenlik a\u00e7\u0131klar\u0131n\u0131 yakalamak i\u00e7in Trivy gibi bir taray\u0131c\u0131y\u0131 pipeline&#8217;a eklemek yayg\u0131n bir pratiktir (bkz. <a href=\"https:\/\/konteynerium.com\/index.php\/2026\/07\/03\/container-image-guvenligi-zafiyet-taramasi-en-iyi-uygulamalar\/\">Container Image G\u00fcvenli\u011fi<\/a> yaz\u0131m\u0131z):<\/p>\n<pre><code>      - name: \u0130maj\u0131 yerel olarak build et (hen\u00fcz push etme)\n        uses: docker\/build-push-action@v5\n        with:\n          context: .\n          push: false\n          load: true\n          tags: benim-api:test\n\n      - name: Trivy ile zafiyet taramas\u0131\n        uses: aquasecurity\/trivy-action@master\n        with:\n          image-ref: benim-api:test\n          severity: HIGH,CRITICAL\n          exit-code: 1   # kritik a\u00e7\u0131k bulunursa pipeline'\u0131 durdur<\/code><\/pre>\n<div class=\"callout\">\n  <span class=\"glyph\">\u2713<\/span><\/p>\n<p>S\u0131ray\u0131 do\u011fru kurun: \u00f6nce build + test + tarama, sonra push. B\u00f6ylece taramadan ge\u00e7emeyen bir imaj hi\u00e7bir zaman registry&#8217;e ula\u015fmaz \u2014 &#8220;\u00f6nce da\u011f\u0131t, sonra kontrol et&#8221; de\u011fil, &#8220;\u00f6nce kontrol et, sonra da\u011f\u0131t&#8221; mant\u0131\u011f\u0131.<\/p>\n<\/div>\n<h2>Otomatik da\u011f\u0131t\u0131m (CD): sunucuya deploy<\/h2>\n<p>\u0130maj registry&#8217;e ula\u015ft\u0131ktan sonra, production sunucusunda yeni s\u00fcr\u00fcm\u00fc \u00e7ekip yeniden ba\u015flatan bir ad\u0131m eklenebilir. Basit bir kurulumda bu, SSH \u00fczerinden sunucuda birka\u00e7 komut \u00e7al\u0131\u015ft\u0131rmak kadar basit olabilir:<\/p>\n<pre><code>  deploy:\n    needs: build\n    runs-on: ubuntu-latest\n    steps:\n      - name: Sunucuda yeni imaj\u0131 \u00e7ek ve yeniden ba\u015flat\n        uses: appleboy\/ssh-action@v1\n        with:\n          host: ${{ secrets.SUNUCU_IP }}\n          username: ${{ secrets.SUNUCU_KULLANICI }}\n          key: ${{ secrets.SUNUCU_SSH_ANAHTARI }}\n          script: |\n            docker pull kullanici-adi\/benim-api:latest\n            docker compose up -d --no-deps --build web<\/code><\/pre>\n<p>Kubernetes veya Docker Swarm kullanan daha b\u00fcy\u00fck kurulumlarda bu ad\u0131m genellikle <code>kubectl set image ...<\/code> veya <code>docker service update --image ...<\/code> komutuyla de\u011fi\u015ftirilir \u2014 mant\u0131k ayn\u0131d\u0131r: yeni imaj\u0131 i\u015faret et, orkestrat\u00f6r kalan\u0131n\u0131 (rolling update dahil) halletsin.<\/p>\n<h2>Pipeline&#8217;\u0131 \u00f6zetleyen ak\u0131\u015f<\/h2>\n<ol>\n<li>Kod <code>main<\/code> dal\u0131na push edilir.<\/li>\n<li>Pipeline imaj\u0131 build eder.<\/li>\n<li>Trivy ile zafiyet taramas\u0131 yap\u0131l\u0131r; kritik a\u00e7\u0131k varsa pipeline durur.<\/li>\n<li>Tarama ge\u00e7erse imaj registry&#8217;e push edilir.<\/li>\n<li>Sunucuda (veya orkestrat\u00f6rde) yeni imaj \u00e7ekilip devreye al\u0131n\u0131r.<\/li>\n<\/ol>\n<p>\u0130maj\u0131n\u0131z art\u0131k otomatik olarak build edilip g\u00fcvenli \u015fekilde production&#8217;a ula\u015f\u0131yor. Bir sonraki ad\u0131m, bu production ortam\u0131ndaki container&#8217;lar\u0131n sa\u011fl\u0131kl\u0131 \u00e7al\u0131\u015f\u0131p \u00e7al\u0131\u015fmad\u0131\u011f\u0131n\u0131 s\u00fcrekli izlemek \u2014 bunu bir sonraki yaz\u0131da ele al\u0131yoruz.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Kod push edildi\u011fi anda imaj\u0131 otomatik build eden, Trivy ile tarayan, registry&#8217;e g\u00f6nderen ve sunucuda devreye alan u\u00e7tan uca bir GitHub Actions pipeline&#8217;\u0131 kuruyoruz.<\/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":[],"seviye":[9],"class_list":["post-279","post","type-post","status-publish","format-standard","hentry","category-production-uygulamalar","seviye-ileri"],"_links":{"self":[{"href":"https:\/\/konteynerium.com\/index.php\/wp-json\/wp\/v2\/posts\/279","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/konteynerium.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/konteynerium.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/konteynerium.com\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/konteynerium.com\/index.php\/wp-json\/wp\/v2\/comments?post=279"}],"version-history":[{"count":1,"href":"https:\/\/konteynerium.com\/index.php\/wp-json\/wp\/v2\/posts\/279\/revisions"}],"predecessor-version":[{"id":577,"href":"https:\/\/konteynerium.com\/index.php\/wp-json\/wp\/v2\/posts\/279\/revisions\/577"}],"wp:attachment":[{"href":"https:\/\/konteynerium.com\/index.php\/wp-json\/wp\/v2\/media?parent=279"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/konteynerium.com\/index.php\/wp-json\/wp\/v2\/categories?post=279"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/konteynerium.com\/index.php\/wp-json\/wp\/v2\/tags?post=279"},{"taxonomy":"seviye","embeddable":true,"href":"https:\/\/konteynerium.com\/index.php\/wp-json\/wp\/v2\/seviye?post=279"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}