여러가지/Docker & AWS

[섹션 3] 데이터 관리 및 볼륨으로 작업하기

15June 2023. 11. 25. 15:41

-------------------------------------------------- 목차 ----------------------------------------------------

- 데이터

- 애플리케이션 분석

- 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을 사용하여 서로 다른 포트를 사용하는 서로 다른 두개의 이미지를 만든 것