# Service Containers

**Service containers**, GitHub Actions içinde bir job’un yanına tanımlayabileceğin **ek Docker konteynerleri**dir. Örneğin, **test** aşamasında bir **veritabanı** (MySQL, PostgreSQL), **cache** (Redis), **message broker** (RabbitMQ) vb. hizmete ihtiyaç duyarsan, bu hizmeti “service” olarak tanımlarsın ve aynı job içinde, test kodun bu konteynerle iletişime geçer. Aşağıda konuyu özetliyorum:

### 1) Service Container Nedir?

* GitHub Actions, job başlarken senin tanımladığın “service container” imajlarını **otomatik** olarak çalıştırır.
* Job bitince (veya başarısız olup da tamamlannca) bu container’lar **otomatik** kapatılıp kaldırılır.
* **Aynı job içindeki step’ler**, bu service container’lara “hostname” veya “localhost” + port üzerinden erişebilir.

#### Uses Cases

```yaml
name: Redis Cache Test

on:
  push:
    branches: [ "main" ]

jobs:
  cache-tests:
    runs-on: ubuntu-latest

    services:
      redis:
        image: redis:6-alpine          # 1) "redis:6-alpine" imajını kullan
        ports:
          - 6379:6379                 # 2) "6379" portunu job’a aç
        options: >-
          --health-cmd "redis-cli ping || exit 1"
          --health-interval 5s
          --health-retries 5
          --health-timeout 3s
        # 3) Bu "options" satırı, container hazır olana kadar (sağlıklı) bekler.
        # "redis" adında bir hostname ile job içindeki adımlar erişebilir.

    steps:
      - name: Check out repo
        uses: actions/checkout@v4
        # 4) Kodlarımızı çekiyoruz (örneğin test dosyalarımız vs.)

      - name: Install dependencies
        run: |
          npm install
        # 5) Node.js projesi ise bağımlılıkları yüklüyoruz

      - name: Run tests (with Redis)
        run: |
          # 6) Testlerimiz "redis" konteynerine bağlanacak. 
          # Varsayılan network modunda "redis" hostname:port (6379) üzerinden erişilebilir.
          npm run test
        env:
          REDIS_HOST: redis
          REDIS_PORT: 6379
        # 7) Testlerimize redis bağlantı bilgilerini veriyoruz (hostname: "redis")

      - name: Show Redis Info
        run: |
          # 8) Örnek: "redis-cli -h redis info" komutuyla Redis’e bağlanıp bilgi alıyoruz.
          redis-cli -h redis info

```

#### Use Case Açıklaması

* **Proje Senaryosu**: Örneğin Node.js tabanlı bir uygulama/cache kütüphanesi veya test suite’inin Redis’e ihtiyaç duyduğunu varsayalım. Bu workflow, “main” branch’e push yaptığında otomatik devreye girip testlerini koşturur.
* **Service Container**: “services.redis” alanı, job başlarken bir Redis konteyneri (versiyon 6, alpine imaj) açar. 6379 portunu job ile bağlar.
* **Erişim**: Testler “redis” adıyla hostname’e bağlanabilir. `env.REDIS_HOST` olarak “redis” ayarlanmıştır.
* **Sağlık Kontrolü**: “options” altındaki `--health-cmd` vs. Redis başlatılınca “READY” duruma gelene dek bekler.
* **Temizlik**: Job bittiğinde container otomatik kapatılır.

Böylece **her push**’ta “sıfırdan” temiz bir Redis ortamı oluşturulup test edilir, test sonra biter bitmez container kaldırılır. Bu yaklaşım, CI/CD’de paylaşılan veritabanı/servis kalıntılarından kaçınarak **izole, tekrarlanabilir test ortamı** sağlar.

#### Uses Case 2

```yaml
jobs:
  test-with-db:
    runs-on: ubuntu-latest
    services:
      postgres:
        image: postgres:13
        ports:
          - 5432:5432
        env:
          POSTGRES_USER: myuser
          POSTGRES_PASSWORD: mypass
          POSTGRES_DB: mydb
        options: >-
          --health-cmd "pg_isready -U myuser" 
          --health-interval 10s 
          --health-timeout 5s 
          --health-retries 5
    steps:
      - uses: actions/checkout@v2
      - name: Install Dependencies
        run: npm install
      - name: Run Tests
        run: npm test
```

### 2) Nasıl Çalışır?

1. **Job Başlarken**
   * GitHub, senin `services:` altına yazdığın her imajı birer container olarak ayağa kaldırır.
   * “Bridge mode” ya da “Host mode” gibi network seçenekleriyle, job’un ana container’ı (veya runner) ile bu service container iletişim kurar.
2. **İletişim**
   * Default “bridge mode”da, service container’a **hostname** olarak “service id” kullanırsın. Yukarıdaki örnekte “postgres”.
   * Port mapping ile, “`5432:5432`” diyorsan job, “`<serviceName>:5432`” veya “`localhost:5432`” şeklinde erişebilir. Genelde hostname = “postgres” + port = 5432.
3. **Job Bitince**
   * Tüm service container’lar otomatik sonlandırılır ve temizlenir.
   * Manual cleanup gerekmez.

### 3) Neden Kullanmalı?

* **Kolay Test Ortamı**: Örneğin CI aşamasında veritabanına veya cache sistemine ihtiyaç varsa, sunucu kurmak yerine Docker imajını “services” olarak ekleyebilirsin.
* **Geçici ve İzole**: Her job ayrı container çalıştırdığı için test verileri, config vb. bir sonraki job’a sızmaz.
* **Otomatik Yönetim**: Container’ları elle başlatma/durdurma uğraşın olmadan, “services” tanımıyla her job’da istediğin ek hizmeti açarsın.

### 4) Dikkat Noktaları

1. **Sadece Linux Runner**
   * Docker tabanlı bu sistem, GitHub Hosted runner’larda **Ubuntu** kullanır veya Self-Hosted runner’da **Linux**makine gerekir. Windows/macOS runner’larda service containers desteklenmez.
2. **Network Ayarları**
   * Varsayılan “bridge” modda, hostname “service adın”dır. `ports:` ile port yönlendirmesi yapılır.
   * Bazı durumlarda “host” mod istersen, self-hosted runner ve Docker kurulumuna özel ayarlar gerekebilir.
3. **Büyük İmajlar**
   * Service container imajı çok büyükse, job başlarken indirme süresi uzun olabilir. Gerekirse caching yöntemleri veya optimize edilmiş imajlar kullanılmalı.
4. **Kısıtlamalar**
   * Service containers “composite actions” içinde tanımlanamaz. Sadece bir job context’inde çalıştırabilirsin.

#### Özet

* **Service Containers**: Job’un yanına ek Docker container’lar ekleyip, test veya uygulama için gerekli altyapı hizmetlerini hızlıca ayağa kaldırma yolu.
* **Otomatik yönetim**: Job başında kurulur, job bitince silinir.
* **Kolay Entegrasyon**: Step’lerin bu hizmete `hostname:port` üzerinden erişip test yapar.
* **Örnek**: DB, cache, MQ vb. test ortamları.

{% hint style="info" %}
Eğer “services” altındaki imaj özel bir registry’de barınıyorsa (Docker Hub Private, GHCR Private, vs.), “credentials” blokuyla login bilgilerini verebilirsin.
{% endhint %}

```yaml
services:
  redis:
    image: my-private-registry.com/redis
    credentials:
      username: ${{ secrets.dockerhub_username }}
      password: ${{ secrets.dockerhub_password }}
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://note.onurbolatoglu.com/github-actions/service-containers.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
