도커 환경에서 DB를 사용하는 애플리케이션 구동을 목표로 하므로 최대한 간단하게 프로젝트를 구성해볼께요.
springboot
프로젝트는 사용자에게 글을 입력받으면 DB에 저장하고 목록을 확인할 수 있는 아주 간단한 구조입니다.
Dependency
Entity
- Repository
- Controller
- View
만을 가지는 구조입니다.
Entity
@Getter
@Entity
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class Contents {
@Id @GeneratedValue
private Long id;
private String content;
public Contents(String content) {
this.content = content;
}
}
Repository
public interface ContentsRepository extends CrudRepository<Contents, Long> {
}
Controller
@RequiredArgsConstructor
@Controller
public class HomeController {
private final ContentsRepository contentsRepository;
@GetMapping("/")
public String home() {
return "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 "list";
}
@Data
@AllArgsConstructor
static class ContentRequest{
private String content;
}
}
입력폼
[ form.html ]
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<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>
목록보기
[ list.html ]
<!DOCTYPE html>
<html xmlns:th="http://thymeleaf.org">
<head>
<meta charset="UTF-8">
<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>
pom.xml
[ pom.xml ]
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.5.3</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.dhk</groupId>
<artifactId>deploy</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>deploy</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
</project>
datasource
의 url
부분에서 호스트 부분 설정을 잘 해주셔야 합니다.
현재 호스트가 db-mysql
로 되어 있는데 이 호스트명은 앞으로 도커환경에서 mysql
이 구동되는 컨테이너의 이름입니다.
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://db-mysql:3306/mydb?useSSL=false
username: user
password: user
jpa:
hibernate:
ddl-auto: create
properties:
hibernate:
format_sql: true
dialect: org.hibernate.dialect.MySQL5InnoDBDialect
FROM openjdk:8-jdk-alpine
ARG JAR_FILE=target/*.jar
COPY ${JAR_FILE} app.jar
ENTRYPOINT ["java", "-jar", "/app.jar"]
FROM
: 베이스 이미지 빌드하고자 하는 이미지의 기본 골격이 되는 이미지입니다. ARG
: 일종의 변수선언이라고 이해해도 될 것 같습니다. 패키징된 jar
파일을 저장합니다. COPY
: 실행가능한 패키징된 파일(jar
)을 컨테이너 내부로 복사합니다.ENTRYPOINT
: 이미지 빌드시 실행되는 명령어입니다. 로컬에서 jar
파일을 구동하는 것과 동일한 명령어를 넣어주면 됩니다.현재 프로젝트는 maven
을 사용하고 있기 때문에 mvn
명령어를 사용합니다.
mvn clean package -DskipTests
-DskipTests
이거 꼭 넣어주세요..
yml
에서 도커에서 구동될 mysql
의 컨테이너명을 넣어주는데 이 부분 때문에 패키징 시 테스트에 실패하는 것 같습니다..
위 명령어를 실행하면 프로젝트 디렉토리에 target
이 생성되고 그 안에 jar
파일이 생성될 것 입니다.
이 때 생성되는 jar
파일을 도커 컨테이너 안으로 복사해줘서 컨테이너가 실행시킬 수 있도록 하는 것 입니다.
도커 환경에서 여러 컨테이너를 동일한 환경에서 연동시키기 위해서 네트워크 설정이 필요합니다.
여기서는 MySQL
과 springboot app
이 동일한 네트워크에서 구동되도록 해주어야 합니다.
일단 네트워크부터 하나 생성해줍니다.
$ docker network create springboot-mysql-net
생성된 네트워크는 아래 명령어로 확인 가능합니다.
$ docker network ls
도커 허브에서 mysql 이미지 가져오기
$ docker pull mysql:5.7
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:5.7
Dockerfile을 이용한 이미지 빌드
$ docker build -t springboot-mysql:1.0
빌드된 이미지로 컨테이너 구동
$ docker run -p 8080:8080 --name springboot-mysql --network springboot-mysql-net -d springboot-mysql:1.0
두 개 컨테이너 모두 백그라운드로 잘 실행되고 있습니다.
요청 및 DB 테스트
이렇게 여러 컨테이너를 구동시키기 위해 docker
에서는 docker-compose
라는 기능을 제공합니다. docker-compose
가 더 편하고 좋아서 저도 처음에는 docker-compose
로 컨테이너 구동을 하려 했습니다..
근데 자꾸 이상한 부분에서 막혀서 어떤 구조로 돌아가는지 파악하기 위해 docker-compose
를 사용하지 않고 구현해봤습니다..ㅎ
다음에는 동일한 app을 docker-compose
로 구동하는 법을 알아볼께요.
감사합니다ㅎ 😄
안녕하세요 글 잘보고 있습니다.
지금 따라하면서 network 생성과 mysql과 프로젝트 이미지 생성까지 잘되고 네트워크 연결추가해서 컨테이너 생성도 이상없이 잘되서 실행중인걸 확인했는데, 프로젝트 컨테이너 로그 확인시 java.net.ConnectException: Connection refused이 발생하는데 혹시 이 상황에서는 무슨 설정이 잘못 되었는지 알수 있을까요?
명령어는 아래처럼 실행했습니다.
1.
docker run --name onboarding-springboot -p 8080:8080 --network preonboarding-mysql-network -d onboarding-springboot
2.
docker run --name mysql-container --network preonboarding-mysql-network -e
MYSQL_ROOT_PASSWORD=XXXX -d -p 3306:3306 mysql:latest