Running Spring Boot with PostgreSQL in Docker Compose

11 tháng 09, 2022 - 2497 lượt xem

Running Spring Boot with PostgreSQL in Docker Compose

Người dịch: Nguyễn Thành Trung - Học viên lớp Java08
Email liên hệ: nguyenthanhtrung.nlk58@gmail.com
Bài viết gốc: https://www.baeldung.com/spring-boot-postgresql-docker

1. Tổng quát

Trong hướng dẫn này, chúng ta sẽ chạy một ứng dụng Spring Boot với cơ sở dữ liệu nguồn mở phổ biến PostgreSQL. Trong bài viết trước, chúng ta đã xem xét Docker Compose để xử lý nhiều container cùng một lúc . Vì vậy, thay vì cài đặt PostgreSQL như một ứng dụng riêng biệt, chúng ta sẽ sử dụng Docker Compose để chạy Spring Boot và PostgreSQL .

2. Tạo dự án Spring Boot

Hãy vào Spring Initializer và tạo dự án Spring Boot của chúng ta . Chúng ta sẽ thêm các mô-đun PostgreSQL Driver và Spring Data JPA . Sau khi chúng ta tải xuống tệp ZIP kết quả và giải nén nó vào một thư mục, chúng ta có thể chạy ứng dụng mới của mình:

./mvnw spring-boot:run

Ứng dụng không thành công vì nó không thể kết nối với cơ sở dữ liệu:

***************************
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

Trước khi có thể khởi động PostgreSQL với Docker Compose, chúng ta cần biến ứng dụng Spring Boot của mình thành một Docker Image. Bước đầu tiên là đóng gói ứng dụng dưới dạng tệp JAR:

./mvnw clean package -DskipTests

Ở đây, trước tiên chúng ta dọn dẹp các bản dựng trước của mình trước khi đóng gói ứng dụng. Ngoài ra, chúng ta bỏ qua các bài kiểm tra vì chúng không thành công nếu không có PostgreSQL.

Bây giờ chúng ta có một tệp JAR ứng dụng trong thư mục đích . Tệp đó có tên dự án và số phiên bản trong tên của nó và kết thúc bằng -SNAPSHOT.jar . Vì vậy, tên của nó có thể là docker-spring-boot-postgres-0.0.1-SNAPSHOT.jar .

Hãy tạo thư mục src / main / docker mới . Sau đó, chúng ta sao chép tệp JAR của ứng dụng vào đó:

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

Cuối cùng, chúng ta tạo Dockerfile này trong cùng một thư mục:

FROM adoptopenjdk:11-jre-hotspot
ARG JAR_FILE=*.jar
COPY ${JAR_FILE} application.jar
ENTRYPOINT ["java", "-jar", "application.jar"]

Tệp này mô tả cách Docker chạy ứng dụng Spring Boot của chúng ta . Nó sử dụng Java 11 từ AdoptOpenJDK và sao chép tệp JAR của ứng dụng vào application.jar . Sau đó, nó chạy tệp JAR đó để khởi động ứng dụng Spring Boot của chúng ta.

4. Docker Compose File

Bây giờ chúng ta hãy viết tệp Docker Compose của chúng ta, docker-compos.yml và lưu nó trong 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

Tên ứng dụng của chúng ta là app. Nó là đầu tiên trong số hai services (dòng 4-15):

Spring Boot Docker image có tên là docker-spring-boot-postgres: new (dòng 5). Docker xây dựng image đó từ Dockerfile trong thư mục hiện tại (dòng 6-7)
Tên container là app (dòng 8). Nó phụ thuộc vào db service (dòng 10). Đó là lý do tại sao nó bắt đầu sau db container
Ứng dụng của chúng ta sử dụng vùng chứa db PostgreSQL làm nguồn dữ liệu (dòng 12). Tên cơ sở dữ liệu, tên người dùng và mật khẩu là tất cả compose-postgres (dòng 12-14)
Hibernate sẽ tự động tạo hoặc cập nhật bất kỳ bảng cơ sở dữ liệu nào cần thiết (dòng 15)
Cơ sở dữ liệu PostgreSQL có tên db và là service thứ 2 (dòng 17-22):

