# Bài 18: Spring Boot với Docker

### 1\. Giới thiệu về Docker

**Docker** là một nền tảng phần mềm cho phép bạn tạo, triển khai và chạy các ứng dụng bên trong các container. Container là các đơn vị phần mềm nhỏ gọn, chứa đựng tất cả các thành phần cần thiết để chạy ứng dụng, bao gồm mã nguồn, thư viện, và các cấu hình hệ thống. Docker giúp đảm bảo rằng ứng dụng của bạn sẽ chạy nhất quán trên mọi môi trường, từ máy phát triển cá nhân đến các máy chủ sản xuất.

### 2\. Lợi ích của Docker

* **Nhất quán**: Đảm bảo ứng dụng chạy nhất quán trên các môi trường khác nhau.
    
* **Di động**: Dễ dàng chuyển đổi và triển khai ứng dụng trên các nền tảng khác nhau.
    
* **Tách biệt**: Mỗi container chạy trong một môi trường tách biệt, giúp tránh xung đột giữa các ứng dụng.
    
* **Nhẹ**: Container nhẹ hơn nhiều so với các máy ảo (VM).
    

### 3\. Cách tích hợp Docker vào dự án Spring Boot

#### 3.1. Tạo file Dockerfile

Dockerfile là một file văn bản chứa các lệnh để xây dựng một image Docker. Dưới đây là một ví dụ về Dockerfile cho ứng dụng Spring Boot.

```Dockerfile
# Sử dụng image chính thức của OpenJDK làm base image
FROM openjdk:11-jre-slim

# Đặt thư mục làm việc trong container
WORKDIR /app

# Sao chép file JAR của ứng dụng vào container
COPY target/myapp.jar /app/myapp.jar

# Expose cổng mà ứng dụng sẽ chạy
EXPOSE 8080

# Lệnh để chạy ứng dụng
ENTRYPOINT ["java", "-jar", "myapp.jar"]
```

#### 3.2. Tạo file JAR của ứng dụng

Đảm bảo rằng bạn đã xây dựng ứng dụng Spring Boot của mình và tạo ra file JAR. Bạn có thể làm điều này bằng cách sử dụng Maven hoặc Gradle.

**Ví dụ với Maven**:

```bash
mvn clean package
```

File JAR sẽ được tạo trong thư mục `target`.

#### 3.3. Xây dựng image Docker

Sử dụng lệnh `docker build` để xây dựng image Docker từ Dockerfile.

```bash
docker build -t myapp:latest .
```

Lệnh này sẽ tạo ra một image Docker mới với tên `myapp` và tag `latest`.

#### 3.4. Chạy container từ image Docker

Sử dụng lệnh `docker run` để chạy container từ image Docker vừa tạo.

```bash
docker run -p 8080:8080 myapp:latest
```

Lệnh này sẽ chạy container và map cổng 8080 của container với cổng 8080 của máy chủ.

### 4\. Sử dụng Docker Compose

**Docker Compose** là một công cụ để định nghĩa và chạy các ứng dụng Docker đa container. Bạn có thể sử dụng Docker Compose để quản lý các dịch vụ phụ thuộc, như cơ sở dữ liệu, message broker, v.v.

#### 4.1. Tạo file docker-compose.yml

Dưới đây là một ví dụ về file `docker-compose.yml` để chạy ứng dụng Spring Boot cùng với một cơ sở dữ liệu MySQL.

```yaml
version: '3.8'
services:
  myapp:
    image: myapp:latest
    build: .
    ports:
      - "8080:8080"
    environment:
      SPRING_DATASOURCE_URL: jdbc:mysql://mysql:3306/mydb
      SPRING_DATASOURCE_USERNAME: root
      SPRING_DATASOURCE_PASSWORD: root
    depends_on:
      - mysql

  mysql:
    image: mysql:8.0
    environment:
      MYSQL_ROOT_PASSWORD: root
      MYSQL_DATABASE: mydb
    ports:
      - "3306:3306"
```

