docker-compose
를 통해서 Dockerfile 하나보다 여러 컨테이너들을 묶어서 편하게 관리하기가 아주 좋습니다.
이제 docker-compose
를 위한 실습을 해봅시다.
UserEntity
를 가지고 CURD를 하는 SpringBoot RESTAPI 프로젝트를 만들어보았습니다. 이 프로젝트는 MySql DB
와 연동을 해야 하는데 docker-compose.yml
파일로 쉽게 연동할 수 있음을 실습해보겠습니다.
Mysql 사용시 로컬에서 port 3306를 중지
시키고 docker-compose 실습을 하기 바랍니다. 이것때문에 port를 docker-compose에서 아무리 바꿔도 바뀌지 않습니다!...
심신건강을 위해 3306를 꺼두고 진행해주세요! => 작업관리자에서 꺼주시길!
build.gradle
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'org.springframework.boot:spring-boot-starter-web'
compileOnly 'org.projectlombok:lombok'
compileOnly 'mysql:mysql-connector-java'
annotationProcessor 'org.projectlombok:lombok'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
implementation group: 'org.javassist', name: 'javassist', version: '3.15.0-GA'
}
@Getter
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Entity
@Table(name = "users")
public class UserEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String username;
private String password;
}
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class UserDto {
private String username;
private String password;
}
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class UserResult {
private Long id;
private String username;
private String password;
public UserResult(UserEntity users) {
this.id = users.getId();
this.username = users.getUsername();
this.password = users.getPassword();
}
}
public interface UserRepository extends JpaRepository<UserEntity, Long> {
}
@RequiredArgsConstructor
@Service
public class UserService {
private final UserRepository userRepository;
public UserEntity create(UserDto userDto) {
UserEntity userEntity = UserEntity.builder()
.username(userDto.getUsername())
.password(userDto.getPassword())
.build();
return userRepository.save(userEntity);
}
public UserEntity readOne(Long id) {
return userRepository.findById(id)
.orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND));
}
}
UserController
@Slf4j
@RestController
@RequiredArgsConstructor
@RequestMapping("/api")
public class UserController {
private final UserService userService;
@PostMapping
public ResponseEntity create(@RequestBody UserDto userDto) {
log.info("create Users");
UserEntity users = userService.create(userDto);
return ResponseEntity.ok(new UserResult(users));
}
@GetMapping("{id}")
public ResponseEntity getUser(@PathVariable Long id) {
log.info("readOne");
UserEntity users = userService.readOne(id);
return ResponseEntity.ok(new UserResult(users));
}
}
DB ORM은 JPA
를 사용합니다.
application.yml
파일에서 JPA 연동 설정을 해야합니다.
database 설정은 docker-compose.yml에서 설정해줄 거기 때문에 applciation.yml에서 뺐습니다.
application.yml
spring:
# 주석을 해도 안해도 상관x, 설사 틀린내용이라도. 우선순위가 docker-compose내용으로 하기 때문
# datasource:
# driver-class-name: com.mysql.cj.jdbc.Driver
# url: jdbc:mysql://database:3306/users_db?useSSL=false
# username: root
# password: '1234'
jpa:
open-in-view: true
hibernate:
ddl-auto: create
naming:
physical-strategy: org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
use-new-id-generator-mappings: false
show-sql: true
properties:
hibernate.format_sql: true
dialect: org.hibernate.dialect.MySQL5InnoDBDialect
build.gradle
jar {
enabled = false
}
자 이제 Dockerfile과 docker-compse.yml을 보겠습니다.
이 둘은 꼭 같은 경로에 있어야 합니다!
꼭 ./gradlew clean build
로 jar를 새로 생성하고 실행해야 오류가 안납니다.
Dockerfile
FROM openjdk:11-jdk
ARG JAR_FILE=build/libs/*.jar
COPY ${JAR_FILE} app.jar
ENTRYPOINT ["java","-jar","/app.jar"]
docker-compse.yml
version: '3'
services:
database:
container_name: mysql_db
image: mysql/mysql-server:5.7
restart: unless-stopped
environment:
MYSQL_DATABASE: users_db
MYSQL_ROOT_HOST: '%'
MYSQL_ROOT_PASSWORD: 1234
TZ: 'Asia/Seoul'
ports:
- "3306:3306"
volumes:
- ./mysql/conf.d:/etc/mysql/conf.d # MySQL 설정 파일 위치
command:
- "mysqld"
- "--character-set-server=utf8mb4"
- "--collation-server=utf8mb4_unicode_ci"
networks:
- test_network
application:
container_name: docker-compose-test
restart: on-failure
build:
context: ./
dockerfile: Dockerfile
ports:
- "8080:8080"
environment:
SPRING_DATASOURCE_URL: jdbc:mysql://mysql_db:3306/users_db?useSSL=false&allowPublicKeyRetrieval=true
SPRING_DATASOURCE_USERNAME: "root"
SPRING_DATASOURCE_PASSWORD: "1234"
depends_on:
- database
networks:
- test_network
networks:
test_network:
이 상태에서 docker-compose 파일을 실행해보겠습니다.
docker-compose up
dockerfile을 새로 build하고 싶다면 빌드 옵션을 사용하면 됩니다.
docker-compose up --build -d
만약 다른 경로에 있거나 다른 파일명을 사용하고 싶을 경우 -f
옵션으로 docker-compose 파일을 지정해주면 됩니다.
docker-compose -f [다른 docker-compose.yml] up
# 예시
docker-compose -f docker-compose.v3.yml up
-d
옵션을 주면 백그라운드로 실행시킬 수 있습니다.
docker-compose -d up
만약 docker-compose 실행을 닫고 싶다면
docker-compose down
이 명령어를 치면 됩니다.
log 명령어를 통해 올라간 springboot 프로젝트가 제대로 실행되는지 확인할 수 있습니다.
docker-compose logs
제대로 실행되는지
postman
으로 api를 보내는 테스트를 진행해봅시다.
post : localhost:8080/api
get : localhost:8080/api/{id}
네, 둘다 제대로 진행되는지 확인했습니다.
정보들을 따로 .env파일로 관리하고 ${}
로 보안처리를 할 수 있습니다.
나중에는 이 파일들은 .gitignore 를 처리해줍니다. 왜냐하면, 중요보안 정보가 들어있는 파일을 외부에 노출하지 않기 위함입니다!
.env
MYSQL_ROOT_HOST=%
MYSQL_ROOT_PASSWORD=1234
MYSQL_DATABASE=board_dsg
SPRING_DATASOURCE_USERNAME=root
docker-compose.yml
version: '3'
services:
database:
container_name: mysql_db
image: mysql
restart: unless-stopped
env_file:
- .env
ports:
- "3306:3306"
volumes:
- ./mysql/conf.d:/etc/mysql/conf.d # MySQL 설정 파일 위치
command:
- "mysqld"
- "--character-set-server=utf8mb4"
- "--collation-server=utf8mb4_unicode_ci"
networks:
- test_network
application:
container_name: board_vue_backend
restart: on-failure
build:
context: ./
dockerfile: Dockerfile
ports:
- "8080:8080"
env_file:
- .env
environment:
SPRING_DATASOURCE_URL: jdbc:mysql://mysql_db:3306/${MYSQL_DATABASE}?useSSL=false&allowPublicKeyRetrieval=true
SPRING_DATASOURCE_USERNAME: ${SPRING_DATASOURCE_USERNAME}
SPRING_DATASOURCE_PASSWORD: ${MYSQL_ROOT_PASSWORD}
depends_on:
- database
networks:
- test_network
networks:
test_network: