[섹션 3] 데이터 관리 및 볼륨으로 작업하기
-------------------------------------------------- 목차 ----------------------------------------------------
- 데이터
- 애플리케이션 분석
- Anonymous Volume vs Named Volumes
- 명명된 볼륨
- 바인드 마운트
- 패키지 nodemon
- 읽기 전용 볼륨
- 볼륨 명령어(확인, 생성, 검사, 삭제)
- .dockerignore
- 환경변수
- 환경변수 파일 .env
- 빌드 인수
[실습 1] Docker 컨테이너 내부 데이터 생성
[실습 2] 명명된 볼륨
[실습 3] 바인드 마운트
[실습 4] nodemon
[실습 5] 빌드 인수
-----------------------------------------------------------------------------------------------------------
● 데이터
ㄱ. Application
ㄴ. Temporary App Data (임시적)
ㄷ. Permanent App Data (영구적)
=> 볼륨에 데이터 저장
=> 컨테이너가 종료 및 삭제되어도 저장되어야 하는 데이터
=> 애플리케이션 업데이트를 가능하게 한다.
● 애플리케이션 분석

=> temp, feedback 폴더는 비어있다.
1) temp 폴더에 feedback과 함께 임시 생성된 파일 저장
2) feedback 폴더에 파일 유무 확인
3) 아직 존재하지 않으면 파일 복사
=> feedback: 영구적인 저장소, temp: 임시 저장소
(+) package.json: 애플리케이션의 종속성을 포함하는 파일
=> npm install 명령어를 통해 package.json에 언급된 모든 종속성 설치
[실습 1] Docker 컨테이너 내부 데이터 생성
1) 이미지 및 컨테이너 생성
---------------------------------------------------------------
FROM node
WORKDIR /app
COPY package.json .
RUN npm install
COPY . .
EXPOSE 80
CMD [ "node", "server.js" ]
---------------------------------------------------------------
> docker build -t feedback-node .
> docker run -p 3000:80 -d --name feedback-app feedback-node
2) localhost:3000 접속
3) 텍스트 파일 생성

=> 텍스트 파일은 Docker 컨테이너 내부에 생성된다.
(오버라이트 X. 즉, 동일 파일 제목 사용 불가)
4) 생성 확인

5) 로컬 파일 시스템 확인
=> 아무런 변화 없다.
! 컨테이너, 이미지, 로컬 파일 시스템 간에는 어떠한 연결도 존재하지 않는다 !
6) 컨테이너 중지 후 재시작 및 재접속
=> 기존에 생성한 텍스트 파일 존재한다.
7) 컨테이너 삭제 후 재접속

=> 기존에 생성한 텍스트 파일이 존재하지 않는다.
● Anonymous Volume vs Named Volumes
ㄱ. Anonymous Volume: 컨테이너가 존재하는 동안에만 존재
---------------------------------------------------------------
...
VOLUME ["/app/feedback"] // 컨테이너 내부 위치
...
---------------------------------------------------------------
ㄴ. Named Volumes: 컨테이너가 삭제한 이후에도 존재
● 명명된 볼륨
: Docker가 인식하는 호스트 머신에 존재하는 폴더로서 Docker 컨테이너 내부 폴더에 매핑
=> 컨테이너 내부 폴더를 컨테이너 외부 폴더에 연결할 수 있다.
=> 내부 폴더와 외부 폴더의 변경 사항은 상호작용하여 반영할 수 있다.
=> 즉, 컨테이너가 종료된 후에도 볼륨과 볼륨 내부에 존재하는 데이터는 존재한다.
=> 단, 로컬 호스트 머신상의 경로를 알지 못한다.
즉, 컨테이너를 종료시킨 이후, 새로운 컨테이너를 생성 시 기존 데이터 유지 위해 사용한다.
또한, 하나의 컨테이너에 종속되지 않고 여러 컨테이너에 연결할 수 있으므로,
여러 컨테이너 간에 데이터를 공유하는 것이 가능하도록 한다.
=> 모든 볼륨은 Docker에 의해 관리된다.
(컨테이너가 생성될 때 자동으로 생성될 수 있다는 것이 Docker에 의해 관리된다는 것이다.)
[실습 2] 명명된 볼륨
1) 이미지 생성
> docker build -t feedback-node:volumes .
2) 명명된 볼륨을 포함한 컨테이너 생성
> docker run -p 3000:80 -d --name feedback-app -v feedback:/app/feedback feedback-node
// 볼륨 이름:/컨테이너 내부 위치
3) 생성된 볼륨 확인

