1. Giới thiệu

Mục tiêu

Trong bài viết này, chúng ta sẽ tìm hiểu cách triển khai một ứng dụng Spring Boot sử dụng Docker Compose. Ứng dụng của chúng ta sẽ bao gồm việc kết nối với cơ sở dữ liệu MySQL thông qua JPA và sử dụng Maildev để gửi email. Chúng ta cũng sẽ tìm hiểu cách truyền biến môi trường từ Docker Compose vào tệp application.properties để quản lý cấu hình một cách linh hoạt.

Lợi ích của việc sử dụng Docker Compose

  • Đơn giản hóa triển khai: Docker Compose cho phép bạn định nghĩa và triển khai một ứng dụng bằng cách sử dụng các container. Điều này giúp đơn giản hóa quá trình triển khai và đảm bảo tính nhất quán giữa các môi trường khác nhau.

  • Phân tách dịch vụ: Bằng cách sử dụng Docker Compose, bạn có thể phân tách các phần khác nhau của ứng dụng thành các dịch vụ độc lập. Trong trường hợp này, chúng ta có các dịch vụ MySQL, Maildev và ứng dụng Spring Boot riêng biệt.

  • Quản lý cấu hình linh hoạt: Docker Compose cho phép bạn quản lý biến môi trường và cấu hình ứng dụng dễ dàng. Bạn có thể thay đổi cấu hình của từng dịch vụ một và áp dụng các biến môi trường để tùy chỉnh hành vi của chúng.

Tổng quan về ứng dụng và các dịch vụ

Ứng dụng của chúng ta là một ứng dụng Spring Boot đơn giản quản lý thông tin về sản phẩm. Chúng ta sẽ sử dụng JPA để kết nối với cơ sở dữ liệu MySQL và Maildev để gửi email mà không cần thiết lập một máy chủ thư điện tử thực tế.

2. Chuẩn bị môi trường

Cài đặt Docker và Docker Compose

Trước khi bắt đầu, bạn cần cài đặt Docker và Docker Compose. Bạn có thể tìm hiểu cách cài đặt chúng trên trang web chính thức của Docker.

  • Hãy cài đặt Docker bằng cách làm theo hướng dẫn tại đây.
  • Hãy cài đặt Docker Compose theo hướng dẫn tại đây.

Tạo một dự án Spring Boot

Bước đầu tiên là tạo một dự án Spring Boot đơn giản. Bạn có thể sử dụng Spring Initializr hoặc IDE của bạn để làm điều này. Đảm bảo rằng bạn đã bao gồm các dependence trong dự án của mình:

  • Spring Web
  • Spring Data JPA
  • MySQL Driver
  • Java Mail Sender

3. Triển khai ứng dụng Spring Boot với Docker Compose

Cấu hình Docker Compose

Chúng ta sẽ bắt đầu bằng việc định nghĩa cấu hình trong tệp docker-compose.yml. Trong tệp này, chúng ta sẽ định nghĩa 3 service chính:

  1. MySQL: Dịch vụ cơ sở dữ liệu MySQL.
  2. Maildev: Dịch vụ Maildev để kiểm tra và hiển thị email gửi từ ứng dụng.
  3. Spring Boot App: Dịch vụ chạy ứng dụng Spring Boot của chúng ta.

Dưới đây là nội dung của tệp docker-compose.yml:

version: '3'

services:
  mysql:
    image: mysql:latest
    restart: always
    environment:
      MYSQL_ROOT_PASSWORD: 123
    ports:
      - "3306:3306"

  maildev:
    image: maildev/maildev
    restart: always
    ports:
      - "1080:1080"
      - "1025:1025"

  spring-app:
    build:
      context: .
      dockerfile: Dockerfile
    depends_on:
      - mysql
      - maildev
    restart: always
    ports:
      - "8080:8080"
    environment:
      - SPRING_MAIL_HOST=maildev
      - SPRING_MAIL_PORT=1025
      - SPRING_MAIL_USERNAME=hien789@gmail.com
      - SPRING_MAIL_PASSWORD=123
      - SPRING_DATASOURCE_URL=jdbc:mysql://mysql:3306/db-example?createDatabaseIfNotExist=true
      - SPRING_DATASOURCE_USERNAME=root
      - SPRING_DATASOURCE_PASSWORD=123
    # Đặt biến môi trường dựa trên môi trường Docker

Trong phần này, chúng ta đã định nghĩa biến môi trường cho MySQL, Maildev và ứng dụng Spring Boot. Lưu ý cách chúng ta sử dụng biến môi trường với các giá trị mặc định để đảm bảo tính linh hoạt khi triển khai.

Tạo tệp Dockerfile cho ứng dụng Spring Boot

Tiếp theo, chúng ta cần tạo một tệp Dockerfile để xây dựng ứng dụng Spring Boot và đóng gói nó vào một hình ảnh Docker. Dưới đây là một tệp Dockerfile đơn giản:

# Base image được sử dụng để build image
FROM --platform=amd64 openjdk:17.0.2-oraclelinux8

# Thông tin tác giả
LABEL authors="buihien"

# Set working directory trong container
WORKDIR /app

