在Docker Compose中使用PostgreSQL運行Spring Boot

1.簡介

在本教程中,我們想使用流行的開源數據庫PostgreSQL運行Spring Boot應用程序。在上一篇文章中,我們研究了Docker Compose一次處理多個容器因此,我們將使用Docker Compose來運行Spring Boot和PostgreSQL ,而不是將PostgreSQL作為單獨的應用程序安裝。

2.創建Spring Boot項目

讓我們轉到Spring Initializer並創建我們的Spring Boot項目。我們將添加PostgreSQL DriverSpring 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. Dockerfile

在使用Docker Compose啟動PostgreSQL之前,我們需要將Spring Boot應用程序轉換為Docker映像。第一步是將應用程序打包為JAR文件:

./mvnw clean package -DskipTests

在這裡,在打包應用程序之前,我們首先清理以前的版本。另外,我們跳過了測試,因為它們在沒有PostgreSQL的情況下失敗了。

target目錄中有一個應用程序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應用程序它使用AdoptOpenJDK中的Java 11,並將應用程序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行)。 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運行

讓我們使用Docker Compose運行我們的Spring Boot應用程序和PostgreSQL

docker-compose up

首先,這將為我們的Spring Boot應用程序構建Docker映像。接下來,它將啟動一個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;

Customer具有一個生成的id屬性和兩個必需屬性: firstNamelastName

現在,我們可以為該實體編寫存儲庫接口

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());

 }

 }
  • 我們通過依賴注入訪問我們的Customer
  • 我們使用存儲庫查詢現有客戶的數量-這將為零
  • 然後我們創建並保存客戶
  • 當我們再次查詢現有客戶時,我們希望找到剛才創建的客戶

7.再次運行Docker Compose

要運行更新的Spring Boot應用程序,我們需要首先對其進行重建。因此,我們在項目根目錄中再次執行以下命令:

./mvnw clean package -DskipTests

 cp target/docker-spring-boot-postgres-0.0.1-SNAPSHOT.jar src/main/docker

我們如何使用此更新的應用程序JAR文件重建Docker映像?最好的方法是刪除現有的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.結論

在這個簡短的教程中,我們首先為PostgreSQL創建一個Spring Boot應用程序。接下來,我們編寫了一個Docker Compose文件,以將我們的應用程序容器與PostgreSQL容器一起運行。

最後,我們創建了一個客戶實體和存儲庫,這使我們可以將客戶保存到PostgreSQL。