저번 글을 통해 도커의 기본 개념, 도커를 사용하는 이유와 간단하게 스프링부트 서버를 도커에 올려서 실행해보았다. 그리고 도커 허브에 개인적인 도커 이미지를 푸시해서 가져오는 것도 해보았는데, 도커 허브에는 공식적으로 MySQL
, NginX
, Apache
, Jenkins
등 유명한 소프트웨어는 이미 도커 허브에 올라와있다.
이번에는 MySQL
을 도커 허브에서 가져와서 실행해보고 스프링부트 파일과 연결해본 다음 어떤 과정을 거쳐야 하고 그 과정을 docker-compose
를 통해 단순화하는 방법에 대해 알아보도록 하겠다.
이 글은 Docker를 공부하며 배운 내용을 정리한 글로 글에 오류가 있을 수 있습니다.
터미널에서 docker run -p 3307:3306 -e MYSQL_ROOT_PASSWORD=root mysql:5.6
을 실행해보자. 그러면 먼저 로컬 도커 이미지에서 mysql:5.6
이라는 이미지를 찾아보다가 없으면 도커 허브에서 다운로드를 시도할 것이다.
그리고 mysql-client
나 MySQL workbench
등 아무 데이터베이스 프로그램을 사용하여 3307번 포트에 root
라는 비밀번호를 주고 접속하면 MySQL
이 실행된 것을 볼 수 있다.
그 후 CREATE DATABASE mysql_docker;
를 통해 데이터베이스를 하나 생성해준다.
MySQL을 컴퓨터에 깔지 않더라도 순식간에 도커 컨테이너에 이렇게 데이터베이스를 실행시킬 수 있다.
먼저 스프링부트 어플리케이션을 작성해주었다. 코드는 여기에서 확인할 수 있고 간단하게 커피 정보를 추가하고 가져오는 API이므로 클론을 해도 되고 entity, repository, controller
만 따로 복사해도 된다.
그리고 application.properties
를 아래와 같이 작성하여 MySQL 드라이버와 JPA를 연결 시켜준다.
spring.datasource.url=jdbc:mysql://<로컬 아이피 주소>:3307/mysql_docker?serverTimezone=Asia/Seoul
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.jpa.database=mysql
spring.jpa.show-sql=true
spring.jpa.hibernate.ddl-auto=update
spring.jpa.format_sql=true
logging.level.org.hibernate.type=trace
그리고 docker ps -a
를 통해 3307번 포트에서 MySQL
이 잘 동작하는지 확인하고
docker build -t spring-docker .
를 통해 이미지를 만들어준다. 그 다음 docker run -p 8081:8080 spring-docker
를 통해 어플리케이션을 실행시켜준다.
이렇게 하면 정상적으로 도커에 올라간 MySQL
과 Spring Boot
가 동작하는 것을 확인할 수 있다.
참고로 spring.datasource.url
에서는 꼭 자신의 로컬 아이피 주소를 붙여주어야 하는데, 그 이유는 도커는 가상화 기술을 사용하기 때문에 도커의 localhost주소와 우리의 OS가 이용하는 네트워크의 localhost 주소가 다르기 때문이다.
비슷한 내용으로 안드로이드 가상 머신에서 localhost가 다르게 작동하는 점 때문에 빠르게 캐치할 수 있었습니다.
참고로 데이터베이스는 볼륨 옵션을 통해 데이터베이스 파일을 저장해주는 것이 일반적입니다.
지금까지 동작하는 과정을 도식화하면 대강 위와 같다.
위 그림을 보면서 이 모든 프로그램이 실행되는 과정은 아래와 같다.
이렇게 네 단계를 거쳐야한다. 이말인 즉슨 간단히 스프링부트와 데이터베이스만을 실행하더라도 4개의 커맨드를 입력해야 한다. 만약 실 서비스라고 한다면 이 두 어플리케이션만이 아니라 수 많은 프로그램을 전부 순서에 맞게 실행해주어야 되는데, 이는 외우기도 힘들고 굉장히 귀찮은 일이다.
하지만 여기서 docker-compose
를 이용하면 이 모든 과정을 압축하여 한 번에 실행할 수 있다. docker-compose
는 일반적으로 docker
를 설치하면 함께 설치되는데, yml
파일 작성을 통해 모든 과정을 일련의 파일로 작성하고 그 파일을 실행하는 하나의 커맨드로 모든 과정을 줄여 줄 수 있다.
프로젝트 루트폴더에 docker-compose.yml
이라는 이름으로 파일을 만들고 아래와 같이 작성해준다. 참고로 파일은 Dockerfile
과는 다르게 yml
형식만 지켜주면 파일 이름은 아무렇게나 바꿔도 상관 없다.
version: '3'
services:
mysql_db:
image: mysql:5.6
restart: always
ports:
- 3307:3306
environment:
- MYSQL_ROOT_PASSWORD=root
- MYSQL_ROOT_USER=root
- MYSQL_USER=user
- MYSQL_PASSWORD=password
- MYSQL_DATABASE=mysql_docker
spring-docker:
build: .
restart: always
ports:
- 8081:8080
depends_on:
- mysql_db
environment:
- SPRING_DATASOURCE_URL=jdbc:mysql://192.168.0.11:3307/mysql_docker?serverTimezone=Asia/Seoul
- SPRING_DATASOURCE_USERNAME=root
- SPRING_DATASOURCE_PASSWORD=root
- SPRING_JPA_HIBERNATE_DDL_AUTO=update
먼저 version
은 docker-compose
의 버전을 뜻하고 그 아래부터 docker compose
가 서비스해줄 컨테이너 정보를 적어주면 된다.
먼저 mysql_db
라는 이름으로 컨테이너를 실행하고 그 컨테이너는 mysql:5.6
이미지를 사용하도록 했다. 그리고 문제가 생기면 계속 재실행하도록 restart
옵션을 주었다.
port와 environment는 각각 도커 run 커맨드에서 -p, e에 해당하는 내용을 적는데, 여기서 MYSQL_DATABASE
옵션을 통해 mysql을 컨테이너에서 실행한후 데이터베이스를 생성해줄 수 있다.
그 아래는 이제 스프링 부트 컨테이너를 의미한다. build 옵션을 통해 Dockerfile
의 위치를 지정해줄 수 있고 가장 중요한 부분이 depends_on
과 environment
인데,
다시 위에서 실행 과정을 보면
이렇게 스프링 부트 파일보다 mysql이 먼저 실행되주어야 한다. 왜냐하면 스프링부트에 설치된 jdbc
가 mysql을 필요로 하기 때문이다. 따라서 depends_on
옵션을 통해 mysql_db
가 먼저 실행된 다음 실행되도록 작성해주면 된다.
또 environment에서 application.properties
에서 Java를 이용하지 않는 부분은 따로 옵션을 줄 수 있는데, SPRING_JPA_HIBERNATE_DDL_AUTO=update
이 부분은 꼭 이곳에 작성해주어야 했다.
이유는 docker compose를 통해 JPA를 이용한 Spring Boot 어플리케이션을 실행하면 Hibernates
가 엔티티 객체를 데이터베이스에 자동으로 생성해주지 않기 때문이다.
이에 대한 해결 방법으로는 직접 sql문을 작성해서 docker-compose.yml
파일에 옵션으로 실행시키는 방식이 있었다. 하지만 이렇게 하면 @Entity
와 불일치가 일어날 수도 있었기 때문에 가장 간단하게 직접 environment
에 값을 주어서 해결하도록 했다.
그리고 터미널에서 docker-compose -f docker-compose.yml up
을 실행해주면 정상적으로 MySQL
과 Spring Boot
가 하나의 커맨드로 간단하게 실행되는 것을 확인할 수 있다.
application.property에서 연결에 관한 정보를 가지고있는데 docker-compose 파일에서 한번더 정의해주는 이유는 뭔가요?