이번 포스팅에서는 docker를 이용해, Database를 이용하는 Spring Boot 어플리케이션을 배포하는 방법을 알아보도록 하겠습니다. (docker가 설치된 환경으로 가정하고 진행하도록 하겠습니다.)
1. Spring Boot Application 생성
우선 간단히 Member List를 조회할 수 있는 Spring Boot Application을 생성하겠습니다.
우선 Application의 전체 파일 구성입니다. 필요한 구성은 아래와 같습니다.
- Member : Entity
- MemberRepository : Member Entity 영속성을 관리
- TestController : Member Entity를 조회할 수 있도록하는 컨트롤러
- application.yml : jpa, jdbc 를 설정
1.1 build.gradle
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'org.springframework.boot:spring-boot-starter-jdbc'
implementation group: 'mysql', name: 'mysql-connector-java', version: '8.0.15'
implementation 'org.springframework.boot:spring-boot-starter-web'
compileOnly 'org.projectlombok:lombok'
developmentOnly 'org.springframework.boot:spring-boot-devtools'
annotationProcessor 'org.projectlombok:lombok'
testImplementation('org.springframework.boot:spring-boot-starter-test') {
exclude group: 'org.junit.vintage', module: 'junit-vintage-engine'
}
}
아 의존성에 대한 언급이 빠졌는데요, build.gradle 파일의 dependeices는 위와 같습니다.
1.2 application.yml
x
server
port80
spring
datasource
driver-class-name com.mysql.cj.jdbc.Driver
url jdbc mysql //db 3306/testdb?serverTimezone=Asia/Seoul&allowPublicKeyRetrieval=true&useSSL=false&characterEncoding=UTF-8
username root
password test1234
jpa
hibernate
ddl-auto create
show-sqltrue
properties
hibernate
dialect org.hibernate.dialect.MySQL5InnoDBDialect
url: jdbc:mysql://db:3306/testdb?...
- jpa 및 spring 을 알아보는 시간이 아니기 때문에, 이 설정에대해서만 간단히 살펴보도록 하겠습니다. 특이한 점은 연결할 호스트의 ip 또는 domain name을 적은것이 아니라 db
라는 이름을 적은것입니다. 이렇게 적은 이유는 docker의 container간의 연결을 위해서 입니다.
물론 container가 생성될때 각 container에도 local ip가 부여되지만, 이는 container가 생성될때 동적으로 부여되기 때문에, server를 구축할 당시에는 알 수가 없습니다. 특별한 이름으로 container간 통신을 할 수 있도록 해야하는데요, custom docker network를 만들게 되면, container 생성시 부여한 이름으로 network 통신이 가능합니다.(docker network 정리 포스팅 참조 - https://galid1.tistory.com/723)
따라서 db
라고 적힌 database는 container의 이름입니다. 잠시후, container를 생성할때 다시한번 언급하도록 하겠습니다.
1.3 Member
xxxxxxxxxx
public class Member {
private Long memberId;
private String name;
public Member(String name) {
this.name = name;
}
}
간단히 id와 name을 가지는 Entity를 생성합니다.
1.4 MemberRepository
public interface MemberRepository extends JpaRepository<Member, Long> {
}
JpaRepository를 상속받는 interface를 생성합니다.
1.5 TestController
xxxxxxxxxx
public class TestController {
private final MemberRepository memberRepository;
"/save") (
public void test() {
Member m1 = new Member("m1");
memberRepository.save(m1);
}
"/get") (
public String getM1() {
return memberRepository.findAll().toString();
}
}
/save(GET)
: 간단히, member를 생성하는 api입니다.
/get(GET)
: member를 출력하는 api입니다.
2. Docker Image (생성한 Application) 생성
앞서 생성한 Spring Boot Application을 Docker Image로 만들겠습니다.
2.1 application의 .jar 생성
우선 bootJar
Gradle Task를 이용하여 .jar
파일을 생성합니다.
프로젝트 최상단/build/libs/
경로에, .jar
파일이 생성됩니다.
2.2 docker image 생성
x➜ ~ docker search java8
우선 java8이 설치된 기본이미지를 찾습니다.
x➜ ~ docker pull williamyeh/java8
이미지를 다운받습니다.
xxxxxxxxxx
➜ libs vi Dockerfile
application의 .jar
파일이 존재하는 경로로 이동하여, Dockerfile
를 생성합니다. (jar파일을 포함한 이미지를 만들기 위함입니다.)
xFROM williamyeh/java8
COPY *.jar app.jar
ENTRYPOINT ["java","-jar","app.jar"]
FROM williamyeh/java8 : 다운 받은 java8이 설치된 이미지를 기본이미지로 합니다.
COPY *.jar app.jar : 현재 Dockerfile이 존재하는 경로에 존재하는 .jar
확장자를 가진 파일을 app.jar
라는 이름으로 새로 만들어질 도커이미지에 포함시킵니다.
ENTRYPOINT ["java","-jar","app.jar"] : 컨테이너 실행시 java -jar app.jar
명령어를 실행합니다.
x➜ libs docker build -t galid1/test:0.1 .
Dockerfile
과, 생성한 .jar
파일이 위치한 경로에서 위와같이 입력합니다. (* image 생성정보가 담긴 파일이름은 꼭 Dockerfile이어야 합니다. 다른 이름을 가진 파일을 이용하여 이미지를 만들기 위해서는, -f
옵션을 이용해 해당 파일을 지정하면 됩니다.)
3. Docker Network 생성
앞서 말씀드렸듯이, 컨테이너간 통신을 컨테이너의 이름으로 하기 위해서는, custom network를 생성하고, 해당 network에 container를 생성해야합니다. 자세한 내용은 다음 링크를 참조해주세요 - https://galid1.tistory.com/723
xxxxxxxxxx
➜ libs docker network create test
간단히 network를 생성합니다.
4. Container 실행 및 Mysql 연결
우선, Spring Boot Application에서는 db
라는 호스트에 database 연결을 요청하고 있습니다. 따라서, database가 실행중이어야 container를 실행할 수 있습니다. (docker 를 이용해 mysql을 설치하는 자세한 방법은 다음링크를 참조해주세요 - https://galid1.tistory.com/724)
4.1 Mysql Container 이미지 다운 및 실행
x➜ libs docker run -d --name db -e MYSQL_ROOT_PASSWORD=test1234 -p 3306:3306 --network test mysql
위 명령어를 이용해 mysql container를 우선 실행합니다. 원래는 이미지를 다운 받아야 하지만, 해당 이미지가 도커 호스트에 존재하지 않는경우, Docker가자동으로 docker hub에서 찾고 존재한다면, 다운을 받아줍니다.
-d
: 백그라운드에서 container가 실행되도록 합니다.
-e
: container 생성시 기본적으로 넘겨줄 파라미터를 지정합니다. 해당 mysql 이미지는 container 실행시, database root 관리자 비밀번호를 받도록 되어있습니다. * Spring Boot Application을 생성할 때 Database 연결을 위해 지정한 비밀번호를 입력합니다.(test1234)
-p
: container가 외부에 노출할 port와 이 port에 연결하기 위해 docker host에서 사용할 port를 지정합니다.
--network
: 우리가 생성한 custom network를 입력합니다.
--name
: container에서 통신하기위해 사용할 이름을 부여합니다. * Spring Boot Application을 생성할때 Database 연결을 위해 지정한 host 이름을 입력합니다. (db)
4.2 database 생성
spring boot application 생성시, 연결을 위해 입력했던 database를 생성해주어야 합니다.
xxxxxxxxxx
➜ libs docker exec -it db bash
root@bb882e7e2e1a:/#
exec
명령을 이용해, db
container에 연결함과 동시에 bash 셸을 실행 시킵니다.
root@bb882e7e2e1a:/# mysql -u root -p
Enter password:
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 8
...
mysql> create database testdb;
Query OK, 1 row affected (0.01 sec)
container 내부에서, mysql -u root -p
를 이용해 mysql을 실행합니다. 비밀번호는 container 생성시, -e
옵션으로 부여한 비밀번호를 사용합니다.
그후, spring boot application에서 연결을 시도하는 database 이름으로 하는 database를 생성합니다.
Ctrl + p + q 를 이용해 docker container를 백그라운드에서 실행하도록 유지하며 container에서 dettach 합니다.(c처음 mysql container 실행시 -d 옵션을 부여했기 때문에 exit로 그냥 나오셔도 무방합니다.)
5. Application 실행 및 확인
드디어, 생성한 Application Image를 이용해 Container를 실행해보겠습니다.
xxxxxxxxxx
➜ libs docker run -it --name app --network test -p 80:80 galid1/test:0.1 bash
--network
옵션을 이용해 mysql container와 같은 network에 container를 실행시키며, Spring Boot application 생성시 application.yml에서 지정한 port를 외부로 노출합니다.
application이 정상적으로 실행됩니다.
'Infra > Docker' 카테고리의 다른 글
Docker - Docker Network란? (Docker Netowkr 사용예제) (0) | 2020.04.17 |
---|---|
Docker - container volume 사용 (0) | 2019.02.15 |
Docker - Docker의 데이터 저장방법 (0) | 2019.02.15 |
Docker - Forbidden path outside the build context 에러 (4) | 2019.01.30 |
Docker - Certification is Expired or not yet valid 에러 (0) | 2019.01.30 |