본문 바로가기
2. 우당탕탕 개발자/2-2. 상세 노트

Docker volume & compose

by Little Monkey 2021. 7. 15.
반응형

Docker volume & compose

도커 파일 작성법과 도커 볼륨과 컴포즈에 대해 정리하겠습니다. 인프런의 따라하며 배우는 도커와 CI 환경 강의를 듣고 있는데요(강추). 그동안 프론트엔드 CSS강의 듣다가 이 강의로 돌아오니 모든 내용이 새롭습니다. 역시 익숙하지 않은 내용은 짧은 텀으로 고반복 해줘야 하는게 진리입니다. 복습하고 강의를 듣다가 모르는 부분은 도커 공식사이트를 참조하며 추가했습니다. 도커는 배우면 배울 수록 신기하고, 사람들 마다 다른 컴퓨터 환경에서도 돌아갈 수 있도록 판을 짜준다는 점이 매력적입니다.

 


docker file 작성법 & port mapping

FROM node:10
WORKDIR /usr/src/app
COPY package.json ./
RUN npm install
COPY . .
EXPOSE 8080
CMD ["node", "server.js"]

 

WORKDIR는 새로 생성될 앱의 디렉토리를 지정해줍니다. 일반적으로 다른 시스템 필수 폴더들과 섞이지 않도록 다른 폴더 안에 넣어줍니다. COPY는 현재 local 파일을 도커의 컨테이너로 복사해주는 역할 입니다. 폴더 전체를 카피하고 싶다면 ./ ./ 라고 하면 됩니다. EXPOSE는 어떤 포트에 해당 server.js를 띄울 것인지를 설정해주는 곳입니다.

 

위의 파일에서 COPY를 2번 실행하는데요. 그 이유는 package.json 의 내용이 변화하지 않고, 단순히 server.js 의 내용만 수정되었을 때, 굳이 package.json을 다시 카피해서 인스톨할 필요는 없기 때문입니다. 컨테이너 cache에서 변화한 패키지 내용이 없으면 RUN부분을 반복 실행하지 않고, 캐시에서 꺼내다 쓰기 때문에 아래의 예시보다 훨씬 효율적입니다.

 

FROM node:10
WORKDIR /usr/src/app
COPY . .
RUN npm install
EXPOSE 8080
CMD ["node", "server.js"]

 

이 경우에는 server.js만 수정되어도 package.json도 함께 다시 다운받고, npm install 되기 때문에 위의 예제보다 비효율적입니다.

 

 

docker run -p 5000:8080 image_name

도커클라이언트야/만들고실행해라/포트를 대응시켜서 /5000:8080/ 그 이미지를

 

도커로 서버를 띄울 때, 내가 작업하는 로컬 컴퓨터의 포트와 컨테이너의 포트가 mapping 저절로 되는 것이 아닙니다. 따라서 로컬 네트워크 포트와 컨테이너 포트를 이렇게 대응할 것이라고 알려주어야 합니다.그래야 서버를 띄운 후 http://localhost:5000했을 때 내가 의도한 대로 서버 화면을 마주할 수 있게 됩니다. 5000과 8080은 내가 원하는 포트 넘버로 변경 가능합니다.

 

 


 

docker volume

 

도커는 실행중인 컨테이너에서 생생되고 수정되는 데이터가 어디에 저장되는지에 따라 bind mountsvolume으로 옵션이 나눠집니다. 일반적으로 컨테이너가 멈추면, 그 안에 데이터도 날아가버립니다(데이터 휘발성). .따라서 오랫동안 가지고 있어야 하는 지속적인 데이터들은 컨테이너 안이 아닌 호스트에 저장하는게 안전합니다. 또한 어떤 데이터들은 여러 컨테이너가 공유해야되는 경우도 있는데, 컨테이너 안의 데이터는 컨테이너 공유가 어렵기 때문에 위의 두 방식을 이용하여 데이터를 공유할 수 있습니다.

 

