Bir imajı elle build edip elle sunucuya taşımak, tek kişilik küçük projelerde işe yarasa da ekiple çalışırken hızla sürdürülemez hale gelir. CI/CD (Continuous Integration / Continuous Deployment), kod her push edildiğinde imajı otomatik build eden, test eden ve gerekirse otomatik dağıtan bir boru hattı (pipeline) kurmanızı sağlar. Bu yazıda GitHub Actions üzerinden uçtan uca çalışan gerçekçi bir örnek kuruyoruz.
Neden CI/CD?
- Tutarlılık: İmaj her zaman aynı, temiz ortamda build edilir — “bende çalışıyordu” sorunu build aşamasında da ortadan kalkar.
- Hız: Kod push edildiği anda test ve build otomatik başlar, elle müdahale gerekmez.
- Güvenlik: Zafiyet taraması gibi kontroller pipeline’a eklenerek, sorunlu bir imajın production’a ulaşması en baştan engellenir.
Basit bir GitHub Actions pipeline’ı
.github/workflows/docker-build.yml dosyasında tanımlanan bu akış; her main dalına push’ta imajı build eder, test eder ve registry’e gönderir:
name: Docker Build ve Push
on:
push:
branches: [main]
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Kodu çek
uses: actions/checkout@v4
- name: Docker Buildx kur
uses: docker/setup-buildx-action@v3
- name: Docker Hub'a giriş yap
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: İmajı build et ve gönder
uses: docker/build-push-action@v5
with:
context: .
push: true
tags: |
kullanici-adi/benim-api:latest
kullanici-adi/benim-api:${{ github.sha }}
cache-from: type=gha
cache-to: type=gha,mode=max
cache-from/cache-to: type=gha satırları, Docker katman önbelleğini GitHub Actions’ın kendi önbellek deposunda tutar — değişmeyen katmanlar (örneğin bağımlılık kurulumu) her build’de sıfırdan çalışmaz, bu da pipeline’ı ciddi ölçüde hızlandırır.
Build’den önce zafiyet taraması ekleyin
İmaj push edilmeden önce, bilinen güvenlik açıklarını yakalamak için Trivy gibi bir tarayıcıyı pipeline’a eklemek yaygın bir pratiktir (bkz. Container Image Güvenliği yazımız):
- name: İmajı yerel olarak build et (henüz push etme)
uses: docker/build-push-action@v5
with:
context: .
push: false
load: true
tags: benim-api:test
- name: Trivy ile zafiyet taraması
uses: aquasecurity/trivy-action@master
with:
image-ref: benim-api:test
severity: HIGH,CRITICAL
exit-code: 1 # kritik açık bulunursa pipeline'ı durdur
Sırayı doğru kurun: önce build + test + tarama, sonra push. Böylece taramadan geçemeyen bir imaj hiçbir zaman registry’e ulaşmaz — “önce dağıt, sonra kontrol et” değil, “önce kontrol et, sonra dağıt” mantığı.
Otomatik dağıtım (CD): sunucuya deploy
İmaj registry’e ulaştıktan sonra, production sunucusunda yeni sürümü çekip yeniden başlatan bir adım eklenebilir. Basit bir kurulumda bu, SSH üzerinden sunucuda birkaç komut çalıştırmak kadar basit olabilir:
deploy:
needs: build
runs-on: ubuntu-latest
steps:
- name: Sunucuda yeni imajı çek ve yeniden başlat
uses: appleboy/ssh-action@v1
with:
host: ${{ secrets.SUNUCU_IP }}
username: ${{ secrets.SUNUCU_KULLANICI }}
key: ${{ secrets.SUNUCU_SSH_ANAHTARI }}
script: |
docker pull kullanici-adi/benim-api:latest
docker compose up -d --no-deps --build web
Kubernetes veya Docker Swarm kullanan daha büyük kurulumlarda bu adım genellikle kubectl set image ... veya docker service update --image ... komutuyla değiştirilir — mantık aynıdır: yeni imajı işaret et, orkestratör kalanını (rolling update dahil) halletsin.
Pipeline’ı özetleyen akış
- Kod
maindalına push edilir. - Pipeline imajı build eder.
- Trivy ile zafiyet taraması yapılır; kritik açık varsa pipeline durur.
- Tarama geçerse imaj registry’e push edilir.
- Sunucuda (veya orkestratörde) yeni imaj çekilip devreye alınır.
İmajınız artık otomatik olarak build edilip güvenli şekilde production’a ulaşıyor. Bir sonraki adım, bu production ortamındaki container’ların sağlıklı çalışıp çalışmadığını sürekli izlemek — bunu bir sonraki yazıda ele alıyoruz.