1. Введение
В этом руководстве мы хотим запустить приложение Spring Boot с популярной базой данных с открытым исходным кодом PostgreSQL. В предыдущей статье мы рассматривали Docker Compose для одновременной обработки нескольких контейнеров . Поэтому вместо того, чтобы устанавливать PostgreSQL как отдельное приложение, мы будем использовать Docker Compose для запуска Spring Boot и PostgreSQL .
2. Создание проекта Spring Boot
Перейдем к Spring Initializer и создадим наш проект Spring Boot . Мы добавим модули PostgreSQL Driver
и Spring Data JPA .
После того, как мы загрузим полученный ZIP-файл и распакуем его в папку, мы можем запустить наше новое приложение:
./mvnw spring-boot:run
Приложение не работает, потому что не может подключиться к базе данных:
***************************
APPLICATION FAILED TO START
***************************
Description:
Failed to configure a DataSource: 'url' attribute is not specified and no embedded datasource could be configured.
Reason: Failed to determine a suitable driver class
3. Докерфайл
Прежде чем мы сможем запустить PostgreSQL с Docker Compose, нам нужно превратить наше приложение Spring Boot в образ Docker . Первый шаг — упаковать приложение в виде файла JAR:
./mvnw clean package -DskipTests
Здесь мы сначала очищаем наши предыдущие сборки перед упаковкой приложения. Кроме того, мы пропускаем тесты, потому что они не работают без PostgreSQL.
Теперь у нас есть JAR-файл приложения в целевом
каталоге. Этот файл имеет имя проекта и номер версии в своем имени и заканчивается на -SNAPSHOT.jar
. Таким образом, его имя может быть docker-spring-boot-postgres-0.0.1-SNAPSHOT.jar
.
Давайте создадим новый каталог src/main/docker
. После этого копируем туда JAR-файл приложения:
cp target/docker-spring-boot-postgres-0.0.1-SNAPSHOT.jar src/main/docker
Наконец, мы создаем этот Dockerfile
в том же каталоге:
FROM adoptopenjdk:11-jre-hotspot
ARG JAR_FILE=*.jar
COPY ${JAR_FILE} application.jar
ENTRYPOINT ["java", "-jar", "application.jar"]
Этот файл описывает, как Docker должен запускать наше приложение Spring Boot . Он использует Java 11 от AdoptOpenJDK и копирует JAR-файл приложения в application.jar
. Затем он запускает этот JAR-файл, чтобы запустить наше приложение Spring Boot.
4. Файл компоновки Docker
Теперь давайте напишем наш файл Docker Compose, docker-compose.yml
, и сохраним его в src/main/docker
:
version: '2'
services:
app:
image: 'docker-spring-boot-postgres:latest'
build:
context: .
container_name: app
depends_on:
- db
environment:
- SPRING_DATASOURCE_URL=jdbc:postgresql://db:5432/compose-postgres
- SPRING_DATASOURCE_USERNAME=compose-postgres
- SPRING_DATASOURCE_PASSWORD=compose-postgres
- SPRING_JPA_HIBERNATE_DDL_AUTO=update
db:
image: 'postgres:13.1-alpine'
container_name: db
environment:
- POSTGRES_USER=compose-postgres
- POSTGRES_PASSWORD=compose-postgres
Наше приложение называется app.
Это первая из двух служб (строки 4-15):
- Образ Spring Boot Docker имеет имя
docker-spring-boot-postgres:latest
(строка 5). Docker создает этот образ изфайла Dockerfile
в текущем каталоге (строки 6–7) . - Имя контейнера —
app
(строка 8). Это зависит от службыБД
(строка 10). Вот почему он начинается после контейнераdb
- Наше приложение использует контейнер
db
PostgreSQL в качестве источника данных (строка 12). Имя базы данных, имя пользователя и пароль — всеcompose-postgres
(строки 12-14) . - Hibernate автоматически создаст или обновит все необходимые таблицы базы данных (строка 15).
База данных PostgreSQL имеет имя db
и является вторым сервисом (строки 17-22):
- Мы используем PostgreSQL 13.1 (строка 18)
- Имя контейнера —
db
(строка 19) . - Имя пользователя и пароль —
compose-postgres
(строки 21-22) .
5. Работа с Docker Compose
Давайте запустим наше приложение Spring Boot и PostgreSQL с помощью Docker Compose :
docker-compose up
Во-первых, это создаст образ Docker для нашего приложения Spring Boot. Затем он запустит контейнер PostgreSQL. Наконец, он запустит образ Docker нашего приложения. На этот раз наше приложение работает нормально:
Starting DemoApplication v0.0.1-SNAPSHOT using Java 11.0.9 on f94e79a2c9fc with PID 1 (/application.jar started by root in /)
[...]
Finished Spring Data repository scanning in 28 ms. Found 0 JPA repository interfaces.
[...]
Started DemoApplication in 4.751 seconds (JVM running for 6.512)
Как мы видим, Spring Data не нашел интерфейса репозитория. Это верно – мы еще не создали его!
Если мы хотим остановить все контейнеры, нам нужно сначала нажать [Ctrl-C]. Затем мы можем остановить Docker Compose:
docker-compose down
6. Создание объекта клиента и репозитория
Чтобы использовать базу данных PostgreSQL в нашем приложении, мы создадим простую сущность клиента :
@Entity
@Table(name = "customer")
public class Customer {
@Id
@GeneratedValue
private long id;
@Column(name = "first_name", nullable = false)
private String firstName;
@Column(name = "last_name", nullable = false)
private String lastName;
У клиента
есть сгенерированный атрибут id
и два обязательных атрибута: firstName
и lastName
.
Теперь мы можем написать интерфейс репозитория для этой сущности :
public interface CustomerRepository extends JpaRepository<Customer, Long> { }
Просто расширяя JpaRepository
, мы наследуем методы для создания и запроса нашей сущности Customer .
Наконец, мы будем использовать эти методы в нашем приложении:
@SpringBootApplication
public class DemoApplication {
@Autowired
private CustomerRepository repository;
@EventListener(ApplicationReadyEvent.class)
public void runAfterStartup() {
List allCustomers = this.repository.findAll();
logger.info("Number of customers: " + allCustomers.size());
Customer newCustomer = new Customer();
newCustomer.setFirstName("John");
newCustomer.setLastName("Doe");
logger.info("Saving new customer...");
this.repository.save(newCustomer);
allCustomers = this.repository.findAll();
logger.info("Number of customers: " + allCustomers.size());
}
}
- Мы получаем доступ к нашему репозиторию
клиентов
через внедрение зависимостей - Запрашиваем количество существующих клиентов с репозиторием — это будет ноль
- Затем мы создаем и сохраняем клиента
- Когда мы снова запрашиваем существующих клиентов, мы ожидаем найти только что созданного.
7. Запуск с Docker Compose снова
Чтобы запустить обновленное приложение Spring Boot, нам нужно сначала его пересобрать. Поэтому мы еще раз выполняем эти команды в корневом каталоге проекта:
./mvnw clean package -DskipTests
cp target/docker-spring-boot-postgres-0.0.1-SNAPSHOT.jar src/main/docker
Как нам восстановить наш образ Docker с помощью этого обновленного JAR-файла приложения? Лучший способ — удалить существующий образ Docker, имя которого мы указали в файле docker-compose.yml
. Это заставляет Docker снова собрать образ при следующем запуске нашего файла Docker Compose:
cd src/main/docker
docker-compose down
docker rmi docker-spring-boot-postgres:latest
docker-compose up
Итак, после остановки наших контейнеров мы удаляем Docker-образ приложения. Затем мы снова запускаем наш файл Docker Compose, который перестраивает образ приложения.
Вот вывод приложения:
Finished Spring Data repository scanning in 180 ms. Found 1 JPA repository interfaces.
[...]
Number of customers: 0
Saving new customer...
Number of customers: 1
Spring Boot находит наш пустой репозиторий клиентов. Поэтому мы начинаем без клиента, но затем успешно создаем его.
8. Заключение
В этом кратком руководстве мы начали с создания приложения Spring Boot для PostgreSQL. Затем мы написали файл Docker Compose для запуска контейнера нашего приложения с контейнером PostgreSQL.
Наконец, мы создали объект клиента и репозиторий, что позволило нам сохранить клиента в PostgreSQL.
Как обычно, исходный код этого руководства можно найти на GitHub .