4) localhost:3000 접속 및 텍스트 파일 생성


5) 컨테이너 삭제

=> 컨테이너를 삭제한 이후에도 볼륨이 존재한다.
6) 컨테이너 재생성
> docker run -p 3000:80 -d --name feedback-app -v feedback:/app/feedback feedback-node
7) 텍스트 폴더 확인

● 바인드 마운트
=> 로컬 호스트 머신 상의 경로이며 컨테이너 내부 경로에 매핑된다
따라서, 로컬 호스트 상의 경로를 인식할 수 있다.
=> 소스코드를 스냅샷(이미지)에서 복사하는 것이 아니라 바인드 마운트에서 복사 할 수 있다.
=> 영구적이고 편집 가능한 데이터에 적합하다.
=> 하나의 컨테이너에 종속되지 않는다.
=> 바인드 마운트 데이터는 실제 호스트 머신에서 삭제해야 한다.
즉, 변경된 소스코드를 이미지 재빌드를 거치지 않고 바로 컨테이너에 적용하기 위해 사용한다.
[실습 3] 바인드 마운트
1) 컨테이너 및 바인드 마운드 생성
> docker run -p 3000:80 -d --rm --name feedback-app -v feedback:/app/feedback
-v "/Users/yooyijun/Desktop/Docker/Section 3/data-volumes-01-starting-setup:/app" -v /app/node_modules feedback-node:volumes
// 로컬 호스트 머신 상의 절대 경로:/컨테이너 내부 위치
// node_modules: npm install 명령어로 생성된 디폴트 폴더
=> 익명 볼륨은 컨테이너에 이미 존재하는 특정 데이터를 잠그기 위해 활용된다.
즉, 외부 경로보다 컨테이너 내부 경로의 우선 순위를 높이기 위해 사용한다.
Dockerfile에서도 생성 가능하다.
(+) 상위 폴더 존재해야한다.

(+) 바로 가기 경로
(Mac/Linux) -v $(pwd):/app
(Windows) -v "%cd%":/app
2) localhost:3000 접속 및 확인

3) feedback.html 파일 수정 후 재로드

=> 변경된 내용이 반영된 것을 확인할 수 있다.
● 패키지 nodemon
: 파일 시스템을 감시하여 파일이 변경될 때마다 노드 서버를 다시 시작하는 패키지
즉, 개발 중 변경 사항이 즉시 반영되도록 한다.
=> server.js 파일이 변경된 경우, 재로드해도 적용되지 않는다. server.js 는 노드 런타임에 의해 실행되기 때문이다.
따라서 컨테이너 중지 후 재시작해야한다. 이러한 문제점을 개선하기 위해 패키지 nodemon을 사용한다.
------------------------- package.json --------------------------
...

...

--------------------------- Dockerfile ----------------------------
FROM node
WORKDIR /app
COPY package.json .
RUN npm install
COPY . .
EXPOSE 80
CMD [ "npm", "start" ]
---------------------------------------------------------------------
[실습 4] nodemon
1) 기존 컨테이너 및 이미지 삭제
2) package.json, Dockerfile 변경 후 이미지 빌드 및 컨테이너 생성
3) localhost:3000 접속 및 파일 생성
4) server.js 내용 변경
5) localhost:3000 접속 및 파일 생성
6) 로그 확인
> docker logs feedback-app

