Gönderi

Docker ve Docker Compose ile Mikroservis Mimarisi Geliştirme

Docker Compose ile tam mikroservis mimarisi. Container orchestration, service discovery, load balancing ve production deployment.

Docker ve Docker Compose ile Mikroservis Mimarisi Geliştirme

Modern yazılım geliştirmede konteynerleştirme, uygulamaların taşınabilir, ölçeklenebilir ve tutarlı bir şekilde çalışmasını sağlayan temel bir teknoloji haline gelmiştir. Docker, konteyner teknolojisinin en popüler implementasyonudur ve Docker Compose, çoklu konteyner uygulamaların yönetimini kolaylaştırır. Bu yazıda Docker temellerinden mikroservis mimarisi oluşturmaya kadar detaylı bir rehber sunacağız.

Docker Nedir ve Neden Kullanmalıyız?

Docker, uygulamaları ve bağımlılıklarını izole edilmiş konteynerlerde çalıştırmamızı sağlayan bir platform’dur. Sanal makinelere göre daha hafif ve hızlıdır çünkü işletim sistemi çekirdeğini paylaşır.

Docker’ın Avantajları

  • Tutarlılık: “Benim makinemde çalışıyordu” problemini çözer
  • Taşınabilirlik: Herhangi bir ortamda aynı şekilde çalışır
  • İzolasyon: Her konteyner izole bir ortamda çalışır
  • Hız: Saniyeler içinde başlatılıp durdurulabilir
  • Kaynak Verimliliği: VM’lere göre çok daha az kaynak tüketir
  • Ölçeklenebilirlik: Kolayca yatay ölçeklendirme yapılabilir

Docker Kurulumu

Ubuntu/Debian için Docker kurulumu:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# Sistem güncellemesi
sudo apt update
sudo apt upgrade -y

# Gerekli paketleri kur
sudo apt install -y apt-transport-https ca-certificates curl software-properties-common

# Docker GPG anahtarını ekle
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg

# Docker repository'yi ekle
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

# Docker'ı kur
sudo apt update
sudo apt install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin

# Docker'ı başlat ve otomatik başlatmayı etkinleştir
sudo systemctl start docker
sudo systemctl enable docker

# Kullanıcıyı docker grubuna ekle (sudo olmadan çalıştırmak için)
sudo usermod -aG docker $USER

# Değişikliklerin geçerli olması için oturumu yenile
newgrp docker

# Docker kurulumunu test et
docker --version
docker compose version

Docker Temel Kavramlar

Image (İmaj)

Docker image, uygulamayı çalıştırmak için gereken tüm bileşenleri içeren read-only şablondur:

1
2
3
4
5
6
7
8
9
10
11
12
13
# Docker Hub'dan image çekme
docker pull nginx:latest
docker pull python:3.11-slim
docker pull postgres:15-alpine

# Mevcut image'ları listeleme
docker images

# Image silme
docker rmi nginx:latest

# Image detaylarını inceleme
docker inspect nginx:latest

Container (Konteyner)

Container, bir image’in çalışan instance’ıdır:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
# Konteyner çalıştırma
docker run nginx

# Detached mode (arkaplanda) çalıştırma
docker run -d --name my-nginx nginx

# Port mapping ile çalıştırma
docker run -d -p 8080:80 --name web-server nginx

# Environment variable ile çalıştırma
docker run -d -e POSTGRES_PASSWORD=secret postgres:15

# Çalışan konteynerleri listeleme
docker ps

# Tüm konteynerleri listeleme (durdurulmuş olanlar dahil)
docker ps -a

# Konteyner durdurma
docker stop my-nginx

# Konteyner başlatma
docker start my-nginx

# Konteyner yeniden başlatma
docker restart my-nginx

# Konteyner silme
docker rm my-nginx

# Çalışan konteyneri zorla silme
docker rm -f my-nginx

# Tüm durdurulmuş konteynerleri silme
docker container prune

Dockerfile Oluşturma

Dockerfile, custom image oluşturmak için kullanılan talimatlar dosyasıdır:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
# Base image seçimi
FROM python:3.11-slim

# Metadata
LABEL maintainer="[email protected]"
LABEL version="1.0"
LABEL description="FastAPI microservice"

