Docker ile Spring Boot Uygulaması Deploy Etmek
Neden Docker ile Spring Boot?
Spring Boot uygulamanızı geliştirdiniz, testlerden geçti, her şey hazır. Ama deployment aşamasında "benim makinemde çalışıyordu" problemini herkes yaşamıştır. Farklı Java versiyonları, eksik system kütüphaneleri, farklı OS yapılandırmaları... Docker tüm bu sorunları ortadan kaldırır.
Docker ile Spring Boot uygulamanızı:
Tekrarlanabilir şekilde paketlersiniz — her build aynı sonucu verir
Taşınabilir hale getirirsiniz — laptop'tan AWS'ye aynı image çalışır
İzole edersiniz — bağımlılıklar diğer uygulamalarla çakışmaz
Ölçeklendirilebilir yaparsınız — Kubernetes ile kolayca scale edilir
Temel Dockerfile
İlk olarak basit bir Dockerfile ile başlayalım:
FROM eclipse-temurin:21-jre-alpine
WORKDIR /app
COPY target/*.jar app.jar
EXPOSE 8080
ENTRYPOINT ["java", "-jar", "app.jar"]Bu Dockerfile çalışır ama birkaç problemi var:
Her kod değişikliğinde tüm JAR yeniden kopyalanır (layer cache kullanılamaz)
Build işlemi Docker dışında yapılması gerekir (
mvn packageönce çalıştırılmalı)Image boyutu optimize edilmemiştir
Multi-Stage Build ile Optimizasyon
Multi-stage build, hem build hem de runtime aşamalarını tek bir Dockerfile'da tanımlamanızı sağlar. Build aşamasında kullanılan Maven, JDK ve kaynak kodlar final image'a dahil edilmez:
# Stage 1: Build
FROM eclipse-temurin:21-jdk-alpine AS build
WORKDIR /app
# Maven wrapper ve pom.xml'i kopyala (dependency cache için)
COPY mvnw pom.xml ./
COPY .mvn .mvn
# Dependency'leri indir (bu katman cache'lenir)
RUN ./mvnw dependency:go-offline -B
# Kaynak kodu kopyala ve build et
COPY src src
RUN ./mvnw package -DskipTests -B
# Stage 2: Runtime
FROM eclipse-temurin:21-jre-alpine
RUN addgroup -S appgroup && adduser -S appuser -G appgroup
WORKDIR /app
COPY --from=build /app/target/*.jar app.jar
RUN chown appuser:appgroup app.jar
USER appuser
EXPOSE 8080
HEALTHCHECK --interval=30s --timeout=3s --retries=3 \
CMD wget -qO- http://localhost:8080/actuator/health || exit 1
ENTRYPOINT ["java", \
"-XX:+UseContainerSupport", \
"-XX:MaxRAMPercentage=75.0", \
"-Djava.security.egd=file:/dev/./urandom", \
"-jar", "app.jar"]Bu Dockerfile'da dikkat edilecek noktalar:
Dependency katmanı ayrı:
pom.xmldeğişmediği sürece dependency'ler cache'den gelirJRE kullanımı: Runtime'da JDK'ya gerek yok, JRE yeterli (image boyutu ~150MB daha küçük)
Non-root user: Güvenlik için uygulama root olarak çalışmaz
Container-aware JVM flags:
UseContainerSupportile JVM, container memory limit'ini doğru algılarHealth check: Docker, uygulamanın sağlıklı olup olmadığını kontrol eder
İpucu:
eclipse-temurinOpenJDK'nın Adoptium tarafından dağıtılan production-grade build'idir. Alpine varyantı en küçük image boyutunu sağlar.
Spring Boot Layered JAR
Spring Boot 2.3+ ile gelen layered JAR özelliği, Docker cache'ini daha iyi kullanmanızı sağlar:
# Stage 1: Build
FROM eclipse-temurin:21-jdk-alpine AS build
WORKDIR /app
COPY mvnw pom.xml ./
COPY .mvn .mvn
RUN ./mvnw dependency:go-offline -B
COPY src src
RUN ./mvnw package -DskipTests -B
# Stage 2: Extract layers
FROM eclipse-temurin:21-jdk-alpine AS extract
WORKDIR /app
COPY --from=build /app/target/*.jar app.jar
RUN java -Djarmode=layertools -jar app.jar extract
# Stage 3: Runtime
FROM eclipse-temurin:21-jre-alpine
RUN addgroup -S appgroup && adduser -S appuser -G appgroup
WORKDIR /app
COPY --from=extract /app/dependencies/ ./
COPY --from=extract /app/spring-boot-loader/ ./
COPY --from=extract /app/snapshot-dependencies/ ./
COPY --from=extract /app/application/ ./
USER appuser
EXPOSE 8080
ENTRYPOINT ["java", "org.springframework.boot.loader.launch.JarLauncher"]Bu yaklaşımda uygulama kodunuz değiştiğinde sadece application katmanı yeniden build edilir. Spring dependency'leri ve third-party kütüphaneler cache'den gelir.
Docker Compose ile Geliştirme Ortamı
Gerçek dünya uygulamalarında veritabanı, cache, message queue gibi servisler de gerekir. Docker Compose ile tüm bileşenleri tek komutla ayağa kaldırabilirsiniz:
services:
app:
build:
context: .
dockerfile: Dockerfile
ports:
- "8080:8080"
environment:
- SPRING_PROFILES_ACTIVE=docker
- SPRING_DATASOURCE_URL=jdbc:mysql://mysql:3306/myapp
- SPRING_DATASOURCE_USERNAME=root
- SPRING_DATASOURCE_PASSWORD=secret
- SPRING_DATA_REDIS_HOST=redis
- SPRING_RABBITMQ_HOST=rabbitmq
depends_on:
mysql:
condition: service_healthy
redis:
condition: service_started
restart: unless-stopped
mysql:
image: mysql:8.0
environment:
MYSQL_DATABASE: myapp
MYSQL_ROOT_PASSWORD: secret
ports:
- "3306:3306"
volumes:
- mysql_data:/var/lib/mysql
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
interval: 10s
timeout: 5s
retries: 5
redis:
image: redis:7-alpine
ports:
- "6379:6379"
volumes:
- redis_data:/data
rabbitmq:
image: rabbitmq:3-management-alpine
ports:
- "5672:5672"
- "15672:15672"
environment:
RABBITMQ_DEFAULT_USER: admin
RABBITMQ_DEFAULT_PASS: admin
volumes:
mysql_data:
redis_data:depends_on ile condition: service_healthy kullanarak MySQL tamamen hazır olana kadar uygulamanın başlamaSını bekletebilirsiniz.
Environment Yönetimi
Spring Boot'un profile mekanizmasını Docker environment variable'ları ile birleştirebilirsiniz:
# application.yml
spring:
datasource:
url: jdbc:mysql://localhost:3306/myapp
username: root
password: secret
---
# application-docker.yml
spring:
config:
activate:
on-profile: docker
datasource:
url: ${SPRING_DATASOURCE_URL:jdbc:mysql://mysql:3306/myapp}
username: ${SPRING_DATASOURCE_USERNAME:root}
password: ${SPRING_DATASOURCE_PASSWORD:secret}Hassas bilgiler (şifreler, API key'ler) için Docker secrets veya .env dosyası kullanın:
# .env dosyası (git'e eklemeyin!)
MYSQL_ROOT_PASSWORD=super_secret_password
SPRING_DATASOURCE_PASSWORD=super_secret_password
JWT_SECRET=my-jwt-secret-key-256-bit# docker-compose.yml
services:
app:
env_file:
- .envHealth Check ve Monitoring
Spring Boot Actuator ile sağlık kontrolü endpoint'leri ekleyin:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>management:
endpoints:
web:
exposure:
include: health,info,metrics,prometheus
endpoint:
health:
show-details: when-authorizedDockerfile'daki HEALTHCHECK direktifi bu endpoint'i kullanır. Kubernetes ortamında liveness ve readiness probe'ları da aynı endpoint'lerle yapılandırılır.
Production Best Practices
Image boyutunu küçük tutun: Alpine tabanlı image'lar kullanın.
eclipse-temurin:21-jre-alpineyaklaşık 100MB'dir.Root olarak çalıştırmayın: Her zaman non-root user oluşturun.
Build cache'i optimize edin: Sık değişen dosyaları (kaynak kodu) en sona koyun.
Güvenlik taraması yapın:
docker scoutveyatrivyile image'daki güvenlik açıklarını tarayın:
# Trivy ile güvenlik taraması
docker run --rm -v /var/run/docker.sock:/var/run/docker.sock \
aquasec/trivy image myapp:latestImage tag'lerinde latest kullanmayın: Versiyon numarası ve commit hash kullanın:
docker build -t myapp:1.2.3 -t myapp:$(git rev-parse --short HEAD) ..dockerignore dosyası oluşturun:
.git
.gitignore
.idea
*.md
target
!target/*.jar
docker-compose*.ymlJVM memory ayarlarını container'a göre yapın:
# Container'a 512MB memory limit verin
docker run -m 512m myapp:latest
# JVM otomatik olarak %75'ini (384MB) heap için kullanır
# -XX:MaxRAMPercentage=75.0 flag'i ileÖzet
Multi-stage build ile build ve runtime katmanlarını ayırın — image boyutu %70 küçülür
Layered JAR ile Docker cache'ini optimize edin — sadece değişen katmanlar rebuild edilir
Docker Compose ile tüm servisleri (DB, cache, queue) tek komutla yönetin
Non-root user, health check ve güvenlik taraması production'da zorunlu
Environment variable'lar ile konfigürasyonu dışarıdan yönetin — image'a secret gömmeyin
JVM container flags kullanarak memory'yi doğru yönetin
Bu yazıyı beğendiniz mi?
Bültene abone olun ve yeni yazılardan ilk siz haberdar olun. Spam yok, söz.
İlgili Yazılar
Docker Compose: Çoklu Container Uygulamalarını Tek Komutla Yönetme Rehberi
Docker Compose ile birden fazla container'ı nasıl tanımlar, yapılandırır ve tek bir komutla ayağa kaldırırsınız? Servis...
Docker Compose Rehberi: Çoklu Container Yönetimi
Docker Compose nedir, nasıl kurulur, docker-compose.yml nasıl yazılır? Services, volumes, networks, environment variable...
Docker Nedir? Container Teknolojisi Rehberi
Docker nedir, container nedir? VM vs container farkları, Dockerfile, Docker Compose, güvenlik ve Kubernetes karşılaştırm...