=> server.js 변경 사항 적용된 것을 확인할 수 있다.
(단, WSL2 제외)
(+) temp 폴더를 익명 볼륨에 매핑하기
------------- Dockerfile --------------
...
VOLUME ["/app/temp"]
...
-----------------------------------------
or
> docker run -p 3000:80 -d --rm --name feedback-app -v feedback:/app/feedback
-v "/Users/yooyijun/Desktop/Docker/Section 3/data-volumes-01-starting-setup:/app" -v /app/temp
-v /app/node_modules feedback-node:volumes
● 읽기 전용 볼륨
=> 컨테이너에서 로컬 시스템 파일을 변경할 수 없어야하기 때문에 바인드 마운트를 읽기 전용 볼륨으로 사용한다.
> docker run -p 3000:80 -d --rm --name feedback-app -v feedback:/app/feedback
-v "/Users/yooyijun/Desktop/Docker/Section 3/data-volumes-01-starting-setup:/app:ro" -v /app/temp -v /app/node_modules feedback-node:volumes
● 볼륨 명령어
ㄱ. 확인
> docker volume ls
ㄴ. 생성
> docker volume create <-볼륨 이름->
ㄷ. 검사
> docker volume inspect <-볼륨 이름->
ㄹ. 삭제
> docker volume rm <-볼륨 이름->
> docker volume prune // 전체
=> 연결된 컨테이너 중지 및 삭제 후 삭제 가능하다.
(+) Dockerfile COPY . .
: 프로덕션용 스냅샷 컨테이너를 생성하는 옵션
● .dockerignore
: COPY 명령으로 복사해서는 안되는 폴더와 파일 지정
-----------------------------------------
node_modules
Dockerfile
.git
-----------------------------------------
● 환경변수
-------------- server.js ----------------
...
app.listen(process.env.PORT);
------------- Dockerfile --------------
...
ENV PORT 80
EXPOSE $PORT
...
-----------------------------------------
> docker run -p 3000:8000 --env PORT=8000 -d --rm --name feedback-app
-v feedback:/app/feedback -v "/Users/yooyijun/Desktop/Docker/Section 3/data-volumes-01-starting-setup:/app:ro" -v /app/temp -v /app/node_modules feedback-node:volumes
=> 포트번호를 변경하기 위해 이미지를 재빌드할 필요 없어진다.
● 환경변수 파일 .env
-----------------------------------------
PORT=8000
-----------------------------------------
> docker run -p 3000:8000 --env-file ./.env -d --rm --name feedback-app
-v feedback:/app/feedback -v "/Users/yooyijun/Desktop/Docker/Section 3/data-volumes-01-starting-setup:/app:ro" -v /app/temp -v /app/node_modules feedback-node:volumes
=> 서로 다른 모드, 구성에서 하나의 동일한 이미지를 기반으로 하나의 동일한 컨테이너를 실행을 가능하게 한다.
● 빌드 인수
=> Dockerfile에 다양한 값을 플러그인((plug in): 끼워넣기) 하거나 하드 코딩 하지 않고도,
이미지를 빌드할 때 다른 값을 플러그인 할 수 있다.
즉, 이미지를 빌드할 때 변경되지 않은 동일한 하나의 Dockerfile을 기반으로 하여
다른 디폴트 값으로 여러번 이미지를 빌드할 수 있다.
-----------------------------------------
RUN npm install
...
ARG DEFAULT_PORT=80
ENV PORT $DEFAULT_PORT
-----------------------------------------
=> ARG는 컨테이너가 시작될 때 실행되는 런타임 명령
[실습 5] 빌드 인수
> docker build -t feedback-node:web-app .
> docker build -t feedback-node:dev --build-arg DEFAULT_PORT=8000 .
=> 다른 빌드 타임 인수를 사용하여 다른 태그로 이미지를 빌드한 것
즉, 동일한 Dockerfile을 사용하여 서로 다른 포트를 사용하는 서로 다른 두개의 이미지를 만든 것