docker-compose를 이용한 MySQL서버를 배포하고 Spring연동하기
1. Spring
(1) Gradle
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
compileOnly 'org.projectlombok:lombok'
annotationProcessor 'org.projectlombok:lombok'
runtimeOnly 'com.mysql:mysql-connector-j'
}
테스트를 위해 springweb,spring-data-jpa,lombok,mysql를 추가해줍니다.
(2) application.yml
spring:
jpa:
hibernate:
ddl-auto: update
properties:
hibernate:
format_sql: true
logging.level:
org.hibernate.SQL: debug
Member 테이블이 만들어지는 sql log를 볼 수 있도록 yml파일에 설정합니다.
(3) Domain
@Entity
@NoArgsConstructor
@Getter
public class Member {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "MEMBER_ID")
private Long id;
private String name;
@Column(unique = true)
private String email;
public Member(String name,String email){
this.name = name;
this.email = email;
}
}
이름과 이메일을 가지는 Member class를 생성합니다.
(4) Repository
public interface MemberRepository extends JpaRepository<Member,Long>{
}
(5) Dto
@Getter
@NoArgsConstructor
public class MemberSaveDto {
private String name;
private String email;
}
Member를 저장할 때 쓰이는 이름과 이메일을 받아오는 Dto를 생성합니다.
(6) Controller
@RestController
@AllArgsConstructor
public class MemberController {
private final MemberRepository memberRepository;
@PostMapping("/member")
public Long saveMember(@RequestBody MemberSaveDto memberSaveDto){
Member member = new Member(memberSaveDto.getName(), memberSaveDto.getEmail());
memberRepository.save(member);
return member.getId();
}
@GetMapping("/member")
public List<Member> findAllMember(){
return memberRepository.findAll();
}
@GetMapping("/member/{id}")
public Member findMember(@PathVariable Long id){
return memberRepository.findById(id).get();
}
}
Member를 저장하고 Member들의 정보를 들고오는 api를 가지는 Controller를 생성합니다.
2.ubuntu(docker-server)
(1) mysql 이미지 Pull
docker pull mysql:8.0
mysql 이미지를 받아옵니다.
(2) mysql.env 파일
MYSQL_DATABASE=[database_name]
MYSQL_ROOT_HOST=%
MYSQL_ROOT_PASSWORD=[password]
TZ=Asia/Seoul
(3) spring.env 파일
SPRING_DATASOURCE_URL=jdbc:mysql://[mysql-container-name]:3306/[database_name]?allowPublicKeyRetrieval=true
SPRING_DATASOURCE_USERNAME=root
SPRING_DATASOURCE_PASSWORD=[password]
database_name과 password 는 2의 mysql.env파일과 동일하게 작성합니다.
(4) docker-compose.yml
version: '3'
services:
docker_gradle:
container_name: docker_gradle
image: docker_gradle
ports:
- "8081:8081"
env_file:
- ./spring/spring.env
depends_on:
mysql:
condition: service_healthy
mysql:
container_name: mysql
image: mysql:8.0
restart: unless-stopped
env_file:
- ./mysql/mysql.env
ports:
- "13306:3306"
command:
- "mysqld"
- "--character-set-server=utf8mb4"
- "--collation-server=utf8mb4_unicode_ci"
healthcheck:
test: ['CMD-SHELL', 'mysqladmin ping -h 127.0.0.1 -u root --password=$$MYSQL_ROOT_PASSWORD']
interval: 10s
timeout: 2s
retries: 100
mysql 컨테이너가 생성되고 MySQL 데이터베이스가 생성되는데 시간이 조금 소요됩니다.
mysql 데이터베이스가 생성되지 않은 상태로 spring server 가 올라가면 database connection에러가 발생합니다.
그러므로 mysqladmin ping을 이용하여 mysql 데이터베이스가 생성되었는지 검사하고,mysql 데이터베이스가 완전히 생성되었을 때 spring server container를 생성합니다.
(5) 실행 및 확인
1. docker compose 실행
docker compose up
docker compose를 daemon 모드로 실행하지 않고 spring server와 mysql server가 잘 연동되는지 확인합니다.
2. mysql container 접속
# mysql container 접속
docker exec -it [mysql_container_name] bash
3. mysql 접속
# mysql 접속
mysql -u root -p
4. member 테이블 확인
# database 목록 확인
show databases;
# database 선택
use test;
# table 목록 확인
show tables;
위의 명령어를 이용하여 member 테이블이 생성되었는지 확인합니다.
(6) volumes 설정
1. conf.d / utf8.cnf
[mysqld]
character-set-server=utf8mb4
collation-server=utf8mb4_unicode_ci
[mysql]
default-character-set = utf8mb4
[client]
default-character-set = utf8mb4
2.conf.d / log.cnf
[mysqld]
general_log=ON
general_log_file=/var/log/mysql/general.log
log_error=/var/log/mysql/error.log
slow_query_log=ON
slow_query_log_file=/var/log/mysql/slow.log
long_query_time=2
log-queries-not-using-indexes
log_timestamps=SYSTEM
3. docker-compose.yml
version: '3'
services:
docker_gradle:
container_name: docker_gradle
image: docker_gradle
restart: on-failure
ports:
- "8081:8081"
env_file:
- ./spring/spring.env
depends_on:
mysql:
condition: service_healthy
mysql:
container_name: mysql
image: mysql:8.0
restart: unless-stopped
env_file:
- ./mysql/mysql.env
ports:
- "13306:3306"
volumes:
- ./mysql/data:/var/lib/mysql
- ./mysql/log:/var/log/mysql
- ./mysql/conf.d:/etc/mysql/conf.d
healthcheck:
test: ['CMD-SHELL', 'mysqladmin ping -h 127.0.0.1 -u root --password=$$MYSQL_ROOT_PASSWORD']
interval: 10s
timeout: 2s
retries: 10
컨테이너가 삭제 될 시 mysql의 로그와 데이터는 사라지기 때문에 volume mount를 통해 데이터와 로그를 보관합니다.