# Copy file JAR được build từ ứng dụng Spring Boot vào working directory trong container 
COPY target/app.jar app.jar

# Expose port của ứng dụng
EXPOSE 8080

# Chỉ định command để chạy ứng dụng khi container khởi chạy
CMD ["java", "-jar", "app.jar"]

Trong tệp Dockerfile này:

  • Chúng ta sử dụng một Docker image chứa OpenJDK 17 làm base image.
  • Chúng ta đặt thư mục làm việc là /app trong container.
  • Chúng ta sao chép tệp JAR được tạo bởi ứng dụng Spring Boot vào thư mục làm việc trong container.
  • Chúng ta mở cổng 8080 để cho phép kết nối vào ứng dụng.
  • Cuối cùng, chúng ta đặt lệnh để chạy ứng dụng Spring Boot khi container khởi chạy.

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

Bây giờ, chúng ta có thể triển khai ứng dụng bằng cách chạy Docker Compose với lệnh sau:

docker-compose up -d

Docker Compose sẽ bắt đầu tạo ra 3 service: MySQL, Maildevứng dụng Spring Boot của chúng ta. Ứng dụng của bạn sẽ sử dụng các biến môi trường được định nghĩa trong docker-compose.yml để cấu hình cơ sở dữ liệu và gửi email thông qua Maildev.

Kết quả sau khi chạy Docker Compose

kết quả chạy docker compose

4. Truyền tham số từ Docker Compose vào ứng dụng Spring Boot

Chúng ta đã sử dụng các placeholder trong tệp application.properties của ứng dụng Spring Boot để đại diện cho các biến môi trường mà chúng ta muốn truyền từ Docker Compose. Điều này cho phép chúng ta định nghĩa các giá trị mặc định và linh hoạt cấu hình ứng dụng.

Chúng ta đã đảm bảo rằng các biến môi trường đã được định nghĩa trong docker-compose.yml trùng khớp với các placeholder trong application.properties. Điều này giúp chúng ta duy trì tính nhất quán trong cấu hình giữa các môi trường khác nhau.

Spring Boot sẽ tự động đọc các giá trị biến môi trường từ tệp application.properties. Khi bạn chạy ứng dụng bằng Docker Compose, các biến môi trường được truyền từ docker-compose.yml sẽ được sử dụng cho cấu hình cơ sở dữ liệu và gửi email.

# Mail configuration
spring.mail.host=${SPRING_MAIL_HOST:localhost}
spring.mail.port=${SPRING_MAIL_PORT:1025}
spring.mail.username=${SPRING_MAIL_USERNAME:hien123@gmail.com}
spring.mail.password=${SPRING_MAIL_PASSWORD:123}
spring.mail.properties.mail.smtp.ssl.trust=*
spring.mail.properties.mail.smtp.auth=true
spring.mail.properties.mail.smtp.starttls.enable=true
spring.mail.properties.mail.smtp.connectiontimeout=5000
spring.mail.properties.mail.smtp.timeout=3000
spring.mail.properties.mail.smtp.writetimeout=5000

# Database configuration
spring.datasource.url=${SPRING_DATASOURCE_URL:jdbc:mysql://localhost:3306/db-example?createDatabaseIfNotExist=true}
spring.datasource.username=${SPRING_DATASOURCE_USERNAME:root}
spring.datasource.password=${SPRING_DATASOURCE_PASSWORD:123}

spring.jpa.show-sql=true
spring.jpa.hibernate.ddl-auto=update
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQLDialect

5. Kiểm tra

Đảm bảo rằng biến môi trường được truyền đúng cách

Kiểm tra rằng các biến môi trường đã được truyền từ Docker Compose vào ứng dụng Spring Boot và ứng dụng đang sử dụng chúng để cấu hình cơ sở dữ liệu và gửi email.

Kiểm tra ứng dụng Spring Boot

Mở trình duyệt và truy cập ứng dụng của bạn tại http://localhost:8080/api/products. Kiểm tra xem ứng dụng có thể thực hiện các thao tác CRUD trên dữ liệu sản phẩm không.

get all product

Kiểm tra gửi email bằng Maildev

Mở trình duyệt và truy cập Maildev tại http://localhost:1080. Kiểm tra xem email đã được gửi từ ứng dụng của bạn có hiển thị đúng không.

send mail

6. Kết luận

Tổng kết bài viết

Chúng ta đã học cách triển khai ứng dụng Spring Boot sử dụng Docker Compose với JPA, MySQL và Maildev. Chúng ta cũng thảo luận về cách truyền biến môi trường từ Docker Compose vào tệp application.properties để quản lý cấu hình một cách linh hoạt trên nhiều môi trường khác nhau.

Lợi ích của việc triển khai ứng dụng Spring Boot với Docker Compose

  • Dễ dàng quản lý và triển khai ứng dụng trong môi trường Docker.
  • Tích hợp dịch vụ cơ sở dữ liệu và email một cách dễ dàng.
  • Linh hoạt cấu hình ứng dụng dựa trên biến môi trường.

Source code tham khảo : https://github.com/buihien0109/springboot-course/tree/main/demo-dockerize-sb-app