Aracılığıyla paylaş


Java uygulamaları için kapsayıcılara giriş

Kapsayıcılar, Java uygulamalarınız için geliştirme, test ve üretim aşamalarında tutarlı ve taşınabilir bir ortam sağlar. Bu makalede Java uygulamaları için kapsayıcılı hale getirme kavramları tanıtılır ve kapsayıcılı Java uygulamaları oluşturma, hata ayıklama, iyileştirme ve Azure Container Apps'e dağıtma konusunda size yol gösterir.

Bu makalede, Java geliştiricileri için temel konteynerleştirme kavramlarını ve aşağıdaki becerileri öğreneceksiniz.

  • Kapsayıcılı Java uygulamaları için geliştirme ortamınızı ayarlama.
  • Java iş yükleri için iyileştirilmiş Dockerfile'lar oluşturma.
  • Kapsayıcılarla yerel geliştirme iş akışlarını yapılandırma.
  • Kapsayıcılı Java uygulamalarında hata ayıklama.
  • Java kapsayıcılarını üretim için optimize etme.
  • Kapsayıcılı Java uygulamalarınızı Azure Container Apps'e dağıtma.

Java uygulamalarınızı kapsayıcılı hale getirerek tutarlı ortamlar, basitleştirilmiş dağıtım, verimli kaynak kullanımı ve gelişmiş ölçeklenebilirlik elde edersiniz.

Java uygulamaları için kapsayıcılar

Kapsayıcılar, uygulamaları bağımlılıklarıyla birlikte paketleyerek ortamlar arasında tutarlılık sağlar. Java geliştiricileri için bu, uygulamayı, bağımlılıklarını, Java Runtime Environment/Java Development Kit'i (JRE/JDK) ve yapılandırma dosyalarını tek bir taşınabilir birimde bir araya getirmek anlamına gelir.

Konteynerleştirme, sanallaştırmaya göre onu bulut geliştirme için ideal kılan önemli avantajlara sahiptir. Bir sanal makinenin aksine, bir kapsayıcı bir sunucunun ana bilgisayar işletim sistemi çekirdeği üzerinde çalışır. Bu, Java sanal makinesinde (JVM) zaten çalışan Java uygulamaları için faydalıdır. Java uygulamalarının kapsayıcılı hale getirilmesi en az ek yük getirir ve önemli dağıtım avantajları sağlar.

Konteyner ekosistemi aşağıdaki temel bileşenleri içerir:

  • Görüntüler - planlar.
  • Kapsayıcılar - çalışan örnekler.
  • Kayıt defterleri - görüntülerin depolandığı yer.
  • Düzenleyiciler: Kapsayıcıları büyük ölçekte yöneten sistemlerdir.

Docker, en popüler kapsayıcılaştırma platformudur ve Azure Container Apps aracılığıyla Azure ekosisteminde iyi bir şekilde desteklenir.

Geliştirme ortamınızı ayarlama

Bu bölüm, gerekli araçları yükleme ve geliştirme ortamınızı kapsayıcılı Java uygulamaları oluşturacak, çalıştıracak ve hata ayıklayacak şekilde yapılandırma konusunda size yol gösterir.

Gerekli araçları yükleyin

Java uygulamalarını kapsayıcılı hale getirmek için geliştirme makinenizde aşağıdaki araçların yüklü olması gerekir:

Aşağıdaki komutları kullanarak yüklemenizi doğrulayın:

docker --version
docker compose version

Kapsayıcı geliştirme için Visual Studio Code'u yapılandırma

Kapsayıcılarda Java geliştirme için Java Uzantı Paketi'ni yükleyerek ve JDK'nizi ayarlayarak Visual Studio Code'u yapılandırın. Dev Containers uzantısı, bir kapsayıcının içindeki herhangi bir klasörü açmanıza ve bu kapsayıcının içinde Visual Studio Code'un tam özellik kümesini kullanmanıza olanak tanır.

Visual Studio Code'un otomatik olarak bir geliştirme kapsayıcısı oluşturmasını ve bu kapsayıcıya bağlanmasını sağlamak için projenizde bir .devcontainer/devcontainer.json dosyası oluşturun.

Örneğin, aşağıdaki örnek yapılandırma bir Java derlemesini tanımlar:

{
    "name": "Java Development",
    "image": "mcr.microsoft.com/devcontainers/java:21",
    "customizations": {
        "vscode": {
            "extensions": [
                "vscjava.vscode-java-pack",
                "ms-azuretools.vscode-docker"
            ]
        }
    },
    "forwardPorts": [8080, 5005],
    "remoteUser": "vscode"
}