Chúng ta sử dụng PostgreSQL 13.1 (dòng 18)
Tên container là db (dòng 19)
Tên người dùng và mật khẩu đều là compose-postgres (dòng 21-22)

5. Chạy ứng dụng Docker Compose

Hãy chạy ứng dụng Spring Boot và PostgreSQL của chúng ta với Docker Compose :

docker-compose up

Đầu tiên, điều này sẽ xây dựng Docker Image cho ứng dụng Spring Boot của chúng ta. Tiếp theo, nó sẽ bắt đầu một container PostgreSQL. Cuối cùng, nó sẽ khởi chạy Docker Image ứng dụng của chúng ta. Lần này, ứng dụng của chúng ta chạy tốt:

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)

Như chúng ta có thể thấy, Spring Data không tìm thấy repository interface. Điều đó là chính xác - chúng ta chưa tạo một tài khoản!

Nếu chúng ta muốn dừng tất cả container, trước tiên chúng ta cần nhấn [Ctrl-C]. Sau đó, chúng ta có thể dừng Docker Compose:

docker-compose down

6. Tạo một Customer Entity and Repository

Để sử dụng cơ sở dữ liệu PostgreSQL trong ứng dụng của chúng ta, chúng ta sẽ tạo một customer entity đơn giản :

@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 có thuộc tính id được tạo và hai thuộc tính bắt buộc: firstName và lastName.

Bây giờ, chúng ta có thể viết repository interface cho entity này :

public interface CustomerRepository extends JpaRepository<Customer, Long> { }

Chỉ cần mở rộng JpaRepository , chúng ta kế thừa các phương thức để tạo và truy vấn Customer entity của chúng ta .

Cuối cùng, chúng ta sẽ sử dụng các phương thức này trong ứng dụng của mình:

@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());
    }
}
  • Chúng ta truy cập Customer repository của mình thông qua dependency injection
  • Chúng ta truy vấn số lượng customer hiện tại với repository - con số này sẽ bằng 0
  • Sau đó, chúng ta tạo và lưu một customer
  • Sau đó, khi chúng ta truy vấn lại các customer hiện tại, chúng ta hy vọng sẽ tìm thấy customer mà chúng ta vừa tạo.

7. Chạy lại ứng dụng với Docker Compose

Để chạy ứng dụng Spring Boot đã cập nhật, trước tiên chúng ta cần xây dựng lại nó. Do đó, chúng ta thực hiện các lệnh này một lần nữa trong thư mục gốc của dự án:

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

Làm cách nào để chúng ta xây dựng lại Docker Image của mình với tệp JAR ứng dụng được cập nhật này? Cách tốt nhất là xóa Docker Image hiện có có tên mà chúng ta đã chỉ định trong docker-compost.yml . Điều này buộc Docker phải xây dựng lại Image vào lần tiếp theo chúng ta khởi động tệp Docker Compose:

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

Vì vậy, sau khi dừng các container của chúng ta, chúng ta xóa Docker image của ứng dụng. Sau đó, chúng ta bắt đầu lại tệp Docker Compose, tệp này sẽ xây dựng lại Image ứng dụng.

Đây là đầu ra của ứng dụng:

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 tìm thấy customer repository trống của chúng ta. Do đó, chúng ta lúc đầu không có customer nhưng sau đó tạo thành công một customer.

8. Kết luận

Trong hướng dẫn ngắn này, chúng ta đã bắt đầu bằng cách tạo một ứng dụng Spring Boot cho PostgreSQL. Tiếp theo, chúng ta đã viết tệp Docker Compose để chạy container ứng dụng của chúng ta với container PostgreSQL.

Cuối cùng, chúng ta đã tạo một customer entity và repository, cho phép chúng ta lưu một customer vào PostgreSQL.

Bình luận

avatar
Trịnh Minh Cường 2022-09-11 09:07:14.583209 +0000 UTC

Bài này hay quá.

Avatar
* Vui lòng trước khi bình luận.
Ảnh đại diện
  +1 Thích
+1