Intro
코드를 변경할 때마다 이미지를 다시 빌드하지 않는 한 실행 중인 컨테이너에 변경 사항이 반영되지 않는다.
이는 도커 이미지가 생성될 때 폴더의 스냅샷만 복사하므로, 복사한 뒤 발생하는 변경 사항은 컨테이너에 반영되지 않기 때문에 그런 것이다.
하지만 개발 중에 도커를 사용한다면 변경 사항이 즉시 반영되는 것이 편할 것이다.(아니면 매번 리빌드해야된다,,😇)
이를 바인드 마운트가 도와준다!
볼륨과의 차이점
- 컴퓨터의 파일 시스템 상의 어디에 위치해 있는지 알 수 있다.
➡ 컴퓨터 상에 매핑될 컨테이너의 경로를 설정하기 때문이다. - 소스 코드를 넣을 수 있다.
➡ 이렇게 하면 컨테이너가 인식해서 바인딩 마운트에서 코드를 복사한다.
(최신 코드에 액세스 가능!) - 영구적이고 편집 가능한 데이터에 적합하다.
바인드 마운트 추가하기
- 컨테이너를 실행할 때 터미널 내부에서 마운트를 설정해야 한다.
- 바인딩 마운트로 공유 중인 폴더에 도커가 액세스 할 수 있는지 확인해야 한다.
(Docker Toolbox를 사용해서 도커를 실행하고 있다면 도커가 Users 폴더에 액세스하도록 디폴트로 설정 되어 있다.)
docker run -d -p 3000:80 --rm --name feedback-app -v feedback:/app/feedback -v "C:/Study/docker/data-volumes-01-starting-setup/data-volumes-01-starting-setup/:/app" feedback-node:volumes
위 명령어를 실행하면 컨테이너가 다시 시작된다.
그리고 현재 위치한 전체 폴더가 컨테이너 내부의 'app' 폴더에 명명된 볼륨으로 마운트 된다.
참고: 항상 전체 경로를 복사하여 사용하고 싶지 않은 경우, 다음 바로 가기를 사용할 수 있다.
macOS / Linux: -v $(pwd):/app
Windows: -v "%cd%":/app
컨테이너 - 볼륨 및 마운트의 상호작용 방식
컨테이너 내부 폴더를 컴퓨터 폴더에 마운트하거나 연결할 때, 몇 가지 중요한 사항을 고려해야 한다.
- 컨테이너 내부에 파일이 있는 경우
- 컨테이너를 시작하면 볼륨에서 파일 찾음
- 이때 내부에 파일이 없다면, 볼륨에서 파일을 로드(바인드 마운트 활용)
- 컨테이너 내부에 파일이 없는 경우
- 컴퓨터 폴더와 파일이 도커 컨테이너의 내용 덮어 씀
하지만 여기서 모듈 등이 제거될 수 있다. - 이를 방지하려면 도커에게 내부 파일 시스템에 외부에서 덮어 쓰면 안 되는 부분이 있다고 알려 주어야 한다.
➡ 도커 컨테이너에 익명 볼륨 추가로 해결
✅ '-v' 로 볼륨을 하나 더 추가하여 '/app/node_modules' 폴더 바인딩
- 컴퓨터 폴더와 파일이 도커 컨테이너의 내용 덮어 씀
docker run -d -p 3000:80 --rm --name feedback-app \
-v feedback:/app/feedback \
-v "C:\Users\docker\data-volumes-01-starting-setup\data-volumes-01-starting-setup\:\app" \
-v /app/node_modules feedback-node:volumes
이는 Dockerfile에 VOLUME [ "/app/node_modules" ] 옵션을 추가하는 것과 같다.
도커는 충돌이 있는 경우 더 자세한 경로를 우선한다. ex. /app vs /app/node_modules(우선)
따라서, node_modules 폴더는 외부에서 들어오는 바인드 마운트된 볼륨의 내용물을 덮어쓴다.
정리
- 'npm install'을 사용하여 이미지 생성 중에 생성된 'node_modules' 폴더가 남음
- 바인드 마운트와 함께 공존할 수 있다.
+ 여기에 더해 소스 코드를 변경하고 새로고침 하면 리빌드 할 필요 없이 변경 사항을 바로 확인할 수 있다!
하지만 여기서 server.js에서 무언가를 변경하면 문제가 발생한다.
새 피드백을 저장할 때마다 콘솔 로그로 'TEST'를 출력하도록 해보자.
그러나 나타나는 로그가 없다. (지극히 정상)
<-- 리눅스만 적용 되는 기능 -->
"devDependencies": {
"nodemon": "2.0.4"
}
- 파일이 변경될 때마다 노드 서버를 재시작하여 변경 사항이 즉시 변경되도록 함
(스프링의 devTools가 생각나는 라이브러리이다.)
그리고 server.js를 실행하기 위해 아래 섹션을 추가하고 Dockerfile도 수정하자.
"scripts": {
"start": "nodemon server.js"
}
CMD ["npm", "start"]
컨테이너 중지 및 이미지 삭제 후 이미지를 재빌드하고, 컨테이너를 다시 실행해서 피드백 파일을 저장해보자.
나는 윈도우에서 WSL2를 사용해서 이미지를 재빌드하고 나서야 수정했던 로그가 나타났지만,
리눅스 시스템을 사용한다면 한참 전부터 'TEST' 로그가 뜨고, 'TEST!!!!'로 로그를 수정한 시점에서 수정한 로그로 나타날 것이다,,(참 빨리 알려주시내요 강사님😇😇)
💥 왜 윈도우는 불가능한 것인가
- WSL2를 사용할 때 파일을 결국 리눅스 시스템에 직접 저장해야 하기 때문
▶ 리눅스 파일 시스템의 어딘가에 저장되는 것 - 일반 윈도우 파일 시스템을 사용하는 경우 파일 변경 사항이 도커 컨테이너로 전파되지 않으므로 nodemon과 같은 툴이 적용되지 않는 것
✅ -v 옵션을 사용하는 세 가지 방식
- 익명의 볼륨 생성
➡ 컨테이너가 제거되면 같이 제거
➡ 익명 볼륨을 사용해서 컨테이너 간에 데이터를 공유할 수 없음
➡ 데이터를 저장하는 데 익명 볼륨을 사용할 수 없음
➡ 그러나 '-v'로 명명된 익명 볼륨은 컨테이너에 존재하는 특정 데이터를 잠그는 데 유용
(다른 모듈에 덮어 쓰여지는 것을 방지)
➡ 시간 절약 가능
➡ 컴퓨터에 폴더 생성(컨테이너 제거되면 같이 제거)
도커가 컨테이너 내부에 모든 데이터를 저장할 필요X
도커가 컨테이너 read-write 레이어 내부의 모든 데이터를 관리할 필요X
➡ 특정 데이터를 컴퓨터 파일 시스템에 아웃소싱 가능(성능, 효율성 ⬆) - 명명된 볼륨 생성
➡ Dockerfile에서 생성 불가능, -v 명령으로만 생성
➡ ':' 앞에 이름 지정
➡ 특정 컨테이너에 연결되지 않고 일반적으로 생성됨
➡ 컨테이너를 종료 및 제거해도 남아 있음
➡ 제거하려면 도커 CLI에 분리된 내장 명령으로 해야 됨
➡ 여러 컨테이너 간 데이터 공유 가능
➡ 컨테이너 종료 및 제거 전반에 걸쳐 데이터 저장 가능 - 컴퓨터의 폴더를 가리키는 절대 경로 지정(바인드 마운트)
➡ 특정 컨테이너에 국한되지 않음
➡ 컨테이너 종료 및 제거해도 남아 있음
➡ 제거하려면 실제 모든 로컬 컨텐츠를 제거해야 함(도커 명령으로 불가능)
➡ 재시작함으로써 동일한 컨테이너에서 재사용 가능
'log.info' 카테고리의 다른 글
[Spring Security] JWT Refresh Token (리프레시 토큰) (0) | 2024.06.20 |
---|---|
[Docker] Docker Compose (0) | 2024.06.18 |
[Redis] 데이터 추가 및 관리 명령어 (0) | 2024.06.17 |
[Redis] Redis에 대해 알아보자 ! (0) | 2024.06.16 |
[Docker] 데이터 관리 및 볼륨 (0) | 2024.06.14 |