Деплой Java приложения на VPS: продвинутый уровень с CI/CD

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

Деплой Java приложения на VPS: продвинутый уровень с CI/CD, Docker и SSL

В этой статье мы рассмотрим продвинутый процесс деплоя Java-приложения на VPS (Virtual Private Server). Мы не будем останавливаться на базовых шагах вроде установки JDK или запуска JAR-файла. Вместо этого сфокусируемся на настройке CI/CD пайплайна, контейнеризации с Docker, использовании Nginx в качестве обратного прокси, автоматическом получении SSL-сертификатов, а также на мониторинге и отказоустойчивости приложения.

Предполагается, что у вас уже есть VPS с Ubuntu 22.04 LTS, базовый домен, и вы знакомы с командной строкой Linux. Все примеры кода написаны на Java 17+ с использованием Spring Boot, но принципы применимы к любому Java-фреймворку.

1. Контейнеризация Java-приложения с Docker

Первый шаг к продвинутому деплою — упаковка приложения в Docker-контейнер. Это обеспечивает воспроизводимость окружения и упрощает развертывание.

Создайте Dockerfile в корне проекта:

# Используем multi-stage build для уменьшения размера финального образа
FROM maven:3.9.6-eclipse-temurin-17 AS builder
WORKDIR /app
COPY pom.xml .
RUN mvn dependency:go-offline
COPY src ./src
RUN mvn clean package -DskipTests

FROM eclipse-temurin:17-jre-alpine
WORKDIR /app
COPY --from=builder /app/target/*.jar app.jar
EXPOSE 8080
ENTRYPOINT ["java", "-jar", "app.jar"]

Файл docker-compose.yml для запуска с базой данных:

version: '3.8'
services:
  app:
    build: .
    ports:
      - "8080:8080"
    environment:
      - SPRING_DATASOURCE_URL=jdbc:postgresql://db:5432/mydb
      - SPRING_DATASOURCE_USERNAME=user
      - SPRING_DATASOURCE_PASSWORD=pass
    depends_on:
      - db
    restart: unless-stopped

  db:
    image: postgres:15-alpine
    environment:
      POSTGRES_DB: mydb
      POSTGRES_USER: user
      POSTGRES_PASSWORD: pass
    volumes:
      - pgdata:/var/lib/postgresql/data
    restart: unless-stopped

volumes:
  pgdata:

После сборки образа командой docker compose build вы получите готовый к деплою контейнер.

2. Настройка CI/CD пайплайна (GitHub Actions)

Автоматизация деплоя — ключевой элемент продвинутого уровня. Используем GitHub Actions для сборки, тестирования и отправки образа на сервер.

Создайте файл .github/workflows/deploy.yml:

name: Deploy Java App to VPS

on:
  push:
    branches: [ main ]

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

      - name: Set up JDK 17
        uses: actions/setup-java@v4
        with:
          java-version: '17'
          distribution: 'temurin'

      - name: Build with Maven
        run: mvn clean package

      - name: Build Docker image
        run: docker build -t myapp:latest .

      - name: Save Docker image to tar
        run: docker save myapp:latest | gzip > myapp.tar.gz

      - name: Copy image to VPS via SCP
        uses: appleboy/scp-action@v0.1.7
        with:
          host: ${{ secrets.VPS_HOST }}
          username: ${{ secrets.VPS_USER }}
          key: ${{ secrets.VPS_SSH_KEY }}
          source: "myapp.tar.gz"
          target: "/opt/app/"

      - name: Deploy on VPS
        uses: appleboy/ssh-action@v1.0.3
        with:
          host: ${{ secrets.VPS_HOST }}
          username: ${{ secrets.VPS_USER }}
          key: ${{ secrets.VPS_SSH_KEY }}
          script: |
            cd /opt/app
            docker load < myapp.tar.gz
            docker compose down
            docker compose up -d
            rm myapp.tar.gz

Не забудьте добавить секреты VPS_HOST, VPS_USER, VPS_SSH_KEY в настройках репозитория GitHub. Теперь каждый пуш в ветку main будет автоматически деплоить новую версию приложения.

3. Настройка Nginx как обратного прокси и SSL

Для продакшн-среды необходимо скрыть внутренний порт 8080 и настроить HTTPS. Используем Nginx с Let's Encrypt.

Конфигурация Nginx (/etc/nginx/sites-available/myapp):

server {
    listen 80;
    server_name example.com www.example.com;
    return 301 https://$server_name$request_uri;
}

server {
    listen 443 ssl http2;
    server_name example.com www.example.com;

    ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;

    location / {
        proxy_pass http://127.0.0.1:8080;
        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;
        proxy_read_timeout 90;
    }

    location /actuator/health {
        access_log off;
        return 200 "OK";
        add_header Content-Type text/plain;
    }
}

Автоматическое получение SSL-сертификата с Certbot:

sudo apt update
sudo apt install certbot python3-certbot-nginx -y
sudo certbot --nginx -d example.com -d www.example.com

Certbot автоматически обновит конфигурацию Nginx и настроит автоматическое обновление сертификатов каждые 90 дней.

4. Мониторинг и отказоустойчивость

Продвинутый деплой невозможен без мониторинга. Добавим Spring Boot Actuator и Prometheus.

Добавьте зависимости в pom.xml:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
    <groupId>io.micrometer</groupId>
    <artifactId>micrometer-registry-prometheus</artifactId>
</dependency>

Блоги

Рекомендаций по книгам