# Çalışma dizini oluştur
WORKDIR /app

# Sistem bağımlılıklarını kur
RUN apt-get update && \
    apt-get install -y --no-install-recommends \
    gcc \
    && rm -rf /var/lib/apt/lists/*

# Python bağımlılıklarını kopyala
COPY requirements.txt .

# Bağımlılıkları kur
RUN pip install --no-cache-dir -r requirements.txt

# Uygulama kodunu kopyala
COPY . .

# Gerekli dizinleri oluştur
RUN mkdir -p /app/logs /app/data

# Non-root kullanıcı oluştur (security best practice)
RUN useradd -m -u 1000 appuser && \
    chown -R appuser:appuser /app

# Non-root kullanıcıya geç
USER appuser

# Port açıklaması (dokümantasyon amaçlı)
EXPOSE 8000

# Health check tanımlama
HEALTHCHECK --interval=30s --timeout=3s --start-period=40s --retries=3 \
    CMD curl -f http://localhost:8000/health || exit 1

# Başlangıç komutu
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]

Image build etme:

1
2
3
4
5
6
7
8
9
10
# Image oluşturma
docker build -t myapp:1.0 .

# Build argument ile oluşturma
docker build --build-arg VERSION=1.0 -t myapp:1.0 .

# No-cache ile oluşturma (tüm katmanları yeniden oluştur)
docker build --no-cache -t myapp:1.0 .

# Multi-stage build örneği

Multi-Stage Build

Production için optimize edilmiş image oluşturma:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# Build stage
FROM python:3.11 AS builder

WORKDIR /app

# Bağımlılıkları kur
COPY requirements.txt .
RUN pip install --user --no-cache-dir -r requirements.txt

# Production stage
FROM python:3.11-slim

WORKDIR /app

# Build stage'den sadece gerekli dosyaları kopyala
COPY --from=builder /root/.local /root/.local
COPY . .

# PATH'i güncelle
ENV PATH=/root/.local/bin:$PATH

USER 1000

EXPOSE 8000

CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]

Bu yaklaşım, final image boyutunu önemli ölçüde küçültür.

Docker Compose Microservices Docker Compose ile Mikroservis Mimarisi

Docker Compose ile Çoklu Konteyner Yönetimi

Docker Compose, birden fazla konteyneri tek bir YAML dosyası ile yönetmemizi sağlar.

Basit Docker Compose Örneği

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
version: '3.8'

services:
  # Web servisi
  web:
    build: ./web
    ports:
      - "8000:8000"
    environment:
      - DATABASE_URL=postgresql://user:pass@db:5432/mydb
      - REDIS_URL=redis://redis:6379
    depends_on:
      - db
      - redis
    volumes:
      - ./web:/app
      - web-logs:/app/logs
    networks:
      - app-network
    restart: unless-stopped

  # Veritabanı servisi
  db:
    image: postgres:15-alpine
    environment:
      - POSTGRES_USER=user
      - POSTGRES_PASSWORD=pass
      - POSTGRES_DB=mydb
    volumes:
      - postgres-data:/var/lib/postgresql/data
      - ./init.sql:/docker-entrypoint-initdb.d/init.sql:ro
    networks:
      - app-network
    restart: unless-stopped
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U user"]
      interval: 10s
      timeout: 5s
      retries: 5

  # Redis servisi
  redis:
    image: redis:7-alpine
    command: redis-server --appendonly yes
    volumes:
      - redis-data:/data
    networks:
      - app-network
    restart: unless-stopped

# Volume tanımlamaları
volumes:
  postgres-data:
  redis-data:
  web-logs:

# Network tanımlamaları
networks:
  app-network:
    driver: bridge

Docker Compose Komutları

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
# Servisleri başlat (detached mode)
docker compose up -d

# Servisleri başlat ve logları takip et
docker compose up

# Belirli bir servisi başlat
docker compose up -d web

# Servisleri durdur
docker compose stop

# Servisleri durdur ve kaldır
docker compose down

# Servisleri, volume'ları ve orphan container'ları da kaldır
docker compose down -v --remove-orphans

# Servisleri yeniden oluştur ve başlat
docker compose up -d --build

# Çalışan servislerin durumunu görüntüle
docker compose ps

# Servis loglarını görüntüle
docker compose logs

# Belirli bir servisin loglarını takip et
docker compose logs -f web

# Servisi yeniden başlat
docker compose restart web

# Servise komut çalıştır
docker compose exec web python manage.py migrate

# Yeni bir shell başlat
docker compose exec web /bin/bash

# Çalışan konteynerlere ait kaynakları görüntüle
docker compose top

# Servisleri ölçeklendir
docker compose up -d --scale web=3

Docker Networking Docker Container Networking ve Bridge Architecture

Docker Networking

Docker, konteynerler arası iletişim için güçlü network özellikleri sunar.

Network Türleri

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
# Bridge network (default)
docker network create my-bridge-network

# Host network (konteynerdoğrudan host network kullanır)
docker run --network host nginx

# None network (network yok)
docker run --network none alpine

# Custom bridge network oluşturma
docker network create --driver bridge \
  --subnet=172.18.0.0/16 \
  --gateway=172.18.0.1 \
  custom-network

# Network'leri listeleme
docker network ls

# Network detaylarını görüntüleme
docker network inspect my-bridge-network

# Konteyneri network'e bağlama
docker network connect my-bridge-network my-container

# Konteyneri network'ten ayırma
docker network disconnect my-bridge-network my-container

# Kullanılmayan network'leri silme
docker network prune

Docker Compose ile Network Yönetimi

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
version: '3.8'

services:
  frontend:
    image: nginx
    networks:
      - frontend-net
      - backend-net
    ports:
      - "80:80"

  api:
    build: ./api
    networks:
      - backend-net
      - database-net
    environment:
      - DB_HOST=database

  database:
    image: postgres:15
    networks:
      - database-net
    volumes:
      - db-data:/var/lib/postgresql/data

networks:
  # Frontend network (public)
  frontend-net:
    driver: bridge

  # Backend network (internal communication)
  backend-net:
    driver: bridge
    internal: false

  # Database network (isolated)
  database-net:
    driver: bridge
    internal: true

volumes:
  db-data:

Docker Volumes Docker Volumes ve Persistent Storage

Docker Volumes ile Veri Kalıcılığı

Konteynerler ephemeral (geçici) olduğu için kalıcı veri depolamak için volume kullanırız.

Volume Türleri

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# Named volume oluşturma
docker volume create my-data

# Volume'ları listeleme
docker volume ls

# Volume detaylarını görüntüleme
docker volume inspect my-data

# Volume kullanarak konteyner başlatma
docker run -d -v my-data:/data nginx

# Bind mount kullanma (host dizinini mount etme)
docker run -d -v /host/path:/container/path nginx

# Read-only bind mount
docker run -d -v /host/path:/container/path:ro nginx

# tmpfs mount (RAM'de geçici depolama)
docker run -d --tmpfs /tmp:rw,size=1g nginx

# Volume silme
docker volume rm my-data

# Kullanılmayan volume'ları silme
docker volume prune

Docker Compose ile Volume Yönetimi

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
version: '3.8'

services:
  app:
    build: .
    volumes:
      # Named volume
      - app-data:/app/data
      
      # Bind mount (kod geliştirme için)
      - ./src:/app/src:ro
      
      # Anonymous volume
      - /app/node_modules
      
      # Config file mount
      - ./config.yml:/app/config.yml:ro

  database:
    image: postgres:15
    volumes:
      # Database data
      - db-data:/var/lib/postgresql/data
      
      # Init scripts
      - ./init-scripts:/docker-entrypoint-initdb.d:ro
      
      # Backup directory
      - ./backups:/backups

volumes:
  app-data:
    driver: local
    driver_opts:
      type: none
      device: /mnt/app-data
      o: bind

  db-data:
    driver: local

Mikroservis Mimarisi Örneği

Gerçek dünya senaryosu için kapsamlı bir mikroservis projesi oluşturalım.

Proje Yapısı

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
microservices-app/
├── docker-compose.yml
├── docker-compose.prod.yml
├── .env
├── nginx/
│   ├── Dockerfile
│   └── nginx.conf
├── api-gateway/
│   ├── Dockerfile
│   ├── requirements.txt
│   └── main.py
├── user-service/
│   ├── Dockerfile
│   ├── requirements.txt
│   └── main.py
├── product-service/
│   ├── Dockerfile
│   ├── requirements.txt
│   └── main.py
└── order-service/
    ├── Dockerfile
    ├── requirements.txt
    └── main.py

Ana Docker Compose Dosyası

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
# docker-compose.yml
version: '3.8'

x-common-variables: &common-variables
  REDIS_URL: redis://redis:6379
  RABBITMQ_URL: amqp://guest:guest@rabbitmq:5672

services:
  # Nginx Reverse Proxy
  nginx:
    build: ./nginx
    ports:
      - "80:80"
      - "443:443"
    depends_on:
      - api-gateway
    networks:
      - frontend
    volumes:
      - ./nginx/conf.d:/etc/nginx/conf.d:ro
      - ./ssl:/etc/nginx/ssl:ro
      - nginx-logs:/var/log/nginx
    restart: unless-stopped

  # API Gateway
  api-gateway:
    build:
      context: ./api-gateway
      args:
        - VERSION=${VERSION:-latest}
    environment:
      <<: *common-variables
      USER_SERVICE_URL: http://user-service:8001
      PRODUCT_SERVICE_URL: http://product-service:8002
      ORDER_SERVICE_URL: http://order-service:8003
    networks:
      - frontend
      - backend
    depends_on:
      - user-service
      - product-service
      - order-service
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:8000/health"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 40s
    restart: unless-stopped

  # User Service
  user-service:
    build: ./user-service
    environment:
      <<: *common-variables
      DATABASE_URL: postgresql://user:${POSTGRES_PASSWORD}@user-db:5432/users
      JWT_SECRET: ${JWT_SECRET}
    networks:
      - backend
      - user-db-net
    depends_on:
      user-db:
        condition: service_healthy
      redis:
        condition: service_started
    deploy:
      replicas: 2
      resources:
        limits:
          cpus: '0.5'
          memory: 512M
    restart: unless-stopped

  user-db:
    image: postgres:15-alpine
    environment:
      POSTGRES_USER: user
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
      POSTGRES_DB: users
    volumes:
      - user-db-data:/var/lib/postgresql/data
      - ./user-service/init.sql:/docker-entrypoint-initdb.d/init.sql:ro
    networks:
      - user-db-net
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U user"]
      interval: 10s
      timeout: 5s
      retries: 5
    restart: unless-stopped

  # Product Service
  product-service:
    build: ./product-service
    environment:
      <<: *common-variables
      DATABASE_URL: postgresql://user:${POSTGRES_PASSWORD}@product-db:5432/products
      ELASTICSEARCH_URL: http://elasticsearch:9200
    networks:
      - backend
      - product-db-net
      - search-net
    depends_on:
      product-db:
        condition: service_healthy
      elasticsearch:
        condition: service_healthy
    restart: unless-stopped

  product-db:
    image: postgres:15-alpine
    environment:
      POSTGRES_USER: user
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
      POSTGRES_DB: products
    volumes:
      - product-db-data:/var/lib/postgresql/data
    networks:
      - product-db-net
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U user"]
      interval: 10s
      timeout: 5s
      retries: 5
    restart: unless-stopped

  # Order Service
  order-service:
    build: ./order-service
    environment:
      <<: *common-variables
      DATABASE_URL: postgresql://user:${POSTGRES_PASSWORD}@order-db:5432/orders
      PAYMENT_API_KEY: ${PAYMENT_API_KEY}
    networks:
      - backend
      - order-db-net
    depends_on:
      order-db:
        condition: service_healthy
      rabbitmq:
        condition: service_healthy
    restart: unless-stopped

  order-db:
    image: postgres:15-alpine
    environment:
      POSTGRES_USER: user
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
      POSTGRES_DB: orders
    volumes:
      - order-db-data:/var/lib/postgresql/data
    networks:
      - order-db-net
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U user"]
      interval: 10s
      timeout: 5s
      retries: 5
    restart: unless-stopped

  # Redis (Caching)
  redis:
    image: redis:7-alpine
    command: redis-server --appendonly yes --requirepass ${REDIS_PASSWORD}
    volumes:
      - redis-data:/data
    networks:
      - backend
    healthcheck:
      test: ["CMD", "redis-cli", "ping"]
      interval: 10s
      timeout: 3s
      retries: 3
    restart: unless-stopped

  # RabbitMQ (Message Queue)
  rabbitmq:
    image: rabbitmq:3-management-alpine
    environment:
      RABBITMQ_DEFAULT_USER: ${RABBITMQ_USER:-guest}
      RABBITMQ_DEFAULT_PASS: ${RABBITMQ_PASSWORD:-guest}
    ports:
      - "15672:15672"  # Management UI
    volumes:
      - rabbitmq-data:/var/lib/rabbitmq
    networks:
      - backend
    healthcheck:
      test: ["CMD", "rabbitmq-diagnostics", "ping"]
      interval: 30s
      timeout: 10s
      retries: 3
    restart: unless-stopped

  # Elasticsearch (Search)
  elasticsearch:
    image: docker.elastic.co/elasticsearch/elasticsearch:8.11.0
    environment:
      - discovery.type=single-node
      - xpack.security.enabled=false
      - "ES_JAVA_OPTS=-Xms512m -Xmx512m"
    volumes:
      - elasticsearch-data:/usr/share/elasticsearch/data
    networks:
      - search-net
    healthcheck:
      test: ["CMD-SHELL", "curl -f http://localhost:9200/_cluster/health || exit 1"]
      interval: 30s
      timeout: 10s
      retries: 3
    restart: unless-stopped

# Volume Tanımlamaları
volumes:
  user-db-data:
  product-db-data:
  order-db-data:
  redis-data:
  rabbitmq-data:
  elasticsearch-data:
  nginx-logs:

# Network Tanımlamaları
networks:
  frontend:
    driver: bridge
  backend:
    driver: bridge
    internal: false
  user-db-net:
    driver: bridge
    internal: true
  product-db-net:
    driver: bridge
    internal: true
  order-db-net:
    driver: bridge
    internal: true
  search-net:
    driver: bridge

Environment Variables

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# .env
VERSION=1.0.0

# Database
POSTGRES_PASSWORD=your_secure_password_here

# Redis
REDIS_PASSWORD=your_redis_password

# RabbitMQ
RABBITMQ_USER=admin
RABBITMQ_PASSWORD=your_rabbitmq_password

# JWT
JWT_SECRET=your_jwt_secret_key_min_32_chars

# Payment API
PAYMENT_API_KEY=your_payment_api_key

Nginx Configuration

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
# nginx/nginx.conf
upstream api_gateway {
    least_conn;
    server api-gateway:8000 max_fails=3 fail_timeout=30s;
}

server {
    listen 80;
    server_name api.example.com;

    # Security headers
    add_header X-Frame-Options "SAMEORIGIN" always;
    add_header X-Content-Type-Options "nosniff" always;
    add_header X-XSS-Protection "1; mode=block" always;

    # Logging
    access_log /var/log/nginx/access.log combined;
    error_log /var/log/nginx/error.log warn;

    # Rate limiting
    limit_req_zone $binary_remote_addr zone=api_limit:10m rate=10r/s;
    limit_req zone=api_limit burst=20 nodelay;

    # API Gateway
    location /api/ {
        proxy_pass http://api_gateway/;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;

        # Timeouts
        proxy_connect_timeout 60s;
        proxy_send_timeout 60s;
        proxy_read_timeout 60s;

        # Buffering
        proxy_buffering off;
        proxy_request_buffering off;
    }

    # Health check endpoint
    location /health {
        access_log off;
        return 200 "healthy\n";
        add_header Content-Type text/plain;
    }
}

Production Best Practices

1. Multi-Environment Setup

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# docker-compose.prod.yml
version: '3.8'

services:
  api-gateway:
    deploy:
      replicas: 3
      update_config:
        parallelism: 1
        delay: 10s
      restart_policy:
        condition: on-failure
        delay: 5s
        max_attempts: 3
    logging:
      driver: "json-file"
      options:
        max-size: "10m"
        max-file: "3"

  # Production-specific overrides
  nginx:
    volumes:
      - /etc/letsencrypt:/etc/letsencrypt:ro

Çalıştırma:

1
2
3
4
5
# Development
docker compose up -d

# Production
docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d

2. Backup ve Restore

1
2
3
4
5
6
7
8
9
10
11
#!/bin/bash
# backup.sh

# Database backup
docker compose exec -T user-db pg_dump -U user users > backups/users_$(date +%Y%m%d_%H%M%S).sql

# Volume backup
docker run --rm \
  -v microservices-app_user-db-data:/data \
  -v $(pwd)/backups:/backup \
  alpine tar czf /backup/user-db-volume_$(date +%Y%m%d_%H%M%S).tar.gz /data
1
2
3
4
5
6
7
8
9
10
11
#!/bin/bash
# restore.sh

# Database restore
docker compose exec -T user-db psql -U user users < backups/users_20241203_120000.sql

# Volume restore
docker run --rm \
  -v microservices-app_user-db-data:/data \
  -v $(pwd)/backups:/backup \
  alpine sh -c "cd /data && tar xzf /backup/user-db-volume_20241203_120000.tar.gz --strip 1"

3. Monitoring ve Logging

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
# docker-compose.monitoring.yml
version: '3.8'

services:
  # Prometheus (Metrics)
  prometheus:
    image: prom/prometheus:latest
    volumes:
      - ./prometheus/prometheus.yml:/etc/prometheus/prometheus.yml:ro
      - prometheus-data:/prometheus
    command:
      - '--config.file=/etc/prometheus/prometheus.yml'
      - '--storage.tsdb.path=/prometheus'
    ports:
      - "9090:9090"
    networks:
      - monitoring

  # Grafana (Visualization)
  grafana:
    image: grafana/grafana:latest
    environment:
      - GF_SECURITY_ADMIN_PASSWORD=${GRAFANA_PASSWORD}
    volumes:
      - grafana-data:/var/lib/grafana
      - ./grafana/dashboards:/etc/grafana/provisioning/dashboards:ro
    ports:
      - "3000:3000"
    networks:
      - monitoring
    depends_on:
      - prometheus

  # Loki (Logging)
  loki:
    image: grafana/loki:latest
    ports:
      - "3100:3100"
    volumes:
      - loki-data:/loki
    networks:
      - monitoring

volumes:
  prometheus-data:
  grafana-data:
  loki-data:

networks:
  monitoring:
    driver: bridge

4. CI/CD Pipeline

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
# .github/workflows/deploy.yml
name: Deploy to Production

on:
  push:
    branches: [ main ]

jobs:
  build-and-deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3

      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v2

      - name: Login to Docker Hub
        uses: docker/login-action@v2
        with:
          username: $
          password: $

      - name: Build and push
        uses: docker/build-push-action@v4
        with:
          context: ./api-gateway
          push: true
          tags: username/api-gateway:$,username/api-gateway:latest
          cache-from: type=gha
          cache-to: type=gha,mode=max

      - name: Deploy to server
        uses: appleboy/ssh-action@master
        with:
          host: $
          username: $
          key: $
          script: |
            cd /opt/microservices-app
            docker compose pull
            docker compose up -d --remove-orphans
            docker system prune -f

Sonuç

Docker ve Docker Compose, modern uygulama geliştirme ve deployment süreçlerinde vazgeçilmez araçlar haline gelmiştir. Mikroservis mimarisinde, her servisin izole edilmesi, bağımsız ölçeklendirilmesi ve yönetilmesi için ideal bir platform sunarlar.

Bu yazıda öğrendikleriniz:

  • Docker temel kavramları ve kullanımı
  • Dockerfile ile custom image oluşturma
  • Docker Compose ile çoklu konteyner yönetimi
  • Network ve volume yönetimi
  • Production-ready mikroservis mimarisi
  • Monitoring, backup ve CI/CD entegrasyonu

Önerilen Kaynaklar

Bir sonraki yazımızda, Redis ile önbellekleme ve oturum yönetimini inceleyeceğiz. Takipte kalın!

Bu gönderi CC BY 4.0 lisansı altındadır.