바인드 마운트와 볼륨은 작동하는 방식은 비슷합니다. 호스트 머신의 파일시스템안에 데이터를 저장하는데, docker전용을 두느냐/안 두느냐에 따라 볼륨/바운드 마운트로 나뉩니다. 볼륨의 경우 도커 전용의 스페이스를 둠으로써 관리성도 높아지고, 호스트 머신의 시스템 파일에 저장되는 일을 막을 수 있으니 훨씬 더 효율적인 느낌이 듭니다. 따라서 현 도커 체제에서는 bind mounts보다는 호스트에 저장하는 volume을 더 선호합니다.

 

볼륨을 이용하여 컨테이너에 필요한 파일을 매번 COPY가 아닌 mapping하게 만들 수 있습니다. 지금까지는 COPY를 이용해서 컨테이너에 필요한 파일을 컨테이너로 복사하여 사용했는데, 변화 내용이 생길 때마다 매번 이미지를 빌드해서 실행시키는 것은 효율적이지 않습니다. 따라서 컨테이너에 필요하지만, 자주 변화되는 파일의 경우 로컬 파일을 복사 아닌 참조(mapping)해서 변화 내용을 바로 반영할 수 있게 합니다. (기업에선 보안의 이유로 폴더 대 폴더로 참조가 아닌 파일 대 파일로 하는 경우도 있다고 합니다)

 

docker run -p 5000:8000 -v /usr/src/app/node_modules -v $(pwd):/usr/src/app image_id

 

도커야 / 실행해라 / 포트매핑을 하면서/로컬5000:컨테이너8000 포트로 / 해당내용은 참조하지 말고 / 다음 위치에서 참조해라 / 그 이미지를

 

보통은 로컬 호스트에서 npm install을 굳이 할 필요가 없으니 그 때 부산물로 생기는 node_modules/파일도 로컬 호스트에 존재하지 않습니다. 따라서 도커 클라이언트에게 그 폴더는 없으니 참조하지 말라고 미리 언질을 줘야 합니다. $(pwd)는 현재 위치를 말합니다.

 

docker compose

 

docker의 컨테이너는 기본적으로 분리되어 있습니다. 컨테이너를 관통하는 커넬은 컨테이너 안에서 다른 컨테이너와 연결하기 위한 용도는 아닙니다. 그러나 때로는 하나의 앱을 실행시킬 때, 서버 따로 클라이언트 따로 컨테이너를 두고, 컨테이너를 연결시켜야 할 때가 있는데요. 그 때가 도커 컴포즈가 필요한 순간입니다. 이처럼 docker compose는 여러개의 컨테이너를 둔 도커 애플리케이션을 실행할 때 유용합니다.

 

필요한 설정들을 docker-compose.yml파일에 적어둡니다.

 

version: "3.9"
services:
  web:
    build: .
    ports:
      - "5000:5000"
    volumes:
      - .:/code
    environment:
      FLASK_ENV: development
  redis:
    image: "redis:alpine"

 

도커 버전을 위에서 언급해주고, 어떤 서비스를 사용할지 인덴트(들여쓰기)에 주의하며 작성해줍니다. 여기 예제는 webredis 두가지를 동시에 사용하려고 하는군요. web의 volumes: - .:/code 를 통해서 /code의 내용이 변화하면 변화된 내용을 즉시 참조해서 이미지를 재 빌드하지 않고 화면에 반영됩니다. environment는 환경 변수를 적어줍니다.

 

 

docker-compose up -d

 

여기서의 -d 플래그는 detached mode (<->foreground)의 약자입니다. 해당 도커의 내용이 터미널과 연결될 필요가 없을 때 붙여줍니다. 해당 도커 컴포넌츠의 내용이 업데이트 되더라도 화면에 표기하지 않습니다.

 

 

$ docker run -d -p 8000:8000 node-docker

ce02b3179f0f10085db9edfccd731101868f58631bdf918ca490ff6fd223a93b

 

docker-compose commands

 

도커 컴포즈 파일이 완성되었다면, 터미널에 다음과 같은 명령어로 도커 컴포즈 파일을 실행할 수 있습니다.

 

docker-compose up

 

이미지 파일이 없을 때 빌드하고 실행합니다.

 

 

docker-compose up --build

 

이미지 파일이 존재하는데, 수정해서 다시 재빌드할 경우 다음과 같이 --build를 뒤에 붙여줍니다.

 

 

docker-compose down

 

도커 컴포즈를 종료합니다.

 

반응형

댓글