Bind Mount의 필요성
Docker는 컨테이너화된 애플리케이션을 실행할 때 데이터의 유연한 관리와 공유를 지원하기 위해 여러 데이터 관리 방법을 제공한다. 대표적으로 앞서 다룬 Anonymous Volume과 Named Volume이 있다. 하지만 이 두 볼륨은 볼륨을 생성해 컨테이너의 디렉토리와 연결하는 방식을 사용하며, 호스트 머신의 경로를 컨테이너의 디렉토리와 연결하지는 못한다.
하지만 개발을 하다 보면, 호스트 머신의 변경 사항이 곧바로 애플리케이션에 반영돼야 하는 경우가 있다. 이런 문제를 해결하기 위해 Docker는 Bind Mount라는 기능을 제공한다.
Bind Mount는 호스트 머신의 디렉터리를 컨테이너의 특정 경로에 직접 연결해 데이터를 공유하거나 관리할 수 있도록 하는 기능으로, 이를 사용하면 호스트 머신에서 개발하면서 변경 사항을 실시간으로 적용되도록 만들어 테스트를 쉽게 할 수 있다.
Bind Mount 사용 방법
GitHub: https://github.com/seyoungcho2/DockerExample/tree/feature/2.volume-bindmount
Bind Mount 사용 준비하기
Bind Mount이 제대로 동작하는지 확인하기 위해서는 코드의 변경 사항이 애플리케이션에 반영되는지 확인할 수 있어야 한다.
이를 위해 Spring Dev Tools를 사용하도록 build.gradle.kts를 변경한다.
dependencies {
...
developmentOnly("org.springframework.boot:spring-boot-devtools")
}
Dockerfile도 곧바로 소스에서 빌드해야 하므로 다음과 같이 변경한다.
# JDK 17 이미지 사용하기
FROM eclipse-temurin:17
# 모든 명령이가 실행될 디렉토리 설정
WORKDIR /app
# build.gradle.kts, settings.gradle.kts 파일을 도커 컨테이너의 app 디렉토리에 복사
COPY build.gradle.kts settings.gradle.kts /app/
# 이미지 내부에 들어가야 할 경로 설정. 현재 경로의 모든 파일들이 도커 컨테이너의 app 디렉토리에 복사
CMD ["./gradlew","dependencies","--no-daemon"]
# 도커 컨테이너의 app 디렉토리에 있는 모든 파일들을 도커 컨테이너의 app 디렉토리에 복사
COPY . /app
# 도커 컨테이너 내부의 8080번 포트를 외부로 노출
EXPOSE 8080
# ENTRYPOINT를 사용해 컨테이너가 시작될 때 실행할 명령어를 지정
CMD ["./gradlew", "bootRun", "--no-daemon"]
이후 다음 명령어로 이미지를 빌드한다.
docker build -t bindmount:1.0.0 .
이제 모든 준비가 완료됐다. 이제 Bind Mount를 사용해 호스트 머신의 코드 변경 사항이 곧바로 반영되는지 알아보자.
Bind Mount 사용하기
현재 경로의 src/main 내부에 소스 코드가 있으므로 이 경로를 컨테이너의 소스 경로와 메핑 시켜야 한다.
이를 위해 -v $(pwd)/src/main:/app/src/main 옵션을 추가해 앞서 만든 bindmount:1.0.0 이미지로 컨테이너를 만들어 실행한다.
docker run -d --name springapp -p 8080:8080 -v $(pwd)/src/main:/app/src/main bindmount:1.0.0
이 명령어가 바로 bind mount를 실행하는 명령어이며, : 앞의 경로가 호스트 기기의 경로이고 : 이후의 경로가 컨테이너의 경로가 된다.
docker run -d --name springapp -p 8080:8080 -v [기기의 경로]:[컨테이너 경로] bindmount:1.0.0
그러면 기기 코드의 변경 사항이 곧바로 컨테이너 경로에 반영된다.
Bind Mount 설정이 마쳐졌다. 이제 실제 테스트를 해보자.
Bind Mount 적용 확인하기
기존의 SimpleController은 /hello 경로로 GET 요청 시 "Hello, Docker!"을 반환했다.
@RestController
class SimpleController {
@GetMapping("/hello")
fun hello(): String {
return "Hello, Docker!"
}
}
이제 이 코드를 당므과 같이 변경해 "Hello, Docker Bind Mount!" 를 반환하도록 수정하자.
@RestController
class SimpleController {
@GetMapping("/hello")
fun hello(): String {
return "Hello, Docker Bind Mount!"
}
}
약간의 시간이 지난 후 혹은 컨테이너 리스타트 이후에 http://localhost:8080/hello로의 GET 요청 시 변경된 문구가 적용된 것을 확인할 수 있다.
'Docker' 카테고리의 다른 글
[Docker] Dockerfile내부, .env 파일 혹은 터미널을 사용해 환경 변수 설정하는 방법 한 번에 정리하기 (0) | 2025.01.30 |
---|---|
[Docker] .dockerignore 사용해 컨테이너에 복사되지 말아야 할 파일 정의하기 (0) | 2025.01.29 |
[Docker] Named Volume 이란 무엇인가? 사용 방법과 특징 정리 (0) | 2025.01.27 |
[Docker] Anonymous Volume(익명 볼륨) 한 번에 정리하기 (0) | 2025.01.26 |
Docker Hub에 이미지 업로드 하기 (0) | 2025.01.25 |