Bu yapılandırma, Microsoft'un Java geliştirme kapsayıcısı görüntüsünü kullanır, temel uzantıları ekler ve hem uygulama bağlantı noktasını 8080hem de hata ayıklama bağlantı noktasını 5005iletir.

Dockerfile oluşturma

Dockerfile, Docker görüntüsü oluşturmaya yönelik yönergeler içerir. Java uygulamaları için Dockerfile genellikle aşağıdaki bileşenleri içerir:

  • JDK veya JRE ile bir temel görüntü.
  • Uygulama dosyalarını kopyalama talimatları.
  • Ortam değişkenlerini ayarlamak için komutlar.
  • Giriş noktalarının konfigürasyonları.

Bir temel görüntü seçin

Doğru temel görüntüyü seçmek çok önemlidir. Şu seçenekleri göz önünde bulundurun:

Açıklama İsim Açıklamalar
Microsoft Java geliştirme Görüntüsü mcr.microsoft.com/java/jdk:21-zulu-ubuntu Tam JDK ve Azure için iyileştirildi
Microsoft Java üretim Görüntüsü mcr.microsoft.com/java/jre:21-zulu-ubuntu Yalnızca çalışma zamanı ve Azure için iyileştirilmiştir
Resmi OpenJDK geliştirme Görüntüsü openjdk:21-jdk Tam Java Geliştirme Kiti
Resmi OpenJDK üretim Görüntüsü openjdk:21-jre Yalnızca çalışma zamanı

Geliştirme ortamları için tam bir JDK görüntüsü kullanın. Üretim için, uygulamanızın boyutunu ve saldırı yüzeyini en aza indirmek için bir JRE veya dağıtımsız görüntü kullanın.

Microsoft Java görüntüleri, Azure'a özgü iyileştirmelerle birlikte gelir ve güvenlik düzeltme ekleriyle düzenli olarak güncelleştirilir, bu da onları Azure Container Apps'i hedefleyen uygulamalar için ideal hale getirir.

Temel Dockerfile örnekleri

Aşağıdaki örnekte bir Java uygulaması için basit bir Dockerfile gösterilmektedir:

FROM mcr.microsoft.com/java/jdk:21-zulu-ubuntu
WORKDIR /app
COPY target/myapp.jar app.jar
EXPOSE 8080
ENTRYPOINT ["java", "-jar", "app.jar"]

Spring Boot uygulamaları için Dockerfile'ınızı aşağıdaki temelle ayarlayabilirsiniz:

