Uwaga
Dostęp do tej strony wymaga autoryzacji. Może spróbować zalogować się lub zmienić katalogi.
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zmienić katalogi.
Kontenery zapewniają spójne, przenośne środowisko dla aplikacji Java na wszystkich etapach programowania, testowania i produkcji. W tym artykule przedstawiono pojęcia dotyczące konteneryzacji aplikacji Java i przeprowadzono Cię przez proces tworzenia, debugowania, optymalizowania i wdrażania konteneryzowanych aplikacji Java w usłudze Azure Container Apps.
W tym artykule poznasz podstawowe pojęcia dotyczące konteneryzacji dla deweloperów języka Java oraz następujące umiejętności:
- Konfigurowanie środowiska programistycznego dla konteneryzowanych aplikacji Java.
- Tworzenie plików Dockerfile zoptymalizowanych pod kątem obciążeń Java.
- Konfigurowanie lokalnych przepływów pracy programowania za pomocą kontenerów.
- Debugowanie konteneryzowanych aplikacji Java.
- Optymalizacja kontenerów Java pod kątem produkcji.
- Wdrażanie konteneryzowanych aplikacji Java w usłudze Azure Container Apps.
Konteneryzując aplikacje Java, uzyskujesz spójne środowiska, uproszczone wdrażanie, efektywne wykorzystanie zasobów i lepszą skalowalność.
Kontenery dla aplikacji Java
Kontenery pakują aplikacje wraz z ich zależnościami, zapewniając spójność między środowiskami. Dla programistów Java oznacza to sprzedaż wiązaną aplikacji, jej zależności, środowiska Java Runtime Environment/Java Development Kit (JRE/JDK) oraz plików konfiguracyjnych w jedną, przenośną jednostkę.
Konteneryzacja ma kluczowe zalety w porównaniu z wirtualizacją, dzięki czemu idealnie nadaje się do tworzenia w chmurze. W przeciwieństwie do maszyny wirtualnej, kontener działa na jądrze systemu operacyjnego hosta serwera. Jest to korzystne dla aplikacji Java, które już działają na wirtualnej maszynie Java (JVM). Konteneryzacja aplikacji Java zwiększa minimalne obciążenie i zapewnia znaczne korzyści z wdrażania.
Ekosystem kontenerów obejmuje następujące kluczowe komponenty:
- Obrazy - plany.
- Kontenery — uruchomione instancje.
- Rejestry - gdzie przechowywane są obrazy.
- Orkiestratory — systemy, które zarządzają kontenerami na dużą skalę.
Platforma Docker to najpopularniejsza platforma konteneryzacji, która jest dobrze obsługiwana w ekosystemie platformy Azure za pośrednictwem usługi Azure Container Apps.
Konfigurowanie środowiska projektowego
Ta sekcja przeprowadzi Cię przez proces instalowania niezbędnych narzędzi i konfigurowania środowiska programistycznego do tworzenia, uruchamiania i debugowania konteneryzowanych aplikacji Java.
Zainstaluj wymagane narzędzia
Do konteneryzacji aplikacji Java potrzebne są następujące narzędzia zainstalowane na komputerze deweloperskim:
- Docker Desktop. Udostępnia aparat platformy Docker, interfejs wiersza polecenia i narzędzie Docker Compose dla systemu Windows lub macOS.
- Visual Studio Code. Dostępny jako darmowy edytor kodu.
- Następujące rozszerzenia Visual Studio Code:
- Rozszerzenie Docker do zarządzania kontenerami.
- Pakiet rozszerzeń Java do programowania w języku Java.
- Dev Containers do programowania wewnątrz kontenerów.
Sprawdź instalację przy użyciu następujących poleceń:
docker --version
docker compose version
Konfigurowanie Visual Studio Code na potrzeby tworzenia kontenerów
W przypadku programowania w języku Java w kontenerach skonfiguruj Visual Studio Code, instalując pakiet rozszerzeń Java i konfigurując zestaw JDK. Rozszerzenie Dev Containers umożliwia otwarcie dowolnego folderu w kontenerze i korzystanie z pełnego zestawu funkcji Visual Studio Code wewnątrz tego kontenera.
Aby umożliwić programowi Visual Studio Code automatyczne kompilowanie kontenera deweloperskiego i nawiązywanie z nim połączenia, utwórz plik .devcontainer/devcontainer.json w projekcie.
Na przykład poniższa przykładowa konfiguracja definiuje kompilację języka Java:
{
"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"
}
Ta konfiguracja używa obrazu kontenera programistycznego Java firmy Microsoft, dodaje niezbędne rozszerzenia i przekazuje zarówno port aplikacji, 8080
jak i port debugowania, 5005
.
Tworzenie pliku Dockerfile
Plik Dockerfile zawiera instrukcje dotyczące tworzenia obrazu platformy Docker. W przypadku aplikacji Java plik Dockerfile zwykle zawiera następujące składniki:
- Obraz podstawowy z zestawem JDK lub JRE.
- Instrukcje kopiowania plików aplikacji.
- Polecenia do ustawiania zmiennych środowiskowych.
- Konfiguracje punktów wejścia.
Wybieranie obrazu podstawowego
Wybór odpowiedniego obrazu bazowego ma kluczowe znaczenie. Rozważ następujące opcje:
Opis | Nazwa | Uwagi |
---|---|---|
Obraz programowania w języku Microsoft Java | mcr.microsoft.com/java/jdk:21-zulu-ubuntu |
Pełny zestaw JDK zoptymalizowany pod kątem platformy Azure |
Obraz produkcyjny Microsoft Java | mcr.microsoft.com/java/jre:21-zulu-ubuntu |
Tylko środowisko uruchomieniowe i zoptymalizowane pod kątem platformy Azure |
Oficjalny obraz rozwoju OpenJDK | openjdk:21-jdk |
Pełny JDK |
Oficjalny obraz produkcyjny OpenJDK | openjdk:21-jre |
Tylko środowisko uruchomieniowe |
W przypadku środowisk programistycznych użyj pełnego obrazu JDK. W środowisku produkcyjnym użyj środowiska JRE lub obrazu bez dystrybucji, aby zminimalizować rozmiar i obszar ataku aplikacji.
Obrazy języka Java firmy Microsoft są dostarczane z optymalizacjami specyficznymi dla platformy Azure i są regularnie aktualizowane za pomocą poprawek zabezpieczeń, dzięki czemu idealnie nadają się do aplikacji przeznaczonych dla usługi Azure Container Apps.
Podstawowe przykłady plików Dockerfile
W poniższym przykładzie przedstawiono prosty plik Dockerfile dla aplikacji Java:
FROM mcr.microsoft.com/java/jdk:21-zulu-ubuntu
WORKDIR /app
COPY target/myapp.jar app.jar
EXPOSE 8080
ENTRYPOINT ["java", "-jar", "app.jar"]
W przypadku aplikacji Spring Boot można skonfigurować plik Dockerfile przy użyciu następującej podstawy:
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"]
W przypadku wdrożeń produkcyjnych użyj obrazu środowiska JRE pokazanego w poniższym przykładzie, aby zmniejszyć rozmiar i zminimalizować obszar ataków aplikacji:
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"]
Rozwój lokalny z wykorzystaniem kontenerów
Kontenery są przeznaczone do wykonywania w różnych kontekstach. W tej sekcji poznasz lokalny przepływ programowania do użycia z kontenerami.
Używanie narzędzia Docker Compose dla aplikacji z wieloma kontenerami
Większość aplikacji Java współdziała z bazami danych, pamięciami podręcznymi lub innymi usługami. Docker Compose ułatwia definiowanie i organizowanie aplikacji z wieloma kontenerami przy użyciu prostego pliku konfiguracji YAML.
Co to jest Docker Compose?
Docker Compose to narzędzie, które umożliwia wykonywanie następujących zadań:
- Definiowanie aplikacji z wieloma kontenerami w jednym pliku.
- Zarządzanie cyklem życia aplikacji, w tym uruchamianiem, zatrzymywaniem i ponownym kompilowaniem.
- Utrzymuj izolowane środowiska.
- Tworzenie sieci do komunikacji usług.
- Utrwalanie danych przy użyciu woluminów.
Przykład: aplikacja Java z bazą danych
Następujący plik compose.yml konfiguruje aplikację Java z bazą danych PostgreSQL:
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
Ten plik ma następujące cechy:
- Usługi mogą odwoływać się do siebie nawzajem według nazw — na przykład
db
w adresie URL JDBC. - Docker Compose automatycznie tworzy sieć dla usług.
- Aplikacja Java czeka na uruchomienie bazy danych z powodu .
depends_on
- Dane bazy danych są zachowywane między ponownymi uruchomieniami przy użyciu nazwanego woluminu.
Typowe polecenia narzędzia Docker Compose
Po utworzeniu pliku compose.yml zarządzaj aplikacją przy użyciu następujących poleceń:
# 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
Przepływ pracy deweloperskiej
Typowy przepływ pracy programowania w języku Java przy użyciu narzędzia Docker Compose obejmuje następujące kroki:
- Utwórz plik compose.yml i plik Dockerfile.
- Uruchom
docker compose up
, aby uruchomić wszystkie usługi. - Wprowadź zmiany w kodzie Java.
- Ponownie skompiluj aplikację. W zależności od konfiguracji może być konieczne ponowne uruchomienie kontenerów.
- Przetestuj zmiany w środowisku konteneryzowanym.
- Po zakończeniu uruchom polecenie
docker compose down
.
Uruchamianie pojedynczych kontenerów za pomocą platformy Docker
W przypadku prostszych scenariuszy, gdy nie potrzebujesz wielu połączonych usług, możesz użyć docker run
polecenia, aby uruchomić poszczególne kontenery.
Następujące polecenia platformy Docker są typowe dla aplikacji Java:
# 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
Debugowanie aplikacji konteneryzowanych
Debugowanie konteneryzowanych aplikacji Java jest czasami trudne, ponieważ kod działa w izolowanym środowisku wewnątrz kontenera.
Standardowe podejścia debugowania nie zawsze są stosowane bezpośrednio, ale przy odpowiedniej konfiguracji można ustanowić połączenie debugowania zdalnego z aplikacją. W tej sekcji pokazano, jak skonfigurować kontenery do debugowania, połączyć narzędzia programistyczne z uruchomionymi kontenerami i rozwiązywać typowe problemy związane z kontenerami.
Konfigurowanie debugowania zdalnego
Debugowanie konteneryzowanych aplikacji Java wymaga uwidocznienia portu debugowania i skonfigurowania środowiska IDE do nawiązywania z nim połączenia. Zadania te można wykonać, wykonując następujące czynności:
Aby włączyć debugowanie, zmodyfikuj plik Dockerfile tak, aby zawierał następującą zawartość:
Uwaga / Notatka
Zamiast tego możesz zmodyfikować polecenie uruchamiania kontenera.
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"]
Skonfiguruj plik launch.json Visual Studio Code w celu nawiązania połączenia z portem debugowania, jak pokazano w poniższym przykładzie:
{ "version": "0.2.0", "configurations": [ { "type": "java", "name": "Debug in Container", "request": "attach", "hostName": "localhost", "port": 5005 } ] }
Uruchom kontener z portem
5005
zamapowanym na hosta, a następnie uruchom debuger w Visual Studio Code.
Rozwiązywanie problemów z kontenerami
Jeśli kontenery nie zachowują się zgodnie z oczekiwaniami, możesz sprawdzić dzienniki aplikacji, aby zbadać problem.
Użyj następujących poleceń, aby rozwiązać problemy z aplikacją. Przed uruchomieniem tych poleceń należy pamiętać o zastąpieniu symboli zastępczych (<...>
) własnymi wartościami.
# 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
W przypadku problemów specyficznych dla języka Java włącz flagi JVM, aby uzyskać lepszą diagnostykę, jak pokazano w poniższym przykładzie:
ENTRYPOINT ["java", "-XX:+PrintFlagsFinal", "-XX:+PrintGCDetails", "-jar", "app.jar"]
W poniższej tabeli wymieniono typowe problemy i odpowiadające im rozwiązania:
Błąd | Możliwe rozwiązanie |
---|---|
Za mało pamięci | Zwiększanie limitów pamięci kontenera |
Przekroczenia limitu czasu połączenia | Sprawdź konfigurację sieci pod kątem błędów. Sprawdź porty i reguły routingu. |
Problemy z uprawnieniami | Sprawdź uprawnienia systemu plików. |
Problemy ze ścieżką klas | Sprawdź strukturę JAR i zależności. |
Optymalizuj kontenery Java
Aplikacje Java w kontenerach wymagają specjalnego uwzględnienia w celu uzyskania optymalnej wydajności. JVM została zaprojektowana, zanim kontenery stały się powszechne. Korzystanie z kontenerów może prowadzić do problemów z alokacją zasobów, jeśli nie są one prawidłowo skonfigurowane.
Możesz znacznie poprawić wydajność i efektywność konteneryzowanych aplikacji Java, dostrajając ustawienia pamięci, optymalizując rozmiar obrazu i konfigurując odzyskiwanie pamięci. W tej sekcji omówiono podstawowe optymalizacje kontenerów Java, ze szczególnym uwzględnieniem zarządzania pamięcią, czasu uruchamiania i wykorzystania zasobów.
Konfiguracja pamięci JVM w kontenerach
Maszyna JVM nie wykrywa automatycznie limitów pamięci kontenera w środowisku Java 8. W środowisku Java 9+ rozpoznawanie kontenerów jest domyślnie włączone.
Skonfiguruj maszynę JVM tak, aby przestrzegała limitów kontenerów, jak pokazano w poniższym przykładzie:
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"]
Następujące flagi JVM są ważne dla aplikacji konteneryzowanych:
-
-XX:MaxRAMPercentage=75.0
. Ustawia maksymalną stertę jako procent dostępnej pamięci. -
-XX:InitialRAMPercentage=50.0
. Ustawia początkowy rozmiar sterty. -
-Xmx
i-Xms
. Te flagi są również dostępne, ale wymagają stałych wartości.
Przygotowanie do wdrożenia produkcyjnego
Przenoszenie konteneryzowanych aplikacji Java do środowiska produkcyjnego wymaga uwzględnienia wykraczających poza podstawowe funkcje.
Środowiska produkcyjne wymagają solidnych zabezpieczeń, niezawodnego monitorowania, odpowiedniej alokacji zasobów i elastyczności konfiguracji.
W tej sekcji omówiono podstawowe praktyki i konfiguracje potrzebne do przygotowania kontenerów Java do użytku produkcyjnego. Ta sekcja koncentruje się na zabezpieczeniach, kontrolach kondycji i zarządzaniu konfiguracją, aby zapewnić niezawodne działanie aplikacji w środowisku produkcyjnym.
Najlepsze rozwiązania dotyczące zabezpieczeń
Zabezpiecz konteneryzowane aplikacje Java, korzystając z następujących rozwiązań:
Domyślny kontekst zabezpieczeń. Uruchom aplikacje jako użytkownik inny niż root, jak pokazano w poniższym przykładzie:
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"]
Proaktywnie szukaj problemów. Regularnie skanuj obrazy kontenerów pod kątem luk w zabezpieczeniach przy użyciu następującego polecenia:
docker scan myapp:latest
Podstawowa aktualność obrazu. Aktualizuj obrazy podstawowe.
Zarządzanie sekretami. Zaimplementuj odpowiednie zarządzanie wpisami tajnymi. Na przykład nie koduj poufnych danych w aplikacji i używaj magazynu kluczy, gdy tylko jest to możliwe.
Ograniczone konteksty zabezpieczeń. Zastosuj zasadę najniższych uprawnień do wszystkich kontekstów zabezpieczeń.
Dostęp do systemu plików. Tam, gdzie to możliwe, używaj systemów plików tylko do odczytu.
Kontrole stanu zdrowia i monitorowanie
Sprawdź kondycję aplikacji za pomocą sond, aby upewnić się, że aplikacja działa poprawnie.
W przypadku aplikacji Spring Boot uwzględnij zależność siłownika dla kompleksowych punktów końcowych kondycji, jak pokazano w poniższym przykładzie:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
Skonfiguruj aplikację tak, aby dzienniki wyjściowe były w formacie odpowiednim dla środowisk kontenerów, takich jak JSON.
Wdrażanie w usłudze Azure Container Apps
W tej sekcji przedstawiono proces przygotowywania kontenerów Java do wdrożenia usługi Azure Container Apps i przedstawiono kluczowe zagadnienia dotyczące konfiguracji.
Przygotowywanie kontenera dla platformy Azure
Konfiguracja portów. Upewnij się, że kontener nasłuchuje na porcie dostarczonym przez platformę Azure, jak pokazano w poniższym przykładzie:
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}
Sonda dla zdrowia. Zaimplementuj sondy kondycji na potrzeby sprawdzania aktualności i gotowości platformy Azure.
Konfiguracja dziennika. Skonfiguruj rejestrowanie do danych wyjściowych do
stdout
/stderr
.Przygotuj się na nieoczekiwane. Skonfiguruj odpowiednią obsługę bezpiecznego zamykania z konfiguracją limitu czasu. Aby uzyskać więcej informacji, zobacz Zarządzanie cyklem życia aplikacji w usłudze Azure Container Apps.