Ответ
В DevOps-практике запуск Java-приложения — это не просто команда java -jar, а этап в цепочке сборки, доставки и развертывания, который должен быть воспроизводимым, изолированным и управляемым. Вот как мы это делаем:
-
Сборка и упаковка в исполняемый JAR (или WAR) Используем Maven или Gradle для сборки финального артефакта, содержащего все зависимости (например,
spring-boot-maven-pluginдля создания fat JAR). Это основа для дальнейших шагов.# Стандартная сборка mvn clean package # На выходе: target/my-application-1.0.0.jar -
Контейнеризация (Docker) Это стандарт де-факто. Создаем Docker-образ на основе официального OpenJDK или дистрибутивов с оптимизированной JVM (например, Eclipse Temurin). Используем многоступенчатую сборку (multi-stage build) для уменьшения размера финального образа.
# Multi-stage build FROM maven:3.8-eclipse-temurin-17 AS builder WORKDIR /app COPY . . RUN mvn clean package -DskipTests FROM eclipse-temurin:17-jre-jammy WORKDIR /app COPY --from=builder /app/target/*.jar app.jar # Настройка JVM для контейнеров (критически важно!) ENV JAVA_OPTS="-XX:+UseContainerSupport -XX:MaxRAMPercentage=75.0" ENTRYPOINT ["sh", "-c", "java $JAVA_OPTS -jar /app/app.jar"]Затем образ пушится в Container Registry (Docker Hub, ECR, GCR).
-
Оркестрация (Kubernetes) Запуск контейнеризированного приложения в K8s через Deployment, который управляет Pod'ами.
apiVersion: apps/v1 kind: Deployment metadata: name: java-app spec: replicas: 3 selector: matchLabels: app: java-app template: metadata: labels: app: java-app spec: containers: - name: app image: my-registry/java-app:1.0.0 ports: - containerPort: 8080 resources: requests: memory: "512Mi" cpu: "250m" limits: memory: "1Gi" cpu: "500m" env: - name: SPRING_PROFILES_ACTIVE value: "production" -
Запуск через системы инициализации (systemd) на виртуальных машинах Если используется не контейнерная, а VM-инфраструктура, приложение управляется как системный сервис.
# /etc/systemd/system/my-java-app.service [Unit] Description=My Java Application After=network.target [Service] Type=simple User=appuser WorkingDirectory=/opt/myapp Environment="JAVA_HOME=/usr/lib/jvm/java-17-openjdk" Environment="JAVA_OPTS=-Xmx1g -Dspring.profiles.active=prod" ExecStart=/usr/bin/java $JAVA_OPTS -jar app.jar SuccessExitStatus=143 Restart=always RestartSec=10 [Install] WantedBy=multi-user.targetУправление:
sudo systemctl start my-java-app. -
Интеграция в CI/CD пайплайн Все вышеперечисленные шаги автоматизируются в пайплайне (Jenkins, GitLab CI, GitHub Actions).
# Пример этапов в GitHub Actions jobs: build-and-deploy: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Set up JDK 17 uses: actions/setup-java@v3 with: distribution: 'temurin' java-version: '17' - name: Build with Maven run: mvn clean package - name: Build and push Docker image run: | docker build -t ${{ secrets.REGISTRY }}/app:${{ github.sha }} . docker push ${{ secrets.REGISTRY }}/app:${{ github.sha }} - name: Deploy to Kubernetes run: | kubectl set image deployment/java-app app=${{ secrets.REGISTRY }}/app:${{ github.sha }}
Главный тренд: Контейнеризация с последующим запуском в оркестраторе (Kubernetes) стала стандартом, так как обеспечивает неизменяемость, изоляцию, простое масштабирование и единый способ управления приложениями любого стека.