Стартиране на Spring Boot с PostgreSQL в Docker Compose

1. Въведение

В този урок искаме да стартираме приложение Spring Spring с популярната база данни с отворен код PostgreSQL. В предишна статия разгледахме Docker Compose за обработка на множество контейнери наведнъж . Така че вместо да инсталираме PostgreSQL като отделно приложение, ще използваме Docker Compose, за да стартираме Spring Boot и PostgreSQL .

2. Създаване на проект за пролетно стартиране

Нека да отидем до 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 Compose File

Сега нека напишем нашия 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). Зависи от услугата db (ред 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 Image за нашето приложение 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;

В Клиентът има генериран номер атрибут и две задължителни атрибути: FirstName и фамилия .

Сега можем да напишем интерфейса на хранилището за този обект :

public interface CustomerRepository extends JpaRepository { }

Като просто разширяваме JpaRepository , ние наследяваме методи за създаване и заявка на нашия обект на клиента .

И накрая, ще използваме тези методи в нашето приложение:

@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()); } }
  • Достъп до хранилището на нашите клиенти става чрез инжектиране на зависимости
  • Запитваме броя на съществуващите клиенти с хранилището - това ще бъде нула
  • След това създаваме и спасяваме клиент
  • When we then query the existing customers again, we expect to find the one we just created

7. Running with Docker Compose Again

To run the updated Spring Boot application, we need to rebuild it first. Therefore, we execute these commands once more in the project root directory:

./mvnw clean package -DskipTests cp target/docker-spring-boot-postgres-0.0.1-SNAPSHOT.jar src/main/docker

How do we rebuild our Docker image with this updated application JAR file? The best way is to remove the existing Docker image whose name we specified in the docker-compose.yml. This forces Docker to build the image again the next time we start our Docker Compose file:

cd src/main/docker docker-compose down docker rmi docker-spring-boot-postgres:latest docker-compose up

So after stopping our containers, we delete the application Docker image. We then start our Docker Compose file again, which rebuilds the application image.

Here's the application output:

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.