Деплой, профили и production-практики

Финальный шаг — вывести приложение в прод. Spring Boot собирается в один JAR, настраивается через окружение и удобно упаковывается в Docker.
Суть: соберите исполняемый JAR, конфигурируйте через переменные окружения и профили, упакуйте в контейнер. Прод требует осознанных настроек безопасности, логирования и наблюдаемости.

Приложение, которое работает на ноутбуке, и приложение в проде — это разные режимы одной программы. В проде другие базы, секреты, нагрузка и требования к надёжности. Spring Boot изначально спроектирован под облако, поэтому деплой обычно прост.

Сборка исполняемого JAR

# Собрать исполняемый "толстый" JAR (со встроенным сервером)
./mvnw clean package

# Запустить в проде
java -jar target/myapp-1.0.0.jar --spring.profiles.active=prod

Плагин spring-boot-maven-plugin собирает «fat JAR» — со всеми зависимостями и встроенным Tomcat. Никакого внешнего сервера приложений не нужно.

Конфигурация через окружение

Секреты и адреса в проде передают переменными окружения — они переопределяют значения из application.yml (вспомните урок про профили):

export SPRING_DATASOURCE_URL=jdbc:postgresql://db:5432/prod
export SPRING_DATASOURCE_PASSWORD=$DB_SECRET
export JWT_SECRET=$JWT_SECRET
java -jar app.jar --spring.profiles.active=prod

Упаковка в Docker

# Dockerfile (как docker-конфиг)
FROM eclipse-temurin:21-jre
WORKDIR /app
COPY target/myapp-1.0.0.jar app.jar
EXPOSE 8080
ENTRYPOINT ["java", "-jar", "app.jar"]

Образ на базе JRE 21 содержит JAR, открывает порт и запускает приложение. Дальше его деплоят в Kubernetes или любую облачную платформу.

Как работает под капотом

  Pipeline деплоя
   код -> ./mvnw package -> fat JAR (app.jar + Tomcat внутри)
        -> docker build -> образ
        -> docker push  -> реестр
        -> Kubernetes pull + run
              |
              +-- env: DATASOURCE_URL, JWT_SECRET (секреты извне)
              +-- profile: prod
              +-- /actuator/health -> проба готовности

Смоделируем выбор конфигурации по окружению и чек-лист готовности:

# Сборка эффективной конфигурации прода из окружения
import os

defaults = {"db_url": "jdbc:postgresql://localhost/dev", "log_level": "DEBUG"}
prod_env = {"db_url": "jdbc:postgresql://db/prod", "log_level": "INFO", "jwt_secret": "from-env"}

def build_config(profile, env):
    cfg = dict(defaults)
    if profile == "prod":
        cfg.update(env)               # окружение перекрывает дефолты
    return cfg

cfg = build_config("prod", prod_env)
print("Конфиг прода:", cfg)

# Чек-лист готовности к проду
checklist = {
    "секреты вынесены в env": "jwt_secret" in cfg,
    "лог-уровень не DEBUG": cfg["log_level"] != "DEBUG",
    "база не localhost": "localhost" not in cfg["db_url"],
}
print("Готов к проду?", all(checklist.values()))
for k, v in checklist.items():
    print(("OK " if v else "FAIL "), k)

Нажмите «Попробуй сам ▶»: прод-профиль перекрывает дефолты, а чек-лист проверяет готовность — секреты в env, лог-уровень и адрес базы.

Частые ошибки

  • Секреты в образе/гите. Пароли и ключи только через окружение или секрет-хранилища.
  • DEBUG-логи в проде. Замедляют и раздувают логи; используйте INFO/WARN.
  • ddl-auto=update в проде. Автоизменение схемы опасно — управляйте миграциями (Flyway/Liquibase).

Best practices

  • Собирайте один артефакт (JAR/образ), настраивайте окружением — «build once, run anywhere».
  • В проде: профиль prod, секреты из env, миграции через Flyway/Liquibase, Actuator-health для проб.
  • Включайте структурированное логирование и наблюдаемость (метрики, трассировку).

Итог: деплой Spring Boot — это один JAR со встроенным сервером, настраиваемый окружением и упакованный в Docker. Прод требует осознанных решений по секретам, логам, миграциям и наблюдаемости. На этом курс завершён — вы прошли путь от первого эндпоинта до production-приложения.

Закрепим главное

Деплой Spring Boot прост ровно настолько, насколько дисциплинированно вы отделили код от окружения. Один исполняемый JAR со встроенным сервером — это переносимый артефакт, который запускается одной командой где угодно: на сервере, в контейнере, в облаке. Упаковка в Docker добавляет воспроизводимость окружения, а оркестратор берёт на себя масштабирование и перезапуск.

Перед каждым выходом в прод полезно прогонять короткий чек-лист. Секреты вынесены в переменные окружения, а не зашиты в образ или конфиг под git. Активен профиль prod с боевыми настройками. Уровень логирования — INFO или WARN, а не DEBUG, иначе логи раздуются и замедлят систему. Схема базы управляется версионируемыми миграциями (Flyway или Liquibase), а не опасным ddl-auto=update. Эндпоинт /actuator/health открыт для проб готовности, но чувствительные эндпоинты Actuator защищены. Этот ритуал из пяти пунктов отсекает большинство типичных аварий первого релиза.

Проверьте себя
1. Почему секреты (пароли БД, JWT-ключ) в проде передают через переменные окружения, а не в application.yml под git?
AТак быстрее читается
BЧтобы не хранить секреты в репозитории и менять их без пересборки; env перекрывает значения из yml
Cyml не поддерживает пароли
DЭто требование Docker
2. Почему ddl-auto=update не рекомендуется в продакшене?
AОн слишком медленный
BАвтоматическое изменение схемы по сущностям опасно; в проде схемой управляют миграциями (Flyway/Liquibase)
CОн не работает с PostgreSQL
DОн удаляет таблицы при каждом старте