FROM mcr.microsoft.com/java/jdk:21-zulu-ubuntu
WORKDIR /app
COPY target/*.jar app.jar
EXPOSE 8080
ENTRYPOINT ["java", "-Dspring.profiles.active=docker", "-jar", "app.jar"]

Üretim dağıtımlarında, uygulamanızın boyutunu küçültmek ve saldırı yüzeyini en aza indirmek için aşağıdaki örnekte gösterilen JRE görüntüsünü kullanın:

FROM mcr.microsoft.com/java/jre:21-zulu-ubuntu
WORKDIR /app
COPY target/*.jar app.jar
EXPOSE 8080
ENV JAVA_OPTS="-Dserver.port=8080"
ENTRYPOINT ["java", ${JAVA_OPTS}, "-jar", "app.jar"]

Konteynerler ile yerel geliştirme

Kapsayıcıların farklı ortamlarda çalıştırılması hedeflenmektedir. Bu bölümde, kapsayıcılarla kullanılmak üzere yerel bir geliştirme akışı öğreneceksiniz.

Çok kapsayıcılı uygulamalar için Docker Compose'u kullanma

Çoğu Java uygulaması veritabanları, önbellekler veya diğer hizmetlerle etkileşim kurar. Docker Compose, basit bir YAML yapılandırma dosyası kullanarak çok kapsayıcılı uygulamaları tanımlamanıza ve düzenlemenize yardımcı olur.

Docker Compose nedir?

Docker Compose, aşağıdaki görevleri gerçekleştirmenizi sağlayan bir araçtır:

  • Tek bir dosyada çok kapsayıcılı uygulamalar tanımlayın.
  • Başlatma, durdurma ve yeniden oluşturma dahil olmak üzere uygulama yaşam döngüsünü yönetin.
  • Yalıtılmış ortamları koruyun.
  • Hizmet iletişimi için ağlar oluşturun.
  • Birimleri kullanarak verileri kalıcı hale getirin.

Örnek: Veritabanı ile Java uygulaması

Aşağıdaki compose.yml dosyası, bir PostgreSQL veritabanıyla bir Java uygulamasını yapılandırır:

version: '3.8'
services:
  app:
    build: .                              # Build from Dockerfile in current directory
    ports:
      - "8080:8080"                       # Map HTTP port
      - "5005:5005"                       # Map debug port
    environment:
      - SPRING_PROFILES_ACTIVE=dev
      - SPRING_DATASOURCE_URL=jdbc:postgresql://db:5432/myapp
    volumes:
      - ./target:/app/target              # Mount target directory for hot reloads
    depends_on:
      - db                                # Ensure database starts first
  
  db:
    image: postgres:13
    environment:
      - POSTGRES_USER=postgres
      - POSTGRES_PASSWORD=postgres
      - POSTGRES_DB=myapp
    ports:
      - "5432:5432"                       # Expose PostgreSQL port
    volumes:
      - postgres-data:/var/lib/postgresql/data  # Persist database data

volumes:
  postgres-data:                          # Named volume for database persistence

Bu dosya aşağıdaki özelliklere sahiptir:

  • Hizmetler birbirlerine adlarıyla başvurabilir - örneğin, db JDBC URL'sinde.
  • Docker Compose, hizmetler için otomatik olarak bir ağ oluşturur.
  • Java uygulaması, depends_on nedeniyle veritabanının başlamasını bekler.
  • Veritabanı verileri, adlandırılmış bir birim kullanılarak yeniden başlatmalar arasında kalıcı olur.

Yaygın Docker Compose komutları

compose.yml dosyanızı oluşturduktan sonra, aşağıdaki komutları kullanarak uygulamanızı yönetin:

# Build images without starting containers
docker compose build

# Start all services defined in compose.yml
docker compose up

# Start in detached mode (run in background)
docker compose up -d

# View running containers managed by compose
docker compose ps

# View logs from all containers
docker compose logs

# View logs from a specific service
docker compose logs app

# Stop all services
docker compose down

# Stop and remove volumes (useful for database resets)
docker compose down -v

Geliştirme iş akışı

Docker Compose kullanan tipik bir Java geliştirme iş akışı aşağıdaki adımları içerir:

  1. compose.yml dosyasını ve Dockerfile'ı oluşturun.
  2. Tüm hizmetleri başlatmak için çalıştırın docker compose up .
  3. Java kodunuzda değişiklikler yapın.
  4. Uygulamanızı yeniden oluşturun. Yapılandırmaya bağlı olarak kapsayıcılarınızı yeniden başlatmanız gerekebilir.
  5. Kapsayıcılı ortamdaki değişiklikleri test edin.
  6. İşiniz bittiğinde, docker compose down komutunu çalıştırın.

Tekil kapsayıcıları Docker ile çalıştırın

Birden çok birbirine bağlı hizmete ihtiyacınız olmayan daha basit senaryolar için, tek tek kapsayıcıları docker run başlatmak için komutu kullanabilirsiniz.

Aşağıdaki Docker komutları Java uygulamaları için tipiktir:

# Run a Java application JAR directly
docker run -p 8080:8080 myapp:latest

# Run with environment variables
docker run -p 8080:8080 -e "SPRING_PROFILES_ACTIVE=prod" myapp:latest

# Run in detached mode (background)
docker run -d -p 8080:8080 myapp:latest

# Run with a name for easy reference
docker run -d -p 8080:8080 --name my-java-app myapp:latest

# Run with volume mount for persistent data
docker run -p 8080:8080 -v ./data:/app/data myapp:latest

Kapsayıcılı uygulamalarda hata ayıklama

Kapsayıcılı Java uygulamalarında hata ayıklamak bazen zor olabilir çünkü kodunuz kapsayıcının içindeki yalıtılmış bir ortamda çalışır.

Standart hata ayıklama yaklaşımları her zaman doğrudan uygulanmaz, ancak doğru yapılandırmayla uygulamanızla uzaktan hata ayıklama bağlantısı kurabilirsiniz. Bu bölümde, kapsayıcılarınızı hata ayıklama için nasıl yapılandıracağınız, geliştirme araçlarınızı çalışan kapsayıcılara nasıl bağlayacağınız ve kapsayıcıyla ilgili yaygın sorunları nasıl gidereceğiniz gösterilmektedir.

Uzaktan hata ayıklamayı ayarlama

Kapsayıcılı Java uygulamalarında hata ayıklamak için bir hata ayıklama bağlantı noktasının kullanıma sunulması ve IDE'nizin buna bağlanacak şekilde yapılandırılması gerekir. Aşağıdaki adımları kullanarak bu görevleri gerçekleştirebilirsiniz:

  1. Hata ayıklamayı etkinleştirmek için Dockerfile'ınızı aşağıdaki içeriği içerecek şekilde değiştirin:

    Uyarı

    Bunun yerine kapsayıcı başlatma komutunuzu değiştirebilirsiniz.

    FROM mcr.microsoft.com/java/jdk:21-zulu-ubuntu
    WORKDIR /app
    COPY target/*.jar app.jar
    EXPOSE 8080 5005
    ENTRYPOINT ["java", "-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:5005", "-jar", "app.jar"]
    
  2. Aşağıdaki örnekte gösterildiği gibi Visual Studio Code'un launch.json dosyasını hata ayıklama bağlantı noktasına bağlanacak şekilde yapılandırın:

    {
      "version": "0.2.0",
      "configurations": [
        {
          "type": "java",
          "name": "Debug in Container",
          "request": "attach",
          "hostName": "localhost",
          "port": 5005
        }
      ]
    }
    
  3. Kapsayıcınızı konağınıza eşlenmiş bağlantı noktasıyla 5005 başlatın ve ardından Visual Studio Code'da hata ayıklayıcıyı başlatın.

Kapsayıcı sorunlarını giderme

Kapsayıcılar beklendiği gibi davranmadığında, sorunu araştırmak için uygulamanızın günlüklerini inceleyebilirsiniz.

Uygulamanızdaki sorunları gidermek için aşağıdaki komutları kullanın. Bu komutları çalıştırmadan önce, yer tutucuları (<...>) kendi değerlerinizle değiştirdiğinizden emin olun.

# View logs
docker logs <CONTAINER_ID>

# Follow logs in real-time
docker logs -f <CONTAINER_ID>

# Inspect container details
docker inspect <CONTAINER_ID>

# Get a shell in the container
docker exec -it <CONTAINER_ID> bash

Java'ya özgü sorunlar için, aşağıdaki örnekte gösterildiği gibi daha iyi tanılama için JVM bayraklarını etkinleştirin:

ENTRYPOINT ["java", "-XX:+PrintFlagsFinal", "-XX:+PrintGCDetails", "-jar", "app.jar"]

Aşağıdaki tabloda sık karşılaşılan sorunlar ve ilgili çözümler listelenmektedir:

Hata Olası çözüm
Bellek yetersiz Kapsayıcı bellek sınırlarını artırın
Bağlantı zaman aşımları Ağ yapılandırmasında hata olup olmadığını kontrol edin. Bağlantı noktalarını ve yönlendirme kurallarını doğrulayın.
İzin sorunları Dosya sistemi izinlerini doğrulayın.
Classpath sorunları JAR yapısını ve bağımlılıklarını kontrol edin.

Java kapsayıcılarını optimize edin

Kapsayıcılardaki Java uygulamaları, en iyi performans için özel dikkat gerektirir. JVM, konteynerler yaygın hale gelmeden önce tasarlandı. Kapsayıcıların kullanılması, düzgün yapılandırılmamışlarsa kaynak ayırma sorunlarına yol açabilir.

Bellek ayarlarında ince ayar yaparak, görüntü boyutunu optimize ederek ve çöp toplamayı yapılandırarak kapsayıcılı Java uygulamalarınızın performansını ve verimliliğini önemli ölçüde artırabilirsiniz. Bu bölüm, bellek yönetimi, başlatma zamanı ve kaynak kullanımına odaklanarak Java kapsayıcıları için temel iyileştirmeleri kapsar.

Kapsayıcılarda JVM bellek yapılandırması

JVM, Java 8'de kapsayıcı bellek sınırlarını otomatik olarak algılamaz. Java 9+ için, kapsayıcı tanıma varsayılan olarak etkindir.

Aşağıdaki örnekte gösterildiği gibi JVM'nizi kapsayıcı sınırlarına uyacak şekilde yapılandırın:

FROM mcr.microsoft.com/java/jre:21-zulu-ubuntu
WORKDIR /app
COPY target/*.jar app.jar
EXPOSE 8080
ENTRYPOINT ["java", "-XX:MaxRAMPercentage=75.0", "-jar", "app.jar"]

Aşağıdaki JVM bayrakları kapsayıcılı uygulamalar için önemlidir:

  • -XX:MaxRAMPercentage=75.0. En fazla yığını kullanılabilir belleğin yüzdesi olarak ayarlar.
  • -XX:InitialRAMPercentage=50.0. İlk yığın boyutunu ayarlar.
  • -Xmx ve -Xms. Bu bayraklar da mevcuttur, ancak sabit değerler gerektirirler.

Üretim dağıtımına hazırlanma

Kapsayıcılı Java uygulamalarını üretime taşımak, temel işlevlerin ötesinde dikkat edilmesi gereken noktalar gerektirir.

Üretim ortamları güçlü güvenlik, güvenilir izleme, uygun kaynak tahsisi ve yapılandırma esnekliği gerektirir.

Bu bölüm, Java kapsayıcılarınızı üretim kullanımına hazırlamak için gereken temel uygulamaları ve yapılandırmaları kapsar. Bu bölüm, uygulamalarınızın üretimde güvenilir bir şekilde çalışmasını sağlamak için güvenlik, durum denetimleri ve yapılandırma yönetimine odaklanır.

En iyi güvenlik uygulamaları

Aşağıdaki uygulamaları kullanarak kapsayıcılı Java uygulamalarınızın güvenliğini sağlayın:

  • Varsayılan güvenlik bağlamı. Aşağıdaki örnekte gösterildiği gibi uygulamalarınızı kök olmayan bir kullanıcı olarak çalıştırın:

    FROM mcr.microsoft.com/java/jre:21-zulu-ubuntu
    WORKDIR /app
    COPY target/*.jar app.jar
    RUN addgroup --system javauser && adduser --system --ingroup javauser javauser
    USER javauser
    ENTRYPOINT ["java", "-jar", "app.jar"]
    
  • Proaktif olarak sorunları arayın. Aşağıdaki komutu kullanarak kapsayıcı görüntülerini güvenlik açıklarına karşı düzenli olarak tarayın:

    docker scan myapp:latest
    
  • Temel görüntü tazeliği. Temel görüntülerinizi güncel tutun.

  • Gizli bilgi yönetimi. Uygun gizli anahtar yönetimi uygulayın. Örneğin, hassas verileri uygulamanıza sabit kodlamayın ve mümkün olduğunda bir anahtar kasası kullanın.

  • Kısıtlı güvenlik bağlamları. En az ayrıcalık ilkesini tüm güvenlik bağlamlarına uygulayın.

  • Dosya sistemi erişimi. Mümkün olan her yerde salt okunur dosya sistemlerini kullanın.

Durum denetimleri ve izleme

Uygulamanızın doğru çalıştığından emin olmak için yoklamalarla uygulama durumunu denetleyin.

Spring Boot uygulamaları için, aşağıdaki örnekte gösterildiği gibi kapsamlı sistem durumu uç noktaları için Actuator bağımlılığını ekleyin:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>

Uygulamanızı, günlükleri JSON gibi kapsayıcı ortamları için uygun bir biçimde çıkaracak şekilde yapılandırın.

Azure Container Apps'a dağıtım

Bu bölüm, Java kapsayıcılarınızı Azure Container Apps dağıtımına hazırlama konusunda size yol gösterir ve yapılandırmayla ilgili önemli noktaları vurgular.

Kapsayıcınızı Azure için hazırlama

  • Bağlantı noktası yapılandırması. Aşağıdaki örnekte gösterildiği gibi kapsayıcınızın Azure tarafından sağlanan bağlantı noktasını dinlediğinden emin olun:

    FROM mcr.microsoft.com/java/jre:21-zulu-ubuntu
    WORKDIR /app
    COPY target/*.jar app.jar
    ENV PORT=8080
    EXPOSE ${PORT}
    CMD java -jar app.jar --server.port=${PORT}
    
  • Sağlık için araştırma. Azure'ın canlılık ve hazırlık denetimleri için sağlık yoklamaları uygulayın.

  • Kayıt yapılandırma. Günlüğe kaydetmeyistdout/stderr'e çıktı vermesi için yapılandırın.

  • Beklenmedik durumlar için plan yapın. Zaman aşımı yapılandırması ile doğru ve kesintisiz bir kapatma işlemi ayarlayın. Daha fazla bilgi için Azure Container Apps'te uygulama yaşam döngüsü yönetimibölümüne bakın.