
이전에는 Docker를 사용해서 Spring Boot를 컨테이너에 빌드시켜 실행까지 했었는데요.
이번에는 Spring Boot의 MySQL을 연동시켜 간단하게 게시글 제목만 작성해보는 프로젝트를 진행해보았습니다.
├─java
│ └─com
│ └─example
│ └─docker_test
│ │ DockerTestApplication.java
│ │
│ ├─controller
│ │ HomeController.java
│ │
│ ├─entity
│ │ Contents.java
│ │
│ └─repository
│ ContentsRepository.java
│
└─resources
│ application.properties
│
├─static
└─templates
└─view
form.html
list.html
# JDK 17 기반
FROM openjdk:17
# build할 jar 파일 변수 선언
ARG JAR_FILE=build/libs/*.jar
# build/libs에 있는 JAR파일을 Docker 이미지의 app.jar로 복사
COPY ${JAR_FILE} app.jar
# Docker 컨테이너가 실행되면 java -jar app.jar 명령어를 실행하여 Spring boot 실행
ENTRYPOINT ["java", "-jar", "app.jar"]
Entity - Repositoty - Controller - View 구조로 진행하였습니다.
@Entity가 붙은 클래스는 JPA가 관리하는 객체
주의
- 기본 생성자 필수(파라미터가 없는 public 또는 protected 생성자)
- final 클래스, enum, interface, inner 클래스 사용 X
- 저장할 필드에 final 사용 X
- 또한 JPA @Entity 에서는 primary key를 지정하기 위해선
jakarta.persistence.Id을 사용해야 합니다.
만약 에러가 난다면 @Id의 라이브러리를 체크해줘야합니다.org.springframework.data.annotation.Id어노테이션은 Spring Data에서 사용되며, JPA 엔티티에는 적절하지 않습니다.
- 참고
@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@Entity
public class Contents {
@Id @GeneratedValue
private Long id;
private String content;
public Contents(String content) {
this.content = content;
}
}
간단한 CRUD 기능만 사용하기때문에 CrudRepository 사용
CRUD기능을 제공하는 인터페이스org.springframework.data.repository- 인터페이스
Repository를 확장함- 참고
public interface ContentsRepository extends CrudRepository<Contents, Long> {
}
CrudRepository 의 Create(저장)인 save(enitiy)와 Read(조회)인 finaAll() 사용
@RequiredArgsConstructor
@Controller
public class HomeController {
private final ContentsRepository contentsRepository;
@GetMapping("/")
public String home(){
return "view/form";
}
@PostMapping("/")
public String form(@ModelAttribute ContentRequest content){
contentsRepository.save(new Contents(content.getContent()));
return "redirect:/";
}
@GetMapping("/list")
public String list(Model model){
List<Contents> contents = new ArrayList<>();
Iterable<Contents> contentsIterable = contentsRepository.findAll();
contentsIterable.forEach(contents::add);
model.addAttribute("contents", contents);
return "view/list";
}
@Data
@AllArgsConstructor
static class ContentRequest{
private String content;
}
}
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Title</title>
</head>
<body>
<form action="/" method="post">
<input type="text" id="content" name="content">
<button type="submit">등록</button>
</form>
<a href="/list">목록보기</a>
</body>
</html>
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Title</title>
</head>
<body>
<table border="1">
<thead>
<tr>
<td>ID</td>
<td>Content</td>
</tr>
</thead>
<tbody>
<tr th:each="c : ${contents}">
<td th:text="${c.id}"></td>
<td th:text="${c.content}"></td>
</tr>
</tbody>
</table>
</body>
<a href="/">글쓰기</a>
</html>
MySQL 연동시 많은 에러가 발목을 잡았습니다.
이유는 MySQL 버전 이였습니다.
MySQL 8.x 버전 이상에서는
spring.datasource.url의 useSSL=false&allowPublicKeyRetrieval=true 를 추가spring.jpa.properties.hibernate.dialect의 org.hibernate.dialect.MySQLDialect참고
spring.application.name=docker_test
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
# 로컬 실행
#spring.datasource.url=jdbc:mysql://localhost:3306/mydb?useSSL=false
#spring.datasource.username=root
#spring.datasource.password=0608
# 도커 실행
spring.datasource.url=jdbc:mysql://db-mysql:3306/mydb?useSSL=false&allowPublicKeyRetrieval=true
spring.datasource.username=user
spring.datasource.password=user
spring.jpa.hibernate.ddl-auto=create
spring.jpa.properties.hibernate.format_sql=true
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQLDialect
./gradlew clean build -x test
build 할때 test에서 DB연결을 해보기때문에 test를 제외하고 build 해줘야함.
-x test: 테스트 작업을 제외하고 빌드를 수행
여러 컨테이너를 동일한 환경에서 연동시키기 위해 네트워크 설정이 필요합니다.
네트워크 생성 명령어
$ docker network create springboot-mysql-net
생성된 네트워크 확인
$ docker network ls
MySQL이미지 가져오기
$ docker pull mysql
MySQL 구동
--name : 컨테이너명 설정-p : 포트매핑--network : 네트워크 설정-e : 환경변수 설정-d : 백그라운드로 컨테이너 실행$ docker run --name db-mysql -p 3306:3306 --network springboot-mysql-net -e MYSQL_ROOT_PASSWORD=root -e MYSQL_DATABASE=mydb -e MYSQL_USER=user -e MYSQL_PASSWORD=user -d mysql

Dockerfile을 이용한 이미지 빌드
$ docker build -t springboot-mysql:1.0
Docker Spring Boot 구동
$ docker run -p 8080:8080 --name springboot-mysql --network springboot-mysql-net -d springboot-mysql:1.0


다음에는 docker-compose를 이용해 보겠습니다.
https://bibi6666667.tistory.com/283