#### 4.2. Chạy Docker Compose

Sử dụng lệnh `docker-compose up` để chạy các dịch vụ được định nghĩa trong file `docker-compose.yml`.

```bash
docker-compose up
```

Lệnh này sẽ xây dựng và chạy các container được định nghĩa trong file `docker-compose.yml`.

### 5\. Ví dụ chi tiết

Dưới đây là một ví dụ chi tiết từ đầu đến cuối về việc tích hợp Docker vào dự án Spring Boot.

#### 5.1. Tạo dự án Spring Boot

Sử dụng Spring Initializr để tạo dự án với các dependency sau:

* Spring Web
    
* Spring Data JPA
    
* MySQL Driver
    

#### 5.2. Cấu trúc dự án

```plaintext
myapp
|-- src
|   |-- main
|   |   |-- java
|   |   |   `-- com
|   |   |       `-- example
|   |   |           `-- myapp
|   |   |               |-- MySpringBootApplication.java
|   |   |               |-- entity
|   |   |               |   `-- User.java
|   |   |               |-- repository
|   |   |               |   `-- UserRepository.java
|   |   |               `-- controller
|   |   |                   `-- UserController.java
|   |   `-- resources
|   |       `-- application.properties
|-- Dockerfile
|-- docker-compose.yml
|-- pom.xml
```

#### 5.3. Tạo Dockerfile

Tạo file `Dockerfile` trong thư mục gốc của dự án.

**Dockerfile**:

```Dockerfile
# Sử dụng image chính thức của OpenJDK làm base image
FROM openjdk:11-jre-slim

# Đặt thư mục làm việc trong container
WORKDIR /app

# Sao chép file JAR của ứng dụng vào container
COPY target/myapp.jar /app/myapp.jar

# Expose cổng mà ứng dụng sẽ chạy
EXPOSE 8080

# Lệnh để chạy ứng dụng
ENTRYPOINT ["java", "-jar", "myapp.jar"]
```

#### 5.4. Cấu hình ứng dụng Spring Boot

Cấu hình kết nối cơ sở dữ liệu trong file [`application.properties`](http://application.properties).

```plaintext
spring.datasource.url=jdbc:mysql://localhost:3306/mydb
spring.datasource.username=root
spring.datasource.password=root
spring.jpa.hibernate.ddl-auto=update
```

#### 5.5. Tạo file docker-compose.yml

Tạo file `docker-compose.yml` trong thư mục gốc của dự án.

**docker-compose.yml**:

```yaml
version: '3.8'
services:
  myapp:
    image: myapp:latest
    build: .
    ports:
      - "8080:8080"
    environment:
      SPRING_DATASOURCE_URL: jdbc:mysql://mysql:3306/mydb
      SPRING_DATASOURCE_USERNAME: root
      SPRING_DATASOURCE_PASSWORD: root
    depends_on:
      - mysql

  mysql:
    image: mysql:8.0
    environment:
      MYSQL_ROOT_PASSWORD: root
      MYSQL_DATABASE: mydb
    ports:
      - "3306:3306"
```

#### 5.6. Xây dựng và chạy ứng dụng

Sử dụng Docker Compose để xây dựng và chạy các dịch vụ.

```bash
docker-compose up --build
```

### 6\. Kết luận

Trong bài viết này, chúng ta đã tìm hiểu về cách tích hợp Docker vào dự án Spring Boot, từ việc tạo Dockerfile đến sử dụng Docker Compose để quản lý các dịch vụ phụ thuộc. Docker giúp đảm bảo rằng ứng dụng của bạn sẽ chạy nhất quán trên mọi môi trường, đồng thời cung cấp các công cụ mạnh mẽ để quản lý và triển khai ứng dụng một cách hiệu quả.

Trong bài viết tiếp theo, chúng ta sẽ tìm hiểu về cách tích hợp Spring Boot với Kubernetes để triển khai và quản lý các ứng dụng trong môi trường container hóa.
